# “Stateful” gotcha in pf(4)



## Incnis Mrsi (Jul 31, 2022)

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.


----------



## Incnis Mrsi (Jul 31, 2022)

Eventually found that formulating the route-to rule as

```
pass out route-to gif0 from $myv6_he to any no state
```
together with (already mentioned above)

```
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.


----------

