1

Isn't the order of processing the rules in iptables top to bottom? Given the following example;

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere            
DNAT       tcp  --  anywhere             anywhere             tcp dpt:5000 to:172.19.0.2:5000

The second rule (DNAT) should never be processed, since the first rule (RETURN) will match with every packet and since this rule has a target, which is a terminating action (RETURN), the subsequent rules will be skipped, leading it to jump to the next rule of the previous chain.

But this is working. I am able to connect to the host on port 5000, which then DNATs it to the container 172.19.0.2:5000. How? As per my understanding, this should not work, since the DNAT rule should never be invoked, as all the packets will match with the first rule.

Here is the full iptables-save -c output:

# Generated by iptables-save v1.6.1 on Tue Sep  4 07:46:28 2018
*mangle
:PREROUTING ACCEPT [223887:255226234]
:INPUT ACCEPT [222119:254095862]
:FORWARD ACCEPT [1246:1112414]
:OUTPUT ACCEPT [146355:28000095]
:POSTROUTING ACCEPT [149233:29175672]
COMMIT
# Completed on Tue Sep  4 07:46:28 2018
# Generated by iptables-save v1.6.1 on Tue Sep  4 07:46:28 2018
*nat
:PREROUTING ACCEPT [98:6639]
:INPUT ACCEPT [19:3259]
:OUTPUT ACCEPT [1784:495831]
:POSTROUTING ACCEPT [1784:495887]
:DOCKER - [0:0]
[3:687] -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
[11:660] -A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
[12:684] -A POSTROUTING -s 172.19.0.0/24 ! -o docker0 -j MASQUERADE
[0:0] -A POSTROUTING -s 172.19.0.2/32 -d 172.19.0.2/32 -p tcp -m tcp --dport 5000 -j MASQUERADE
[0:0] -A DOCKER -i docker0 -j RETURN
[0:0] -A DOCKER ! -i docker0 -p tcp -m tcp --dport 5000 -j DNAT --to-destination 172.19.0.2:5000
[2:120] -A DOCKER ! -i docker0 -p tcp -m tcp --dport 5001 -j DNAT --to-destination 172.19.0.2:5001
COMMIT
# Completed on Tue Sep  4 07:46:28 2018
# Generated by iptables-save v1.6.1 on Tue Sep  4 07:46:28 2018
*filter
:INPUT ACCEPT [222119:254095862]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [146355:28000095]
:DOCKER - [0:0]
:DOCKER-ISOLATION - [0:0]
:DOCKER-USER - [0:0]
[1246:1112414] -A FORWARD -j DOCKER-USER
[1246:1112414] -A FORWARD -j DOCKER-ISOLATION
[618:1075408] -A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
[0:0] -A FORWARD -o docker0 -j DOCKER
[628:37006] -A FORWARD -i docker0 ! -o docker0 -j ACCEPT
[0:0] -A FORWARD -i docker0 -o docker0 -j ACCEPT
[0:0] -A DOCKER -d 172.19.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 5000 -j ACCEPT
[1246:1112414] -A DOCKER-ISOLATION -j RETURN
[1246:1112414] -A DOCKER-USER -j RETURN
COMMIT
# Completed on Tue Sep  4 07:46:28 2018

closed as too broad by Ipor Sircer, roaima, msp9011, Jeff Schaller, sebasth Sep 4 '18 at 5:34

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • Your assumption given the rules snippet is correct. Since you say it's not working you should update your question with evidence supporting your assertion so we have a chance of helping you further. (What happens? What doesn't happen? Why do you think this rule chain is at fault? What if you add a LOG target before and after the RETURN - do both get printed or just one?) – roaima Sep 3 '18 at 19:47
  • If you edit your question and put the output of iptables-save -c instead, the reason will probably appear (your command didn't display interfaces) – A.B Sep 3 '18 at 19:56
  • 2
    @A.B @roaima , Thanks. I have extended the question with iptables-save -c and I guess I know the problem now. The first rule will only match with any packet coming out of the docker0 interface. Is that right? – soupybionics Sep 4 '18 at 4:15
  • 1
    This is correct. – Jonas Berlin Sep 4 '18 at 9:53