Iptables, subnet rule overwriting ip rule
I want to DROP
all packet that come from the subnet 192.168.112.0/24
with destination 192.168.112.0/24
but I want to allow only a specific destination to be accessible (192.168.112.253
).
I am using the following rules, the first (DROP
) rule is working as expected dropping all packets but the second (ACCEPT
) rule is not allowing packets for the specific destination to pass.
iptables -I FORWARD -s 192.168.112.0/24 -d 192.168.112.0/24 -j DROP
iptables -I FORWARD -s 192.168.112.0/24 -d 192.168.112.253 -j ACCEPT
Is there any reason why the first rule (ACCEPT
) is being ignored ?
I’m not able to reproduce your problem.
I have a host at 172.17.0.2/16
. Initially, it can reach any host on the 192.168.1.0/24
network:
/ # ping -c1 192.168.1.1
PING 192.168.1.1 (192.168.1.1): 56 data bytes
64 bytes from 192.168.1.1: seq=0 ttl=63 time=0.350 ms
--- 192.168.1.1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.350/0.350/0.350 ms
/ # ping -c1 192.168.1.6
PING 192.168.1.6 (192.168.1.6): 56 data bytes
64 bytes from 192.168.1.6: seq=0 ttl=63 time=6.690 ms
--- 192.168.1.6 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 6.690/6.690/6.690 ms
If on the intervening router I add this rule:
iptables -I FORWARD -s 172.17.0.0/16 -d 192.168.1.0/24 -j DROP
Then the host is no longer able to reach any host on the 192.168.1.0/24
network:
/ # ping -c1 192.118.1.1
PING 192.118.1.1 (192.118.1.1): 51 data bytes
--- 192.118.1.1 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
But if I add the appropriate ACCEPT
rule:
iptables -I FORWARD -s 172.17.0.0/16 -d 192.168.1.1 -j ACCEPT
Then I have restored connectivity to 192.168.1.1
:
/ # ping -c1 192.168.1.1
PING 192.168.1.1 (192.168.1.1): 56 data bytes
64 bytes from 192.168.1.1: seq=0 ttl=63 time=0.484 ms
--- 192.168.1.1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.484/0.484/0.484 ms
While connections to other hosts on the 192.168.1.0/24
network continue to be blocked:
/ # ping -c1 192.168.1.6
PING 192.168.1.6 (192.168.1.6): 56 data bytes
--- 192.168.1.6 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
After adding both of those rules, the FORWARD
chain looks like:
# iptables -S FORWARD
-P FORWARD ACCEPT
-A FORWARD -s 172.17.0.0/16 -d 192.168.1.1/32 -j ACCEPT
-A FORWARD -s 172.17.0.0/16 -d 192.168.1.0/24 -j DROP
The main thing you missed is that you also need an ACCEPT
rule for replies from 192.168.112.253
to 192.168.112.0/24
to be allowed:
-I FORWARD -s 192.168.112.253 -d 192.168.112.0/24 -j ACCEPT
Both ACCEPT
rules need to be placed before (i.e., -I
later than) the DROP
rule, since 192.168.112.0/24
covers 192.168.112.253
, which means the traffics that you wished to be "whitelisted" will be covered by it. Therefore, if it is matched against first, the ACCEPT
rules will not have any effect.
The order among the two ACCEPT
rules themselves does not matter though, since they don’t "overlap" with each other.
There are two caveats with the approach adopted here by the way. First, as you can see, you’ll need two (ACCEPT
) rules for each "pair" of traffics. Second, it allows 192.168.112.253
to initiate connections to the 192.168.112.0/24
. (With that said, you may consider neither of them an actual problem.)
Often we simply have the following "stateful" rule that allows all replying traffics:
-I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
(To be precise, traffics of both directions will have the state of ESTABLISHED
except the very first one that initiates the connection. RELATED
is used for certain recognized replying traffics in which the port number pair is not just swapped but different from the original traffic. The ,
means "inclusive or", even though a traffic won’t be in both states at a time. Consider the info within the parentheses "AFAIK" though.)