[FreeBSD]: Enable IPv6 (with router solicitation) with a PF firewall

Enabling IPv6 is straight forward in FreeBSD, there's a lot of tutorials handling the topic extensively.

The best documentation I encountered was - as usual - in the FreeBSD Handbook

However, I was not able to find a lot of information of IPv6 in combination with a pf (packet filter) firewall on FreeBSD. It took me quite some time to figure out how allow router solicitation and router advertisement messages in /etc/pf.conf. I found a useful blog post that helped me BSD PF IPv6 and IPv4 /etc/pf.conf Firewall Script, thanks a lot to the author!

Here's how I did it:

First of all, enable IPv6 by adding to your /etc/rc.conf:

ipv6_enable="YES"
ipv6_network_interfaces="em0"
ifconfig_em0_ipv6="inet6 accept_rtadv"
rtsold_enable="YES"
rtsold_flafs="em0"

Please note that your network interface may be named differently. Mine is called em0, please replace with the name of your external interface.

After that, allow IPv6 route solicitation and advertisements by adding the following lines to your /etc/pf.conf:

#Define the interfaces
ext_if = "em0"

#### IPv6 #######
# activate spoofing protection for all interfaces
block in quick from urpf-failed

# antispoof is a common special case of filtering and blocking. 
antispoof log quick for $ext_if inet6

# Try to block nmap scans
block in log quick on $ext_if inet6 proto tcp from any to any flags FUP/FUP

# Allow ping pong out
pass out on $ext_if inet6 proto icmp6 all icmp6-type echoreq keep state

# ND solicitation out
pass out on $ext_if inet6 proto icmp6 all icmp6-type {neighbradv, neighbrsol}

# ND advertisement in
pass in on $ext_if inet6 proto icmp6 all icmp6-type {neighbradv, neighbrsol}

# Router advertisement out
pass out on $ext_if inet6 proto icmp6 all icmp6-type routeradv 

# Router advertisement in
pass in on $ext_if inet6 proto icmp6 all icmp6-type routeradv 

# Router solicitation out
pass out on $ext_if inet6 proto icmp6 all icmp6-type routersol

# Router solicitation in
pass in on $ext_if inet6 proto icmp6 all icmp6-type routersol

# Allow Ping pong in
pass in on $ext_if inet6 proto icmp6 all icmp6-type echoreq
####### End of IPv6 ##########

Of course, you need to keep your existing PF settings and may need to add new rules for IPv6 traffic. This configuration is just about router soliticing that is required for auto-configuration of IPv6 addresses. Again a link to the excellent FreeBSD Handbook for more information about PF.