Skip to main content
Remove counters and reduce indentation for readability
Source Link
table ip nat {
        chain DOCKER {
                iifname "docker0" counter packets 0 bytes 0 return
                iifname != "docker0" meta l4proto tcp ip daddr 172.17.0.1 tcp dport 5000 counter packets 0 bytes 0 dnat to 172.17.0.2:5000
                iifname != "docker0" meta l4proto tcp ip daddr 127.0.0.1 tcp dport 5000 counter packets 0 bytes 0 dnat to 172.17.0.2:5000
        }

        chain POSTROUTING {
                type nat hook postrouting priority srcnat; policy accept;
                oifname != "docker0" ip saddr 172.17.0.0/16 counter packets 1000 bytes 44000 masquerade 
                meta l4proto tcp ip saddr 172.17.0.2 ip daddr 172.17.0.2 tcp dport 5000 counter packets 0 bytes 0 masquerade 
        }

        chain PREROUTING {
                type nat hook prerouting priority dstnat; policy accept;
                fib daddr type local counter packets 2360 bytes 321200 jump DOCKER
        }

        chain OUTPUT {
                type nat hook output priority -100; policy accept;
                ip daddr != 127.0.0.0/8 fib daddr type local counter packets 1000 bytes 44000 jump DOCKER
        }
}
table ip filter {
        chain INPUT {
                type filter hook input priority filter; policy drop;
                iif "lo" accept comment "Allow loopback"
                ct state invalid drop
                ct state established,related accept
                iifname "bond0-data" tcp dport 22 counter packets 5 bytes 300 accept
                udp dport 3052 counter packets 282 bytes 230622 accept
                iifname "bond0-data" tcp dport 9090 counter packets 0 bytes 0 accept
                counter packets 2098 bytes 94204 log drop
        }

        chain FORWARD {
                type filter hook forward priority filter; policy drop;
                counter packets 8348495 bytes 902838489 jump DOCKER-USER
                counter packets 8348495 bytes 902838489 jump DOCKER-ISOLATION-STAGE-1
                oifname "docker0" ct state related,established counter packets 0 bytes 0 accept
                oifname "docker0" counter packets 0 bytes 0 jump DOCKER
                iifname "docker0" oifname != "docker0" counter packets 0 bytes 0 accept
                iifname "docker0" oifname "docker0" counter packets 0 bytes 0 accept
                counter packets 0 bytes 0 log drop
        }

        chain OUTPUT {
                type filter hook output priority filter; policy accept;
        }

        chain FORWARD-OVERRIDE {
                type filter hook forward priority filter + 10; policy accept;
                ct state invalid drop
                ct state established,related accept comment "Accept established, related"
                iifname "bond1-control" counter packets 0 bytes 0 drop comment "Drop new connections from bond1-control"
        }

        chain DOCKER {
                iifname != "docker0" oifname "docker0" meta l4proto tcp ip daddr 172.17.0.2 tcp dport 5000 counter packets 0 bytes 0 accept
        }

        chain DOCKER-ISOLATION-STAGE-1 {
                iifname "docker0" oifname != "docker0" counter packets 0 bytes 0 jump DOCKER-ISOLATION-STAGE-2
                counter packets 8348495 bytes 902838489 return
        }

        chain DOCKER-ISOLATION-STAGE-2 {
                oifname "docker0" counter packets 0 bytes 0 drop
                counter packets 4932244 bytes 299297906 return
        }

        chain DOCKER-USER {
                counter packets 8348495 bytes 902838489 return
        }
}
table ip nat {
        chain DOCKER {
                iifname "docker0" counter packets 0 bytes 0 return
                iifname != "docker0" meta l4proto tcp ip daddr 172.17.0.1 tcp dport 5000 counter packets 0 bytes 0 dnat to 172.17.0.2:5000
                iifname != "docker0" meta l4proto tcp ip daddr 127.0.0.1 tcp dport 5000 counter packets 0 bytes 0 dnat to 172.17.0.2:5000
        }

        chain POSTROUTING {
                type nat hook postrouting priority srcnat; policy accept;
                oifname != "docker0" ip saddr 172.17.0.0/16 counter packets 1000 bytes 44000 masquerade 
                meta l4proto tcp ip saddr 172.17.0.2 ip daddr 172.17.0.2 tcp dport 5000 counter packets 0 bytes 0 masquerade 
        }

        chain PREROUTING {
                type nat hook prerouting priority dstnat; policy accept;
                fib daddr type local counter packets 2360 bytes 321200 jump DOCKER
        }

        chain OUTPUT {
                type nat hook output priority -100; policy accept;
                ip daddr != 127.0.0.0/8 fib daddr type local counter packets 1000 bytes 44000 jump DOCKER
        }
}
table ip filter {
        chain INPUT {
                type filter hook input priority filter; policy drop;
                iif "lo" accept comment "Allow loopback"
                ct state invalid drop
                ct state established,related accept
                iifname "bond0-data" tcp dport 22 counter packets 5 bytes 300 accept
                udp dport 3052 counter packets 282 bytes 230622 accept
                iifname "bond0-data" tcp dport 9090 counter packets 0 bytes 0 accept
                counter packets 2098 bytes 94204 log drop
        }

        chain FORWARD {
                type filter hook forward priority filter; policy drop;
                counter packets 8348495 bytes 902838489 jump DOCKER-USER
                counter packets 8348495 bytes 902838489 jump DOCKER-ISOLATION-STAGE-1
                oifname "docker0" ct state related,established counter packets 0 bytes 0 accept
                oifname "docker0" counter packets 0 bytes 0 jump DOCKER
                iifname "docker0" oifname != "docker0" counter packets 0 bytes 0 accept
                iifname "docker0" oifname "docker0" counter packets 0 bytes 0 accept
                counter packets 0 bytes 0 log drop
        }

        chain OUTPUT {
                type filter hook output priority filter; policy accept;
        }

        chain FORWARD-OVERRIDE {
                type filter hook forward priority filter + 10; policy accept;
                ct state invalid drop
                ct state established,related accept comment "Accept established, related"
                iifname "bond1-control" counter packets 0 bytes 0 drop comment "Drop new connections from bond1-control"
        }

        chain DOCKER {
                iifname != "docker0" oifname "docker0" meta l4proto tcp ip daddr 172.17.0.2 tcp dport 5000 counter packets 0 bytes 0 accept
        }

        chain DOCKER-ISOLATION-STAGE-1 {
                iifname "docker0" oifname != "docker0" counter packets 0 bytes 0 jump DOCKER-ISOLATION-STAGE-2
                counter packets 8348495 bytes 902838489 return
        }

        chain DOCKER-ISOLATION-STAGE-2 {
                oifname "docker0" counter packets 0 bytes 0 drop
                counter packets 4932244 bytes 299297906 return
        }

        chain DOCKER-USER {
                counter packets 8348495 bytes 902838489 return
        }
}
table ip nat {
    chain DOCKER {
        iifname "docker0" return
        iifname != "docker0" meta l4proto tcp ip daddr 172.17.0.1 tcp dport 5000 dnat to 172.17.0.2:5000
        iifname != "docker0" meta l4proto tcp ip daddr 127.0.0.1 tcp dport 5000 dnat to 172.17.0.2:5000
    }

    chain POSTROUTING {
        type nat hook postrouting priority srcnat; policy accept;
        oifname != "docker0" ip saddr 172.17.0.0/16 masquerade
        meta l4proto tcp ip saddr 172.17.0.2 ip daddr 172.17.0.2 tcp dport 5000 masquerade
    }

    chain PREROUTING {
        type nat hook prerouting priority dstnat; policy accept;
        fib daddr type local jump DOCKER
    }

    chain OUTPUT {
        type nat hook output priority -100; policy accept;
        ip daddr != 127.0.0.0/8 fib daddr type local jump DOCKER
    }
}
table ip filter {
    chain INPUT {
        type filter hook input priority filter; policy drop;
        iif "lo" accept comment "Allow loopback"
        ct state invalid drop
        ct state established,related accept
        iifname "bond0-data" tcp dport 22 accept
        udp dport 3052 accept
        iifname "bond0-data" tcp dport 9090 accept
        log drop
    }

    chain FORWARD {
        type filter hook forward priority filter; policy drop;
        jump DOCKER-USER
        jump DOCKER-ISOLATION-STAGE-1
        oifname "docker0" ct state related,established accept
        oifname "docker0" jump DOCKER
        iifname "docker0" oifname != "docker0" accept
        iifname "docker0" oifname "docker0" accept
        log drop
    }

    chain OUTPUT {
        type filter hook output priority filter; policy accept;
    }

    chain FORWARD-OVERRIDE {
        type filter hook forward priority filter + 10; policy accept;
        ct state invalid drop
        ct state established,related accept comment "Accept established, related"
        iifname "bond1-control" drop comment "Drop new connections from bond1-control"
    }

    chain DOCKER {
        iifname != "docker0" oifname "docker0" meta l4proto tcp ip daddr 172.17.0.2 tcp dport 5000 accept
    }

    chain DOCKER-ISOLATION-STAGE-1 {
        iifname "docker0" oifname != "docker0" jump DOCKER-ISOLATION-STAGE-2
        return
    }

    chain DOCKER-ISOLATION-STAGE-2 {
        oifname "docker0" drop
        return
    }

    chain DOCKER-USER {
        return
    }
}
Source Link

