[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: pf and statesfull filtering on a bridge
Daniel, thanks!
I'm wondering if you've tried to use "return-rst"/"return-icmp"
with pf filtering on bridge? I have a default deny policy for
tcp protocol with rules like:
1. block return-rst in log proto tcp all
2. block return-rst out log proto tcp all
When tcp packet gets blocked on normal interface (non-bridged),
it's blocked by rule #1, and rst packet is sent succesfully.
But in case of the bridge, it seems that rst packet gets blocked
by rule #2? Could it be the case?
Thanks,
-albertr
Daniel Hartmeier writes:
> Several people have asked about stateful filtering with pf for bridges,
> and I wasn't sure myself about what's possible until I actually tried it
> today :)
>
> Assume we want to build a stealth ethernet bridge that does stateful packet
> filtering using pf. First set up the bridge and verify it's working correctly:
>
> /etc/hostname.rl0
> up
>
> /etc/hostname.rl1
> up
>
> /etc/bridgename.bridge0
> add rl0 add rl1 up
>
> Now enable pf with an empty rule set (passing all packets by default), and
> observe how everything is still working.
>
> To better understand how pf sees the packets, we add these four rules:
>
> pass in log on rl0 inet proto icmp
> pass out log on rl0 inet proto icmp
> pass in log on rl1 inet proto icmp
> pass out log on rl1 inet proto icmp
>
> We send an echo-request (ping) from a host on the rl0 side of the bridge
> to a host on the rl1 side, and an echo-reply comes back. We see the following
> log entries:
>
> rule 0, pass in on rl0, icmp echo-request
> rule 3, pass out on rl1, icmp echo-request
> rule 2, pass in on rl1, icmp echo-reply
> rule 1, pass out on rl0, icmp echo-reply
>
> As you can see, each packet goes through pf twice. It comes in on one
> interface and goes out through the other.
>
> With pf (unlike ipf), we can actually address each of these cases, both
> directions on both interfaces.
>
> If we filter statefully, there's one thing to keep in mind: the states in
> the state table are sorted by a key which consists of the two address and
> port pairs of the connection. The order of these two pairs is relevant.
> If an outgoing packet from A to B creates state, pf will let pass outgoing
> packets from A to B and incoming packets from B to A. But it will still
> block outgoing packets from B to A and incoming packets from A to B. In
> a non-bridging case this is perfectly clear and obvious.
>
> But in our bridging case, the same packet goes through pf twice, once through
> each interface. And the order of the key pairs is different in both cases.
>
> There are two solutions. The first one is to create two states per
> connection, one for each direction, using two 'keep state' rules.
> I don't think anyone will want to do that. Especially since the second
> solution is very simple and elegant:
>
> From pf perspective, packets go through our bridge twice. If you look at
> either interface, you see exactly the same traffic, only the direction
> is reversed. Hence, we can ignore one interface and do all the filtering
> on the other one.
>
> Here's an example:
>
> # we want to filter on rl0, hence just pass anything on rl1.
> pass in quick on rl1 all
> pass out quick on rl1 all
>
> # as an example, we block eveything by default, and let pass only
> # icmp echo requests related replies (both directions, statefully).
> block in on rl0 all
> block out on rl0 all
> pass in on rl0 inet proto icmp all icmp-type echoreq keep state
> pass out on rl0 inet proto icmp all icmp-type echoreq keep state
>
> This works equally well for more complex rules. The general recipe is
> to pick one interface you want to filter on. Start with two rules
> that let pass anything on the other interface (quick). After that,
> filter only on the interface you picked.
>
> Regards,
> Daniel