Score:1

Iptables blocks loopback interface but why?

eg flag

I am having trouble understanding why iptables is blocking my loopback interface traffic.

Here is the scenario:

  1. I set the default policy of the INPUT chain to DROP.
  2. I allow traffic to port 8080.
  3. My filter tables look like this (NAT and MANGLE tables are empty):
#Make the default policy of the INPUT chain DROP
root@debian10:~#iptables -P INPUT DROP

#Allow traffic to port 8080
root@debian10:~#iptables -A INPUT -p tcp --dport 8080 -j ACCEPT

#That how my filter tables looks like (NAT and MANGLE tables are empty)
root@debian10:~# iptables -L
Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere           tcp dpt:http-alt         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination 
  1. I start a SimpleHTTPServer with Python3 for testing purposes.
root@debian10:~# python3 -m http.server 8080 
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/)
  1. I check if the port is open from another PC in the LAN, and everything seems okay.
root@moxie:~# nc -z -v 192.168.122.107 8080
Connection to 192.168.122.107 8080 port [tcp/http-alt] succeeded!
  1. I try to check if the port is open from localhost, but the network filter drops the packets.
root@debian10:~# nc -z -v localhost 8080
localhost [127.0.0.1] 8080 (http-alt) : Connection timed out

When I changed the default policy of the INPUT chain back to ACCEPT, netcat was able to successfully connect from localhost to 127.0.0.1 on port 8080.

I cannot understand why the network filter is dropping the packets when I try to connect to localhost.

Score:0
cl flag
A.B

You're disabling replies for the local case, preventing a successful communication. Let's check both cases.

  • From remote (working case):

    • Query packet

      source: 192.168.122.2 port 12345
      destination 192.168.122.107 port 8080

      The filter/INPUT rule matches: packet accepted

    • Reply packet

      source: 192.168.122.107 port 8080
      destination: 192.168.122.2 port 12345

      The filter/OUTPUT rule accepts anything: packet accepted

    Communication works both ways

  • From local system to itself (doesn't work, replacing OP's localhost with 192.168.122.107, it's the same):

    • Query packet

      source: 192.168.122.107 port 12345
      destination: 192.168.122.107 port 8080

      • emitted first: filter/OUTPUT accepts anything: packet accepted
      • packet is looped back through the lo interface
      • received back: filter/INPUT matches: packet accepted
  • Reply packet

    source: 192.168.122.107 port 8080
    destination: 192.168.122.107 port 12345

    • emitted first: filter/OUTPUT accepts anything: packet accepted
    • packet is looped back through the lo interface
    • received back: filter/INPUT doesn't match destination port 12345: packet dropped

    Communication doesn't work.

You need a stateful firewall to always accept established flows whenever the default policy is to drop them, because the randomly chosen source port, which becomes the destination in the reply, can't be guessed in advance.

On Linux's Netfilter framework, this is handled by conntrack and the iptables match modules that will query it. Here this can be done with iptables' conntrack match module:

iptables -I INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

With this any packet from a flow tracked as being already established is automatically accepted. For OP's loopback case this will allow the server to reply to itself successfully without knowing in advance the dynamically chosen source port of the initial query. The RELATED part also allows to accepted related errors, for example ICMP Destination unreachable (even for TCP it's useful for example with Path MTU Discovery).

More simply, most setups, including those with stateful firewall rules anyway accept local communication. You could also use instead (if for some reason you don't want to activate the conntrack subsystem), or in addition:

iptables -A INPUT -i lo -j ACCEPT
Bongo avatar
eg flag
Thank you very much for the information. It worked exactly as you wrote it. I have a lot more to read about iptables, especially for connection tracking (stateful firewall). Just to be sure, in this case, the connection is in the ESTABLISHED state because there are packets in both directions (the 3-way handshake has passed when the initial request/query packet was sent) ?
A.B avatar
cl flag
A.B
The ESTABLISHED state of a *conntrack* entry doesn't really match the ESTABLISHED state of a TCP connection. With *conntrack* ESTABLISHED means: "seen reply traffic": the first reply packet (most probably the TCP SYN/ACK) is the 1st with *conntrack* state ESTABLISHED (before, the very first query packet was in NEW state).
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.