IPv4 & IPv6 Router and PF Firewall

This article details how to configure a IPv4/IPv6 dual-stack Internet gateway router and secure it with PF.

The configuration requires that your Internet Service Provider already supports and is providing you with IPv6 Internet connectivity and addresses via Router Advertisement messages.

  • The system will be configured to work as a CPE (Customer Premises Equipment) which needs RA messages from the upstream network for network configuration and acts as a router for the LAN simultaneously. For more information about this kind of configuration, see RFC 6204.
  • The rc.conf statement ipv6_cpe_wanif="iface" causes sysctl variables net.inet6.ip6.rfc6204w3 and net.inet6.ip6.no_radr to be set to 1. This configures the specified "iface" to accept RA messages and the default router information in them, and configures the other interfaces to ignore default router information in any received RA messages, even if the ACCEPT_RTADV flag is set on those interfaces. See rc.conf(5) for more information.
  • Request from your ISP an IPv6 prefix delegation. This will be a /64 or /56 block of Internet routable IPv6 addresses you can assign to your LAN clients. Assign one of these addresses to the router's internal interface: Prefix Delegation IPv6 address

 

Configure System Startup

NOTE: The System Startup section is not 100% complete at the moment as it lacks the precise configuration to request a prefix delegation via DHCP. This can be accomplished by installing the isc-dhcp client (contained in port net/dual-dhclient) and correctly configuring the DHCP request sent to your ISP to also assign and reply with a /64 or /56 prefix delegation. The current information in this section can be adapted as needed and the firewall section that follows is 100% complete.

Configure the network interfaces, enable routing, and enable PF firewall by adding the following to /etc/rc.conf:

ifconfig_re0="SYNCDHCP"
ifconfig_re0_ipv6="inet6"
ipv6_cpe_wanif="re0"
ifconfig_re1="inet 192.0.2.1 netmask 255.255.255.0"
ifconfig_re1_ipv6="inet6 Prefix Delegation IPv6 address prefixlen 64"
gateway_enable="YES"
ipv6_gateway_enable="YES"

# PF
pf_enable="YES"
pf_rules="/etc/pf.conf"
pflog_enable="YES"
pflog_logfile="/var/log/pflog"

 

Configure the Firewall Rules

Edit /etc/pf.conf

# Macros #
ext_if = re0
int_if = re1

# ICMP types #
icmp_types = "{ echorep, unreach, squench, echoreq, timex, paramprob }"
icmp6_types = "{ unreach, toobig, timex, paramprob, echoreq, echorep, neighbradv, neighbrsol, routeradv, routersol }"

# Private and documentation example networks #
priv_nets = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8, 255.255.255.255/32 }"
doc_example_nets = "{ 2001:DB8::/32, 192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24 }"


# Options #
set block-policy drop
set skip on lo0

# Scrub #
scrub in on $ext_if

# NAT #
nat on $ext_if from 192.0.2.0/24 to any -> ($ext_if)


### Block ###
block log all

# Antispoof #
antispoof log for $ext_if
block in log on $extv4_if from $priv_nets
block in log from $doc_example_nets
block in log from { urpf-failed, no-route }


### Allow ###
# Allow all traffic on internal interface #
pass quick on $int_if

# Allow all traffic out on external interface(s) #
pass out on $ext_if

# Allow IPv6 fragments #
pass inet6 proto ipv6-frag 

# ICMP #
pass in on $ext_if inet proto icmp all icmp-type $icmp_types
pass in on $ext_if inet6 proto icmp6 all icmp6-type $icmp6_types allow-opts


### Inbound Services ###
# pass in on $extv4_if proto tcp to 192.0.2.2 port http
# pass in on $extv6_if proto tcp to 2001:db8::2 port http

NOTE: When specifying ingress allow rules it is important to create separate rules for IPv4 and IPv6 as well as specifying the exact destination addresses for the required server/service. This ensures that unwanted ingress IPv6 traffic is not inadvertently allowed to reach other destinations on your internal network.

 

After rebooting the system, check that all IP addresses were assigned and ensure that you have network connectivity to both IPv4 and IPv6 external Internet hosts.

tcpdump -netttti pflog0 can be used to monitor the firewall activity in real-time.

 

When both IPv4 and IPv6 connectivity are confirmed working you can begin assigning IPv6 addresses from your assigned prefix delegation routed /64 block.
rtadvd(8) - router advertisement daemon is a quick and easy way to automatically configure IPv6 addresses for your LAN systems and devices.

To install dual-stack DHCP servers for stateful address assignments, refer to: IPv4 & IPv6 ISC DHCP Server on a Dual-Stack Network

To install the dual-stack dhcp client port net/dual-dhclient, refer to: IPv4 and IPv6 Client Addresses via DHCP