Dear Colleagues,
I'm trying to figure out the difference between floating and if-bound states. Let's consider a simple ruleset with just 2 rules: root@fw:~ # pfctl -vvs rules No ALTQ support in kernel ALTQ related functions disabled @0 block return in on dmz all [ Evaluations: 2282 Packets: 1022 Bytes: 85848 States: 0 ] [ Inserted: uid 0 pid 822 State Creations: 0 ] @1 pass in on inside all flags S/SA keep state [ Evaluations: 1771 Packets: 511 Bytes: 42924 States: 1 ] [ Inserted: uid 0 pid 822 State Creations: 1 ] root@fw:~ # Let's ping host 172.16.1.10 (attached to the "dmz" interface) from host 192.168.10.3 (attached to the "inside" interface) via the router. Echo requests from 192.168.10.3 to 172.16.1.10 match Rule 1 and are passed, and echo replies from 172.16.1.10 to 192.168.10.3 match Rule 0 and are blocked by the rule. However, pinging 172.16.1.10 from 192.168.10.3 creates the following "all" state: root@fw:~ # pfctl -vvs state No ALTQ support in kernel ALTQ related functions disabled all icmp 172.16.1.10:31234 <- 192.168.10.3:31234 0:0 age 00:12:08, expires in 00:00:10, 694:0 pkts, 58296:0 bytes, rule 1 id: 000000005df37f65 creatorid: 66d731d7 root@fw:~ # Why is this state not permitting the reversed packets (echo replies) from 172.16.1.10 to 192.168.10.3 incoming via the "dmz" interface? It is my understanding that with the default "state-policy=floating", reversed packets should be passed from 172.16.1.10 to 192.168.10.3, but it is not happening. This behaviour would be expected with "state-policy=if-bound", but with "state-policy=floating" shouldn't the states be global? What am I missing? -- Victor Sudakov, VAS4-RIPE, VAS47-RIPN 2:5005/49@fidonet http://vas.tomsk.ru/ |
[...]
> What am I missing? You're missing correct understanding of how states are handled in Pf. https://docs.oracle.com/cd/E37838_01/html/E60993/pfovw-rls.html#NWSECpfovw-passin -- End of message. Next message? |
In reply to this post by Victor Sudakov
Hello,
On Fri, Dec 13, 2019 at 02:23:38PM +0700, Victor Sudakov wrote: > Dear Colleagues, > > I'm trying to figure out the difference between floating and if-bound > states. Let's consider a simple ruleset with just 2 rules: > > root@fw:~ # pfctl -vvs rules > No ALTQ support in kernel > ALTQ related functions disabled > @0 block return in on dmz all > [ Evaluations: 2282 Packets: 1022 Bytes: 85848 States: 0 ] > [ Inserted: uid 0 pid 822 State Creations: 0 ] > @1 pass in on inside all flags S/SA keep state > [ Evaluations: 1771 Packets: 511 Bytes: 42924 States: 1 ] > [ Inserted: uid 0 pid 822 State Creations: 1 ] > root@fw:~ # > > Let's ping host 172.16.1.10 (attached to the "dmz" interface) from host > 192.168.10.3 (attached to the "inside" interface) via the router. > > Echo requests from 192.168.10.3 to 172.16.1.10 match Rule 1 and are > passed, and echo replies from 172.16.1.10 to 192.168.10.3 match Rule 0 > and are blocked by the rule. > > However, pinging 172.16.1.10 from 192.168.10.3 creates the following "all" state: > > root@fw:~ # pfctl -vvs state > No ALTQ support in kernel > ALTQ related functions disabled > all icmp 172.16.1.10:31234 <- 192.168.10.3:31234 0:0 > age 00:12:08, expires in 00:00:10, 694:0 pkts, 58296:0 bytes, rule 1 > id: 000000005df37f65 creatorid: 66d731d7 > root@fw:~ # > > Why is this state not permitting the reversed packets (echo > replies) from 172.16.1.10 to 192.168.10.3 incoming via the "dmz" interface? > > It is my understanding that with the default "state-policy=floating", > reversed packets should be passed from 172.16.1.10 to 192.168.10.3, > but it is not happening. > > This behaviour would be expected with "state-policy=if-bound", but > with "state-policy=floating" shouldn't the states be global? > > What am I missing? according to my understanding the state got created by inbound rule bound to 'inside' interface. Such state allows further packets: 192.168.10.3 -> 172.16.1.10 @ inbound 172.16.1.10 -> 192.168.10.3 @ outbound these are all packets, which are allowed by by state created by your 'pass in' rule. The forwarding essentially means the packets cross two interfaces. It means the PF running on your host sees the packet two times. The first time the packet is seen as inbound second time it is seen as outbound. For ICMP requests story goes like this: 192.168.10.3 -> 172.16.1.10 @ inbound 192.168.10.3 -> 172.16.1.10 @ outbound for ICMP replies: 172.16.1.10 -> 192.168.10.3 @ inbound 172.16.1.10 -> 192.168.10.3 @ outbound Now it should become obvious your firewall is missing state, which allows replies. There is no state, which allows inbound ICMP reply, and there is no such rule, which allows inbound ICMP rule. you need to adjust a policy bit: block return in on dmz all pass out on dmz all pass in on inside all the 'pass out' rule will create the state, which will allow inbound ICMP replies sent by hosts attached to dmz. I hope my explanation sounds clear. regards sashan |
In reply to this post by Igor Podlesny
Igor Podlesny wrote:
> [...] > > What am I missing? > > You're missing correct understanding of how states are handled in Pf. Obviously. Therefore I came here for enlightenment. > > https://docs.oracle.com/cd/E37838_01/html/E60993/pfovw-rls.html#NWSECpfovw-passin A good explanation, thank you for the link. It's a pity this explanation is not in the pf documentation (or is it?). However, the link above does not cover the difference between if-bound and global state policies. And from man pf.conf I made the conclusion (mistakenly) that with state-policy=floating, pf states would work like those in ipf/ipfw. Where is floating vs if-bound explained at length? -- Victor Sudakov, VAS4-RIPE, VAS47-RIPN 2:5005/49@fidonet http://vas.tomsk.ru/ |
In reply to this post by Alexandr Nedvedicky
Alexandr Nedvedicky wrote:
[dd] > > Why is this state not permitting the reversed packets (echo > > replies) from 172.16.1.10 to 192.168.10.3 incoming via the "dmz" interface? > > > > It is my understanding that with the default "state-policy=floating", > > reversed packets should be passed from 172.16.1.10 to 192.168.10.3, > > but it is not happening. > > > > This behaviour would be expected with "state-policy=if-bound", but > > with "state-policy=floating" shouldn't the states be global? > > > > What am I missing? > > according to my understanding the state got created by > inbound rule bound to 'inside' interface. Correct. That was my intention. > Such state allows > further packets: > > 192.168.10.3 -> 172.16.1.10 @ inbound > 172.16.1.10 -> 192.168.10.3 @ outbound Well, if the "pfctl -vvs state" showed those inbound and outbound markers, I would have probably suspected something. Unfortunately it presents the state as "all." > > these are all packets, which are allowed by by state created > by your 'pass in' rule. > > The forwarding essentially means the packets cross two interfaces. > It means the PF running on your host sees the packet two times. This is certainly true for pf rules. However, states are processed before rules, arent't they? > time the packet is seen as inbound second time it is seen as outbound. Seen by the rules, yes. But isn't the state table supposed to be checked *before* rules? > For ICMP requests story goes like this: > > 192.168.10.3 -> 172.16.1.10 @ inbound > 192.168.10.3 -> 172.16.1.10 @ outbound > > for ICMP replies: > 172.16.1.10 -> 192.168.10.3 @ inbound > 172.16.1.10 -> 192.168.10.3 @ outbound > > Now it should become obvious your firewall is missing state, which allows > replies. There is no state, which allows inbound ICMP reply, and there is > no such rule, which allows inbound ICMP rule. state table was global. Thank you for explaining. But then, what is the real difference betwttn if-bound and global? -- Victor Sudakov, VAS4-RIPE, VAS47-RIPN 2:5005/49@fidonet http://vas.tomsk.ru/ |
On Fri, 13 Dec 2019 at 22:00, Victor Sudakov <[hidden email]> wrote:
[...] > But then, what is the real difference betwttn if-bound and global? it's not global but rather "floating". man pf.conf says: "... floating States can match packets on any interfaces (the default). ..." IOW, floating state doesn't care which interface gets reply traffic, meanwhile if-bound does. This adds something like urpf-failed protection to the state table. -- End of message. Next message? |
In reply to this post by Victor Sudakov
On Fri, Dec 13, 2019 at 10:02 AM Victor Sudakov <[hidden email]> wrote: But then, what is the real difference betwttn if-bound and global? My understanding is that the difference applies when you have multiple paths to the same destination. For example, suppose you have a hardwired ethernet connection on em0, and you also have a wireless connection on iwn0, and you freely switch back and forth between them but use the same IP address on both. With if-bound states, switching from one interface to another would require you to restart all your already-in-progress sessions in order to re-establish states on the new interface. With floating states, a state established on one interface could be used directly if packets for that connection suddenly start appearing on a different interface. (this is a bad example, I know, because ARP issues would make it hard for an IP to float back and forth transparently, but a more proper example is harder to explain). It is a more useful setting on a router in a mesh network, where packets you're forwarding might move between different interfaces, as their path through the network is adjusted due to congestion or whatever. On an endpoint it's not particularly useful unless you want to allow sessions to migrate between different interfaces (all using the same IP address), which is a somewhat rare use case and one you would normally use trunk interfaces to support, rather than floating states. -ken |
In reply to this post by Victor Sudakov
Hello,
</snip> > > > For ICMP requests story goes like this: > > > > 192.168.10.3 -> 172.16.1.10 @ inbound > > 192.168.10.3 -> 172.16.1.10 @ outbound > > > > for ICMP replies: > > 172.16.1.10 -> 192.168.10.3 @ inbound > > 172.16.1.10 -> 192.168.10.3 @ outbound > > > > Now it should become obvious your firewall is missing state, which allows > > replies. There is no state, which allows inbound ICMP reply, and there is > > no such rule, which allows inbound ICMP rule. > > I see now. The state-policy=floating mislead me into believing that the > state table was global. Thank you for explaining. > > But then, what is the real difference betwttn if-bound and global? > assuming we talk about if-bound vs. floating state policy. you have to note the packet direction and interface as two different attributes to match. If you enable if-bound state match policy then PF continues to check for direction where packet is traveling (@inbounc vs. @outbound), furthermore PF also requires the packet to be seen on the interface, where PF saw packet, which has created the state. floating relaxes the requirement such interface is omitted, think of packet may match any/all interfaces, but must travel in expected direction. to be honest I don't know at top of my head, what is a good/typical use-case for if-bound state policy. I assume those set-ups must be rare/special. regards sashan |
[...]
> to be honest I don't know at top of my head, what is a good/typical > use-case for if-bound state policy. I assume those set-ups must be > rare/special. anti-spoofing. In case one suspects a spoofing attack can be carried out on some "side" network interface(s), leveraging if-bound state option allows to eliminate the threat. An example: https://www.openwall.com/lists/oss-security/2019/12/05/1 -- End of message. Next message? |
In reply to this post by Igor Podlesny
Igor Podlesny wrote:
> [...] > > But then, what is the real difference betwttn if-bound and global? > > it's not global but rather "floating". man pf.conf says: > > "... floating States can match packets on any interfaces (the default). ..." Of course I meant "floating", it's in the Subject line. > > IOW, floating state doesn't care which interface gets reply traffic, > meanwhile if-bound does. Is there yet another policy which doesn't care what direction the stateful traffic goes? The state table should work before the rules anyway. The documentation you gave at https://docs.oracle.com/cd/E37838_01/html/E60993/pfovw-rls.html#NWSECpfovw-passin mentions some "sloppy" option for the kept state, is not what I'm looking for? > This adds something like urpf-failed protection to the state table. And a bit of confusion too. -- Victor Sudakov, VAS4-RIPE, VAS47-RIPN 2:5005/49@fidonet http://vas.tomsk.ru/ |
In reply to this post by Alexandr Nedvedicky
Alexandr Nedvedicky wrote:
> > > > I see now. The state-policy=floating mislead me into believing that the > > state table was global. Thank you for explaining. > > > > But then, what is the real difference betwttn if-bound and global? > > > > assuming we talk about if-bound vs. floating state policy. > > you have to note the packet direction and interface as two different > attributes to match. > > If you enable if-bound state match policy then PF continues to > check for direction where packet is traveling (@inbounc vs. @outbound), > furthermore PF also requires the packet to be seen on the interface, > where PF saw packet, which has created the state. > > floating relaxes the requirement such interface is omitted, think of packet > may match any/all interfaces, but must travel in expected direction. > > to be honest I don't know at top of my head, what is a good/typical > use-case for if-bound state policy. I assume those set-ups must be > rare/special. Maybe to emulate the Cisco reflexive ACL behaviour? Frankly I'd like to see yet another state-policy, could be called "global" if you wish, which emulates ipfw/ipf bidirectional state behavior. -- Victor Sudakov, VAS4-RIPE, VAS47-RIPN 2:5005/49@fidonet http://vas.tomsk.ru/ |
In reply to this post by Igor Podlesny
Igor Podlesny wrote:
> [...] > > to be honest I don't know at top of my head, what is a good/typical > > use-case for if-bound state policy. I assume those set-ups must be > > rare/special. > > anti-spoofing. > > In case one suspects a spoofing attack can be carried out on some "side" network > interface(s), leveraging if-bound state option allows to eliminate the threat. Isn't "antispoof" for that already? > > An example: https://www.openwall.com/lists/oss-security/2019/12/05/1 -- Victor Sudakov, VAS4-RIPE, VAS47-RIPN 2:5005/49@fidonet http://vas.tomsk.ru/ |
On Sun, 15 Dec 2019 at 15:01, Victor Sudakov <[hidden email]> wrote:
> Igor Podlesny wrote: > > [...] > > > to be honest I don't know at top of my head, what is a good/typical > > > use-case for if-bound state policy. I assume those set-ups must be > > > rare/special. > > > > anti-spoofing. > > > > In case one suspects a spoofing attack can be carried out on some "side" network > > interface(s), leveraging if-bound state option allows to eliminate the threat. > > Isn't "antispoof" for that already? If we're talking about __new__ connections attempts it will work, of course. But we discussed "states" instead so far. Also being attentive enough (obviously) you'll find that "antispoof" __requires__ an interface name to function ("urpf-failed" doesn't but still you'll need to bypass state look-ups for this to be effective) meanwhile "if-bound" can be applied independently. -- End of message. Next message? |
Free forum by Nabble | Edit this page |