IPv4 + IPv6 (tunnelbroker.net) Router and PF Firewall

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

IPv6 Internet connectivity and prefix delegation address block is provided by IPv6 tunnel broker: https://tunnelbroker.net
Refer to this article: IPv6 via Hurricane Electric's Free IPv6 Tunnel Broker Service for additional information and how to sign up for and create this tunnel.

If you Internet Service Provider does provide you with IPv6 addresses via router advertisements or other mechanism, then refer to the configuration in this article: IPv4 + IPv6 Router and PF Firewall.


Configure System Startup

Add the following (below) to /etc/rc.conf:

Substitute IP addresses for your internal network as needed and modify the gif0 tunnel addresses to reflect the ones provided to you by tunnelbroker.net.

Optionally you can assign an additional IPv6 address to the system from the 'routed /64' block assigned to your tunnel. To accomplish this include and edit line: ifconfig_gif0_alias0="inet6 Routed /64 IP Address prefixlen 64" substituting Routed /64 IP Address with an IPv6 address from the 'routed /64' block assigned to your tunnel.

ifconfig_re1="inet netmask"
ifconfig_gif0="tunnel Client IPv4 Address Server IPv4 Address"
ifconfig_gif0_ipv6="inet6 Client IPv6 Address Server IPv6 Address prefixlen 128"
ifconfig_gif0_alias0="inet6 Routed /64 IP Address prefixlen 64" ipv6_defaultrouter="Server IPv6 Address" 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

NOTE: It is important to understand in this configuration that the re0 network interface is the IPv4 gateway, and the gif0 tunnel interface is the IPv6 gateway for Internet traffic. IPv4 and IPv6 interfaces will need to be secured separately with some IP address family specific firewall rules for the respective interfaces.

Edit /ect/pf.conf

#### Macros ####
int_if = re1
ext_if = "{ re0, gif0 }"
extv4_if = re0 extv6_if = gif0 # ICMP Types icmp_types = "{ echorep, unreach, squench, echoreq, timex, paramprob }" icmp6_types = "{ unreach, toobig, timex, paramprob, echoreq, echorep, neighbradv, neighbrsol, routeradv, routersol }" # Private Networks priv_nets = "{,,,, }" #### Options #### set block-policy drop set skip on lo0 # Scrub scrub in on $ext_if # NAT nat on $extv4_if from -> ($extv4_if) ### Block ### block log all # Antispoof antispoof log for $ext_if
block in log on $extv4_if from $priv_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 interfaces pass out on $extv4_if inet proto { tcp, udp, icmp } pass out on $extv6_if inet6 proto { tcp, udp, icmp6 } # IPv6 Over IPv4 Tunnel pass in on $extv4_if proto 41 from Server IPv4 Address pass out on $extv4_if proto 41 to Server IPv4 Address # Allow IPv6 fragments pass inet6 proto ipv6-frag # ICMP pass in on $extv4_if inet proto icmp all icmp-type $icmp_types pass in on $extv6_if inet6 proto icmp6 all icmp6-type $icmp6_types allow-opts # Inbound Services # pass in on $ext_if proto tcp to port http


Reboot the system and watch the console for any errors during startup.
Login and test the network ensuring that you can ping both IPv4 and IPv6 external Internet hosts.


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

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