PF PF not allowing IPv6 traffic

Hello,

I'm new to FreeBSD and loving it. The only thing I'm really struggling with is getting a good pf.conf.

Here's my attempt. Sadly I can't get it to allow IPv6 traffic. Can anyone help me with what I'm doing wrong?

Code:
vtnet0 = "vtnet0"
set skip on { lo0 lo1 }

# basic hardening
scrub in all fragment reassemble max-mss 1440
antispoof quick for $vtnet0

# block everything by default
block all

# only allow in 80, 443, and 34020 (for ssh)
#  allow this on IPv4
pass in inet proto { tcp udp } to port { https, http, 34020 }
#  and IPv6
pass in inet6 proto { tcp udp } to port { https, http, 34020 }

# only allow the server to connect out to these ports
pass out proto { tcp udp } to port { 22 53 80 123 443 465 27017 }

IPv4 works but I can't get the fireawall to allow traffic directed at the IPv6 address. I can ssh into my server at user@IP_4_ADDRESS but it doesn't allow any traffic when ssh'ing into user@IP_6_ADDRESS.

I love FreeBSD but PF has been a bit too powerful and overwhelming for me. I wish there were some clear examples out there for best practices for a web-server firewall. I'm afraid of leaving big security holes when I'm struggling so much to understand a basic pf.conf. Any help with a full working example pf.conf would be really appreciated.

Very strangely, when I restart the firewall with sudo pfctl -d and then sudo pfctl -e, the firewall allows IPv6 traffic for about 30 seconds with the firewall freshly running, and then it drops it again.
 
Ok, I found this on serverfault.com that mentioned the need to unblock ICMP6 router solicitation and adding this fixes it.

Code:
pass proto icmp
pass proto ipv6-icmp

Now IPv6 works. I wasn't aware of the need ICMP messages for IPv6 to work. But this strikes me as very permissive and I don't know what kind of traffic could all go through that. Any suggestions on what the bare minimum to allow IPv6 use would be? I also saw this answer but I don't understand everything that's going on there.

Is it a good idea just let all ICMP traffic in? This site, shouldiblockicmp.com talks about how many types of ICMP should be blocked but certain types of ICMP messages are necssary to good operation. But I don't understand how to allow just those types of traffic using pf. If anyone could help with a sane default pf.conf that would be great!

Should ICMP just be given a free pass?

Someone here said:

If you are blocking icmp for security then that is silly. If your kernel has vulnerability than can be exploited using icmp you are going to have bad time anyway.

Hidding network structure might be an option, but ipv6 enumeration is harder to di due to size of common network prefixes, and unless only should be done in most paranoid settings

UFW on Debian uses this set of rules in /etc/ufw/before.rules which seems more limited.

Code:
# drop INVALID packets (logs these in loglevel medium and higher)
-A ufw-before-input -m conntrack --ctstate INVALID -j ufw-logging-deny
-A ufw-before-input -m conntrack --ctstate INVALID -j DROP

# ok icmp codes for INPUT
-A ufw-before-input -p icmp --icmp-type destination-unreachable -j ACCEPT
-A ufw-before-input -p icmp --icmp-type time-exceeded -j ACCEPT
-A ufw-before-input -p icmp --icmp-type parameter-problem -j ACCEPT
-A ufw-before-input -p icmp --icmp-type echo-request -j ACCEPT

# ok icmp code for FORWARD
-A ufw-before-forward -p icmp --icmp-type destination-unreachable -j ACCEPT
-A ufw-before-forward -p icmp --icmp-type time-exceeded -j ACCEPT
-A ufw-before-forward -p icmp --icmp-type parameter-problem -j ACCEPT
-A ufw-before-forward -p icmp --icmp-type echo-request -j ACCEPT

# allow dhcp client to work
-A ufw-before-input -p udp --sport 67 --dport 68 -j ACCEPT

#
# ufw-not-local
#
-A ufw-before-input -j ufw-not-local

# if LOCAL, RETURN
-A ufw-not-local -m addrtype --dst-type LOCAL -j RETURN

# if MULTICAST, RETURN
-A ufw-not-local -m addrtype --dst-type MULTICAST -j RETURN

# if BROADCAST, RETURN
-A ufw-not-local -m addrtype --dst-type BROADCAST -j RETURN

# all other non-local packets are dropped
-A ufw-not-local -m limit --limit 3/min --limit-burst 10 -j ufw-logging-deny
-A ufw-not-local -j DROP

# allow MULTICAST mDNS for service discovery (be sure the MULTICAST line above
# is uncommented)
-A ufw-before-input -p udp -d 224.0.0.251 --dport 5353 -j ACCEPT

# allow MULTICAST UPnP for service discovery (be sure the MULTICAST line above
# is uncommented)
-A ufw-before-input -p udp -d 239.255.255.250 --dport 1900 -j ACCEPT

What would an equivalent pf ruleset be? I'm sorry, I'm not a networking expert and I don't fully understand all the details in the pf man pages. I really want to use FreeBSD but for those of us who aren't confident with an extremely fine-grained firewall setup it would be really, really nice to have a decent base ruleset like UFW rules above for a web server that we could build off of.
 
Make sure net.inet.ip.forwarding AND net.inet6.ip6.forwarding are set to 1:
Code:
% sysctl net | grep forward
net.inet.ip.forwarding: 1
net.inet6.ip6.forwarding: 1

Either by setting those sysctls in /etc/sysctl.conf or via gateway_enable *and* ipv6_gateway_enable in rc.conf(5)

I tripped over this myself... more than once... :rolleyes:
 
Thanks, but after I had IPv6 working by allowing all ICMP traffic, adding ipv6_gateway_enable in rc.conf broke it again. I'm also not using this server as a gateway, just as a destination web server.
 
I wasn't aware of the need ICMP messages for IPv6 to work.
No, it's ICMP6 you need to allow, not ICMP (that's IPv4).

 
No, it's ICMP6 you need to allow, not ICMP (that's IPv4).

Right, I now understand that it's ICMP6 that I need. But after a bunch of reading around I was thinking, well if it's generally a good/ok idea to enable all ICMP, why not just let it all through? Now my big question is about how much ICMP blocking is good practice? This old (2007) IETF memo suggests it's best to filter some of it (but I'm having getting pf to follow their recommendations because of the need to specify codes along with ICMP message types), and other people say that ICMP blocking is an old practice that's pretty much pointless. I don't know enough about it.

As this answer says :

Blocking ICMP is not only useless but most cases it is also harmful. There is several reason why you should not block ICMP if you are not absolute sure what you are doing and specially why you are doing.

It seems FreeBSD would be quite hardened against bad ping requests or ICMP-tunneling ? So is there a real reason to block ICMP other than lowering the surface area for DDoS attacks?
 
There are only a couple of ICMP types that I would block. You really want to allow certain ICMP types though, or else you might break path MTU discovery. You usually need this with VPNs.

ICMP6 is a different matter, it's required for NDP, you can think of this as equivalent to IPv4's ARP
 
There are only a couple of ICMP types that I would block. You really want to allow certain ICMP types though, or else you might break path MTU discovery. You usually need this with VPNs.

ICMP6 is a different matter, it's required for NDP, you can think of this as equivalent to IPv4's ARP
What are those "coulp of ICMP" types that you would reccomend blocking?
 
For ICMP (IPv4) I only allow ICMP echo request, port/destination unreachable, fragmentation needed and time-exceeded. The rest is just junk and not necessary.
 
 
Thanks. That's helpful but sadly the link to the complete pf.conf is dead, as well as the richer pf.conf example mentioned in the bibliography. It would be nice to have a good full sample config.
 
Back
Top