ESTABLISHED,RELATED - How to block NEW ?

Started by brunoc68, November 20, 2024, 06:27:55 PM

Previous topic - Next topic
Dear all,

I am using a MikroTik OpenVPN client which connects to an OPNSense OpenVPN server.
I have a PC named "A" on the client network and a PC named "B" on the server network.
I want B to be able to dialog with A, but I want to block all traffic from A to B that is initiated by A.

That was easy to do with iptables :
- traffic A->B initiated by B was catched by "--state RELATED,ESTABLISHED -j ACCEPT"
- traffic A->B initiated by A was catched by "--state NEW -j DROP"

I read on the different posts that with OPNSense it is actually default behaviour that when B is authorized to A, A can reply to B, and I could test it works well.

However, my issue is the following when one does step by step :
1. first, A pings B : there is no answer - correct
2. second, B pings A : it works - correct
3. but now, if A pings B, A gets replies - NOT CORRECT

Actually what happens is obviously the following :
- step 1 : there is no rule to accept traffic from A to B so there is no reply
- step 2 : there is a rule to accept traffic from B to A, so as default OPNSense tracks the state of the connexion and replies from A are accepted back to B
- step 3 : when, at that point, A initiates traffic to B, OPNSense uses the previous state of the connexion at step 2 and it accepts the traffic !

So, in case there is regular communication from B to A, an attacker could suddenly usurpate the IP address of A to attack B through the firewall.

How can one definitely block traffic from A to B that is initiated by A ?

Quote from: brunoc68 on November 20, 2024, 06:27:55 PM
I read on the different posts that with OPNSense it is actually default behaviour that when B is authorized to A, A can reply to B, and I could test it works well.

Correct, OPNsense is a stateful firewall.

Quote
However, my issue is the following when one does step by step :
1. first, A pings B : there is no answer - correct
2. second, B pings A : it works - correct
3. but now, if A pings B, A gets replies - NOT CORRECT

Actually what happens is obviously the following :
- step 1 : there is no rule to accept traffic from A to B so there is no reply
- step 2 : there is a rule to accept traffic from B to A, so as default OPNSense tracks the state of the connexion and replies from A are accepted back to B
- step 3 : when, at that point, A initiates traffic to B, OPNSense uses the previous state of the connexion at step 2 and it accepts the traffic !

Does it ? Can you share a packet trace of the scenario you tested ? (Interfaces: Diagnostics: Packet Capture).

Your example is about ping, which is ICMP, can you reproduce this with a TCP scenario also ?

Quote
So, in case there is regular communication from B to A, an attacker could suddenly usurpate the IP address of A to attack B through the firewall.

How can one definitely block traffic from A to B that is initiated by A ?

That is done by a default block rule in OPNsense, please share the packet trace to diag whats happening in your scenario.

November 21, 2024, 03:57:44 PM #2 Last Edit: November 21, 2024, 04:57:47 PM by meyergru
Quote from: brunoc68 on November 20, 2024, 06:27:55 PM
However, my issue is the following when one does step by step :
1. first, A pings B : there is no answer - correct
2. second, B pings A : it works - correct
3. but now, if A pings B, A gets replies - NOT CORRECT

You seem not to understand that - unlike with real stateful traffic like TCP - with ICMP traffic, there is no "state" other than a time period where traffic in the reverse direction was seen.

A established TCP connection is characterized by a quadruple of (src_ip, src_port, dst_ip, dst_port). Thus, you can actually determine which response packets are to be allowed. If a packet was observed with a different dst_port as sender, it would not be allowed, since it cannot be attributed to the existing connection.

With ICMP, this is different. There is no port, only an ICMP subtype. Other than that, there are only (src_ip, dst_ip). Thus, you can only decide based on "soft" factors ("related"), like if within the last few seconds, you saw ICMP traffic between both parties that might explain why another ICMP packet is seen (and being passed).

Try the same test on an iptables-based firewall and you will probably see the same result.
Or, retry step 3 of your test after some time has passed.

Intel N100, 4 x I226-V, 16 GByte, 256 GByte NVME, ZTE F6005

1100 down / 440 up, Bufferbloat A+

Quote from: meyergru on November 21, 2024, 03:57:44 PM
With ICMP, this is different. There is no port, only an ICMP subtype. Other than that, there are only (src_ip, dst_ip). Thus, you can only decide based on "soft" factors ("related"), like if within the last few seconds, you saw ICMP traffic between both parties that might explain why another ICMP packet is seen (and being passed).

Let's see the trace, OP is most probably hitting something similar as this:

https://forum.opnsense.org/index.php?topic=36152.msg176859#msg176859

As you already expained there's no state in ICMP buth there is relation based on sequence id, if these are non-unique you get the scenario as described. That's why it's interesting to see if this behaviour can also be seen with TCP (probably not).



There is a sequence number, correct, but since you can "smoke ping" and there is no foreseeable sequence in which packets get transmitted, you cannot decide based on the sequence number (or, in other words: even if you used something akin to a "catch range", it would be just as good as an abitrary time range).
Intel N100, 4 x I226-V, 16 GByte, 256 GByte NVME, ZTE F6005

1100 down / 440 up, Bufferbloat A+

Quote from: meyergru on November 21, 2024, 05:00:12 PM
There is a sequence number, correct, but since you can "smoke ping" and there is no foreseeable sequence in which packets get transmitted, you cannot decide based on the sequence number (or, in other words: even if you used something akin to a "catch range", it would be just as good as an abitrary time range).

You can't decide anything indeed, it's the "related" behaviour baked into the ICMP network code. As explained in the link above, if your infrastructure somehow sends all ICMP with id=0x0001 you get exactly the behaviour described by the OP. So you need to fix your infra (ie the sequence id's) in that case, not something your firewall (OPNsense et all) can fix.