“Stateful” gotcha in pf(4)

The NetBSD FAQ on pf(4) states:
By storing information about each connection in a state table, PF is able to quickly determine if a packet passing through the firewall belongs to an already-established connection. If it does, it is passed through the firewall without going through ruleset evaluation.
Although it might be handy for firewalling proper, “passing without going through ruleset evaluation” is abysmally silly for routing.
Yesterday Ī̲ found that my system of rules, based on the Thread dual-homed-ipv6-via-freebsd-gateway-with-pf-4.82761, doesn’t work universally. Although it works for UDP, as well as outbound TCP, under some conditions it fails for inbound TCP. Namely, when an Internet host sends a SYN to a LAN host, it creates a state. And the reply (from a host in $myv6_he) “passes without going” through pass out route-to gif0 from $myv6_he to any, that is, ends in stf0 by default route and is eventually discarded.
Appending the pass in on gif0 from any to $myv6_he no state rule did not help.
Any ideas what to do now? FreeBSD has such thing as FIBs (see setfib(2)), but is it possible to assign a FIB to a forwarded connection, or to a specific packet? Currently FreeBSD 12.3, but Ī̲ may consider another version (or even OS) if could get rid of this stupidity.
 
Eventually found that formulating the route-to rule as
Code:
pass out route-to gif0 from $myv6_he to any no state
together with (already mentioned above)
Code:
pass in on gif0 from any to $myv6_he no state
mitigate the evil state effect.
But realistic rulesets are much more complex (than just few routing-related pieces), and surely stamping all relevant rules with these “no state” is neither elegant nor secure, so suggestions about fixing the thing reasonably are welcome.
 
Back
Top