Understanding docker port forwarding and iptables/nftables

Given a fairly common firewall setup with nftables/iptables (OUTPUT accept, INPUT/FORWARD accept established+related, default drop):

table ip nat {
        chain DOCKER {
                iifname "docker0" counter packets 0 bytes 0 return
                iifname != "docker0" meta l4proto tcp ip daddr 172.17.0.1 tcp dport 5000 counter packets 0 bytes 0 dnat to 172.17.0.2:5000
                iifname != "docker0" meta l4proto tcp ip daddr 127.0.0.1 tcp dport 5000 counter packets 0 bytes 0 dnat to 172.17.0.2:5000
        }

        chain POSTROUTING {
                type nat hook postrouting priority srcnat; policy accept;
                oifname != "docker0" ip saddr 172.17.0.0/16 counter packets 1000 bytes 44000 masquerade 
                meta l4proto tcp ip saddr 172.17.0.2 ip daddr 172.17.0.2 tcp dport 5000 counter packets 0 bytes 0 masquerade 
        }

        chain PREROUTING {
                type nat hook prerouting priority dstnat; policy accept;
                fib daddr type local counter packets 2360 bytes 321200 jump DOCKER
        }

        chain OUTPUT {
                type nat hook output priority -100; policy accept;
                ip daddr != 127.0.0.0/8 fib daddr type local counter packets 1000 bytes 44000 jump DOCKER
        }
}
table ip filter {
        chain INPUT {
                type filter hook input priority filter; policy drop;
                iif "lo" accept comment "Allow loopback"
                ct state invalid drop
                ct state established,related accept
                iifname "bond0-data" tcp dport 22 counter packets 5 bytes 300 accept
                udp dport 3052 counter packets 282 bytes 230622 accept
                iifname "bond0-data" tcp dport 9090 counter packets 0 bytes 0 accept
                counter packets 2098 bytes 94204 log drop
        }

        chain FORWARD {
                type filter hook forward priority filter; policy drop;
                counter packets 8348495 bytes 902838489 jump DOCKER-USER
                counter packets 8348495 bytes 902838489 jump DOCKER-ISOLATION-STAGE-1
                oifname "docker0" ct state related,established counter packets 0 bytes 0 accept
                oifname "docker0" counter packets 0 bytes 0 jump DOCKER
                iifname "docker0" oifname != "docker0" counter packets 0 bytes 0 accept
                iifname "docker0" oifname "docker0" counter packets 0 bytes 0 accept
                counter packets 0 bytes 0 log drop
        }

        chain OUTPUT {
                type filter hook output priority filter; policy accept;
        }

        chain FORWARD-OVERRIDE {
                type filter hook forward priority filter + 10; policy accept;
                ct state invalid drop
                ct state established,related accept comment "Accept established, related"
                iifname "bond1-control" counter packets 0 bytes 0 drop comment "Drop new connections from bond1-control"
        }

        chain DOCKER {
                iifname != "docker0" oifname "docker0" meta l4proto tcp ip daddr 172.17.0.2 tcp dport 5000 counter packets 0 bytes 0 accept
        }

        chain DOCKER-ISOLATION-STAGE-1 {
                iifname "docker0" oifname != "docker0" counter packets 0 bytes 0 jump DOCKER-ISOLATION-STAGE-2
                counter packets 8348495 bytes 902838489 return
        }

        chain DOCKER-ISOLATION-STAGE-2 {
                oifname "docker0" counter packets 0 bytes 0 drop
                counter packets 4932244 bytes 299297906 return
        }

        chain DOCKER-USER {
                counter packets 8348495 bytes 902838489 return
        }
}

Note that container 172.17.0.2:5000 is mapped to port 5000 using docker's port forwarding.

If I try to connect from container 172.17.0.3 directly to 172.17.0.2:5000 then this works. If I try to connect from container 172.17.0.3 through the host IP (172.17.0.1:5000) then this does not work, unless I add iffname "docker0" accept to the INPUT chain.

I would like to understand why.

The kern.log shows the following when trying to connect:

IN=docker0 OUT= PHYSIN=vethbdc197b MAC=xxxxxxx SRC=172.17.0.3 DST=172.17.0.1 LEN=44 TOS=0x00 PREC=0x00 TTL=58 ID=37344 PROTO=TCP SPT=52535 DPT=5000 WINDOW=1024 RES=0x00 SYN URGP=0

Why is it that this connection is blocked when direct connections are allowed? My best guess at the moment is the direct connection is somehow allowed by the OUTPUT accept and then INPUT sees it as established,related. But it's not clear how things differ when going through the docker port mapping. Maybe DNAT results in a separate INPUT connection that then gets blocked?

Can anyone shed some light on how this works from the iptables/nftables perspective?