pf blocks IPv6 packets with source :: (unspecified) to ff02::16 regardless of matching pass/block rules with allow-opts (FreeBSD 15.1 / OPNsense 26.7)
support
### Environment
- OPNsense 26.7 (Xenial Xenops), FreeBSD 15.1 base
- Issue appeared immediately after upgrading from a prior release to 26.7
- Interface: VLAN-tagged interface (vlan02), IPv6 enabled via SLAAC/RA on that segment
### Description
IPv6 packets with source address `::` (unspecified) destined to `ff02::16`
(MLDv2-capable routers multicast address) are being blocked by the implicit
default-deny rule, with filter log reason `ip-option`, even though:
1. An explicit `pass` rule exists matching this exact traffic (interface,
direction, protocol ipv6-icmp, source ::, destination ff02::16) with
`allow-opts` and `keep state` enabled.
2. An explicit `block` rule (which per pf.conf(5) does not require
`allow-opts` to match packets containing IP options / IPv6 hop-by-hop
headers) was also tested in the same position, and also does not match.
3. `pfctl -vvsr` shows the rule being evaluated (`Evaluations` counter
increments) but never actually matched (`Packets: 0`).
4. The filter log entry for the blocked packet shows an empty `rulenr` and
`rid`, indicating the packet is falling through to the implicit default
deny without matching any user-defined rule at all — pass or block.
Other MLDv2 reports on the same interface, identical in every respect
except that they use a `fe80::...` link-local source instead of `::`, are
correctly matched by the same rules and pass without issue. This isolates
the problem specifically to the unspecified source address `::` in
combination with the IPv6 Hop-by-Hop Options header (Router Alert) used by
MLDv2.
This traffic is generated by hosts on the segment sending MLDv2 Listener
Reports during Duplicate Address Detection (RFC 4862), before a link-local
address is available — a normal and expected part of IPv6 address
configuration, not malicious or malformed traffic.
### Steps to reproduce
1. On an IPv6-enabled interface, observe a host performing address
configuration (e.g. reboot a client, or bring up a new VLAN client).
2. Capture with: `tcpdump -ne -i pflog0 ip6 and dst ff02::16`
3. Observe blocked packets with source `::`, reason `ip-option`, alongside
passed packets with `fe80::...` source, both using the same rule.
4. Attempt to explicitly permit or explicitly block source `::` traffic to
`ff02::16` with a dedicated quick rule — the packet still bypasses the
rule and hits the implicit block.
### Expected behavior
A pass or block rule matching interface, protocol, source `::`, and
destination `ff02::16` should be evaluated as matching, the same way it is
for `fe80::...` source packets, regardless of the presence of an IPv6
Hop-by-Hop Options header.
### Actual behavior
Packets with source `::` bypass all user-defined rules (pass and block
alike) and fall through to the implicit default-deny, logged with an empty
rule number and reason `ip-option`.
### Supporting data
- `pfctl -vvsr` output showing the relevant rule with Evaluations > 0 but
Packets: 0
- Filter log entry (JSON) showing `rid`/`rulenr` empty, `reason: ip-option`,
`src: ::`, `dst: ff02::16`
- tcpdump on pflog0 showing side-by-side pass (fe80::) vs block (::) for
identical MLDv2 report traffic
1 条评论