Score:1

iptables rules not working for allowing a specific IP

tz flag

I have a host with 2 network interfaces: wifi and site-site vpn (zerotier).

root@host:~# ifconfig wlp0s20f3
wlp0s20f3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.38  netmask 255.255.255.0  broadcast 192.168.1.255
        inet6 fe80::a098:2166:78af:d78d  prefixlen 64  scopeid 0x20<link>
        ether ac:12:03:ab:6e:31  txqueuelen 1000  (Ethernet)
        RX packets 1071869  bytes 1035656551 (1.0 GB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 911450  bytes 134092251 (134.0 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0


root@host:~# ifconfig ztklh3tu4b
ztklh3tu4b: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 2800
        inet 10.147.18.192  netmask 255.255.255.0  broadcast 10.147.18.255
        inet6 fe80::f8f6:d1ff:fe3d:4f09  prefixlen 64  scopeid 0x20<link>
        ether fa:f6:d1:3d:4f:09  txqueuelen 1000  (Ethernet)
        RX packets 8836  bytes 1146994 (1.1 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 667  bytes 281732 (281.7 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

I want to block all the traffic (both inbound and outbound) to this host except an IP behind the VPN. So I added following iptable rules:

iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
iptables -A INPUT -s 10.147.18.80 -j ACCEPT
iptables -A OUTPUT -d 10.147.18.80 -j ACCEPT

When I ping this 10.147.18.80, I am unable to do so. Here are the ping results:

PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
^C
--- 8.8.8.8 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3067ms

root@host:~# ping 10.147.18.80
PING 10.147.18.80 (10.147.18.80) 56(84) bytes of data.
^C
--- 10.147.18.80 ping statistics ---
6 packets transmitted, 0 received, 100% packet loss, time 5097ms

When I change the IP in the iptables rule to be something else like 8.8.8.8, everything works as expected, i.e. I cannot communicate with anything except 8.8.8.8.

Edit The following output of iptables -nvL shows the chains:

root@host:~# iptables -nvL
Chain INPUT (policy DROP 23 packets, 4560 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     all  --  *      *       10.147.18.80         0.0.0.0/0           

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy DROP 330 packets, 25776 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    8   672 ACCEPT     all  --  *      *       0.0.0.0/0            10.147.18.80         

The above output from iptables show that packets go out to the IP but no reply is received when the rules are in place.

Tcpdump on my host shows the same behavior:

tcpdump: data link type LINUX_SLL2
tcpdump: listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes


13:28:32.323064 ztklh3tu4b Out IP (tos 0x0, ttl 64, id 17342, offset 0, flags [DF], proto ICMP (1), length 84)
    10.147.18.192 > 10.147.18.80: ICMP echo request, id 61, seq 1, length 64
13:28:33.330145 ztklh3tu4b Out IP (tos 0x0, ttl 64, id 17567, offset 0, flags [DF], proto ICMP (1), length 84)
    10.147.18.192 > 10.147.18.80: ICMP echo request, id 61, seq 2, length 64
13:28:34.354178 ztklh3tu4b Out IP (tos 0x0, ttl 64, id 17694, offset 0, flags [DF], proto ICMP (1), length 84)
    10.147.18.192 > 10.147.18.80: ICMP echo request, id 61, seq 3, length 64
13:28:35.378135 ztklh3tu4b Out IP (tos 0x0, ttl 64, id 17714, offset 0, flags [DF], proto ICMP (1), length 84)
    10.147.18.192 > 10.147.18.80: ICMP echo request, id 61, seq 4, length 64

Tcpdump on 10.147.18.80 does not show any inbound ICMP echo request from 10.147.18.192. What could have gone wrong?

Score:0
in flag

If you are using a VPN client on this host to create the second interface, don't forget to also allow connections to the VPN server, otherwise your local ip 10.147.18.192 won't be reachable anymore.

You'll need to at least allow outbound and inbound traffic to/from the VPN server on interface wlp0s20f3 :

iptables -I OUTPUT -d $vpn_server_ip -p $proto --dport $vpn_port -j ACCEPT
iptables -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

$proto will be udp or tcp, and $vpn_server_ip:$vpn_port the ip address or range and port of the VPN server(s)

I can't help much to guess theses values, but your VPN documentation, or tcpdump/wireguard with a working established connection to the VPN tunnel should give you these informations.

Score:0
ru flag

These two commands you mention in your question:

iptables -A INPUT -s 10.147.18.80 -j ACCEPT
iptables -A OUTPUT -d 10.147.18.80 -j ACCEPT

They append those rules to the end of the chains. -A option appends the rule to the end. If you use -I option you will put the rule to the top of the chain.

The issue here is that you probably have already have a DROP or REJECT rule, before the ACCEPT the rule in one of the chains that drops the traffic before it reaches the end of the chain. Like for instance a rule that drops traffic to or from a whole subnet that contains the IP 10.147.18.80.

If you have a rule in a chain that drops/rejects traffic to that IP, or from that IP depending if it is a INPUT or OUTPUT chain, before the ACCEPT rule, then whether the rule specifies just that IP or the whole subnet, traffic gets dropped and all other rules in the chain are not processed any more.

DROP, REJECT, ACCEPT are terminating targets, once iptables matches that rule, it stops processing other rules in the chain, it doesn't proceed to the next rule.

Try

iptables -I INPUT -s 10.147.18.80 -j ACCEPT
iptables -I OUTPUT -d 10.147.18.80 -j ACCEPT

This will put those rule on top of the chains so they are the first rules to be hit, and other rules won't be processed then for that traffic in those chains.

You can list all rules in a chain with something like

iptables -nvL

or if you want o view just specific chains

iptables -nvL INPUT 
iptables -nvL OUTPUT

EDIT

Given the output you pasted, and the fact you can ping if you change default actions to ACCEPT this doesn't seem to be the issue.

You can use something like tcpdump to see if the traffic is going any and being returned.

Command like this will give you all icmp packets being sent or received by the machine

tcpdump -nnvvi any icmp

If you get something like this in the output

10:13:48.866598 IP (tos 0x0, ttl 255, id 30625, offset 0, flags [DF], proto ICMP (1), length 84)
    10.147.18.192 > 10.147.18.80: ICMP echo request, id 26621, seq 4, length 64
10:13:48.867771 IP (tos 0x0, ttl 53, id 0, offset 0, flags [none], proto ICMP (1), length 84)
    10.147.18.80 > 10.147.18.192: ICMP echo reply, id 26621, seq 4, length 64

Then your ping packets are being sent out, and returned, but being rejected by some other rule.

You can check if you maybe have some other rules in other tables like nat or mingle table, if maybe some of the rules there are conflicting with the traffic.

iptables -t nat -nvL
iptables -t mingle -nvL

You can also see if the packets are going through ACCEPT rule in OUTPUT chain by number under pkts in the listing. If that number is increasing after you try to ping, but the number in INPUT chain stay 0 then the issue is with incoming traffic rules.

Also check your routes, with ip r command or something similar, if maybe the traffic is not exiting through the interface in same subnet so the source IP of returning packets maybe gets changed due to some NAT rules along the way.

Muhammad Saboor avatar
tz flag
In this context, it does not matter if I use -A or -I because we only have one rule (the rule to accept traffic from the specific IP). I am dropping the traffic by setting default policy (-P) which determines what happens to packet in case no rule is matched. We can also confirm this by printing the chains using `iptables -nvL`. Secondly, if that was the case, the case where I drop all the traffic except 8.8.8.8 should not have worked.
ru flag
if you flush all rules, or change the default policy to ACCEPT, are you able to ping the IP then, is the IP accessible
Muhammad Saboor avatar
tz flag
If I set INPUT and OUTPUT policies to ACCEPT, then I can ping the IP
ru flag
the packet count "pkts" in you output is 0 for both rules. when you ping the IP with those rules in place, does the packet count increase in INPUT chain, if it stays 0 in INPUT chain, then the issue is the rule in INPUT chain is not being hit, if it increase in INPUT but stays 0 in OUTPUT chain then the rule in OUTPUT chain is not being hit. Do you have rule in any other tables, iptables -nvL -t nat, iptables -nvL -t mangle
ru flag
it could be that the source IP on returning packets gets changed, check if the traffic is exiting and being returned with different IP with tcpdump or something similar
Muhammad Saboor avatar
tz flag
packet counter is increasing in OUTPUT chain but not increasing in INPUT chain. tcpdump also shows the packets going out but no reply is received. I can only see ICMP echo requests in its output. Also before starting, I had flushed all the chains and even deleted user-defined chains in all the iptables (filter, nat, raw, security, mangle).
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.