Monday, March 23, 2026

Re: Stateless filtering for established states

On March 23, 2026 5:13:44 AM PDT, Subzero <unsignedsubzero@proton.me> wrote:
>Hello, hoping for some guidance here.
>Trying to build a firewall system on OpenBSD.
>
>It appears that PF has a fundamental design
>problem for high-security environments. When
>you allow creating new states for LAN -> WAN
>traffic, and subsequently need to filter the return
>packets, that is simply impossible.
>
>For example: you execute a traceroute and the
>middle hops have RFC1918 IPs. As a general
>rule of thumb, you should filter RFC1918 sources
>from your WAN side. Yet, there is no way to
>acommplish that through PF.
>
>One workaround I have found is that you can use
>a transit rdomain which is stateless - you can then
>filter per-packet and achieve the desired behavior.
>The caveat: increased CPU usage, less throughput.
>
>What is the established way to handle this on
>OpenBSD - if there is one at all?
I may be misunderstanding your specific case/question. But I assume you are using NAT? In that case you can for example use the quick rule to block inet/ranges and destination ports, or rules added to overload tables, placed above your nat-to rules in pf.conf. eg.

no_route_addrs = " { 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 100.64.0.0/10, 10.0.0.0/8, ... }"

table <badguys> persist

block in quick log on egress \
from $no_route_addrs to any
...
block in quick log on { whatever } inet \
proto tcp from any to any port 1337
block in quick log on {whatever} from <badguys> to any
...
<nat-rules> <keep/synproxy.modulate>-state (<rate-limit-stuff etc.>, overload <badguys> \
flush global)
...

The quick rules will be triggered regardless of {keep,modulate,synproxy}-states defined later on, including those applicable to NAT.

If you're doing something other than NAT / packet inspection etc. some specifics would help providing help.

- achaean

No comments:

Post a Comment