PF with IPv6

Paul Mather paul at
Mon May 3 13:43:30 UTC 2021

On May 2, 2021, at 8:40 PM, Doug Hardie <bc979 at> wrote:

> On 1 May 2021, at 07:37, Paul Mather <paul at <mailto:paul at>> wrote:
>> On Fri, 30 Apr 2021 21:20:48 -0700, Doug Hardie <bc979 at <mailto:bc979 at>> wrote:
>>> Message: 3
>>> Date: Fri, 30 Apr 2021 21:20:48 -0700
>>> From: Doug Hardie <bc979 at <mailto:bc979 at>>
>>> To: FreeBSD Questions <freebsd-questions at <mailto:freebsd-questions at>>
>>> Subject: PF with IPv6
>>> Message-ID: <2CD4806C-F1A4-4DDE-8C2F-2B0A08EA2A18 at <mailto:2CD4806C-F1A4-4DDE-8C2F-2B0A08EA2A18 at>>
>>> Content-Type: text/plain;	charset=us-ascii
>>> FreeBSD 13-RELEASE.  I have a small test network setup and tried to block all IPv6 except those addressed to a specific address.  /etc/pf.conf contained:
>>> ext_if = "bge0"
>>> LAN3 = "2001:1000:0:3000::/64"
>>> pass in quick log on $ext_if proto ipv6 from $LAN3 to $LAN3
>>> block in log on $ext_if proto ipv6 from any to any
>>> Nothing got blocked.  pftop showed all zeros for both rules.  I then added at the end:
>>> pass in quick log on $ext_if proto icmp6 from $LAN3 to $LAN3
>>> block in log on $ext_if proto icmp6 from any to any
>>> A lot of stuff got blocked.  The log shows many entries like:
>>> 15:59:41.597632 rule 3/0(match): block in on bge0: (hlim 1, next-header Options (0) payload length: 32) fe80::120c:6bff:fe5d:4404 > ff02::1: HBH (rtalert: 0x0000) (pad1)(pad1) ICMP6, multicast listener query
>>> 	0x0000:  6000 0000 0020 0001 fe80 0000 0000 0000  `...............
>>> 	0x0010:  120c 6bff fe5d 4404 ff02 0000 0000 0000  ..k..]D.........
>>> 	0x0020:  0000 0000 0000 0001 3a00 0502 0000 0000  ........:.......
>>> 	0x0030:  8200 98aa                                ....
>>> Rule 3 is the block for ICMP6, but those are clearly IP6 packets that should have been blocked by rule 1. Is there a problem with IPv6 and pf?
>> It's not clear to me precisely what you are trying to achieve.  The "proto" keyword in PF rules refers to protocols in /etc/protocols.  Your rules appear to be targeting the specific case of filtering IPv6 encapsulated in IPv4.  I don't believe that is what you intend.
>> The more standard way in PF to block IPv6 vs IPv4 traffic is to use "inet" (IPv4) or "inet6" (IPv6) to target IPv4 or IPv6 packets.
>> Note, the last rule you added that you say did start blocking things is more typical of rules to block ICMP6.  Because you omit "inet" or "inet6" on the rule it will be applied to both IPv4 and IPv6 packets.  But, the "proto icmp6" part is specifically targeting ICMP6.
>> So, to summarise, use "inet" and "inet6" to select IPv4 and IPv6 and "proto" to select the protocol you want to target (e.g., "tcp", "udp", "icmp", "icmp6", etc.).  E.g., "pass in log quick on $ext_if inet6 from ..." to allow all IPv6 for the rule, or ""pass in log quick on $ext_if inet6 proto tcp from ..." to allow only IPv6 TCP traffic, etc.
> First, it appeared to me that since ipv6 is listed in /etc/protocols, that it could be used as a protocol.  However, after reading the man page again, I see where it wants family, not protocol.  With that change it does work.

The "ipv6" protocol in /etc/protocols (protocol 41) is an IPv6 transition protocol more commonly known as "6in4".  It is used by sites that have only IPv4 connectivity to tunnel IPv6 traffic using IPv4 packets.  The Hurricane Electric TunnelBroker uses 6in4 via protocol 41, and is a well-known way of getting IPv6 connectivity when your ISP doesn't provide native IPv6.

As you observe, the "ipv6" tunnelling protocol is not the same as the IPv6 address family (AF_INET6).

Glad you got it sorted out and working, though.



More information about the freebsd-questions mailing list