dockeriptables

Docker chain in iptables overrides INPUT rules


I have a server and I am running a few docker containers. These containers have a few ports that aren't open. I have added INPUT rules to only allow access to those ports from 1 ip and after that I have a DROP rule.

This should block all access to the ports from except my home ip. Now it turns out that docker just allows everything and docker somehow is able to override the input rules because the input rules are not working.

I believe this has to do with the FORWARDING rule which looks like this:

Chain FORWARD (policy ACCEPT) target prot opt source destination DOCKER-USER all -- anywhere anywhere DOCKER-ISOLATION-STAGE-1 all -- anywhere anywhereACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED DOCKER all -- anywhere anywhere ACCEPT all -- anywhere anywhere ACCEPT all -- anywhere anywhere ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED DOCKER all -- anywhere anywhere ACCEPT all -- anywhere anywhere ACCEPT all -- anywhere anywhere

I have flushed all the rules and then I get really wierd errors from docker things like:

driver failed programming external connectivity on endpoint gogs (b62814647bf440e923c009da0ca76185fac2f89a9534eb11792dbcb07ef3ffbf): (iptables failed: iptables --wait -t filter -A DOCKER ! -i br-5dd41982af68 -o br-5dd41982af68 -p tcp -d 172.18.0.6 --dport 3000 -j ACCEPT: iptables: No chain/target/match by that name.

How can I make sure that the input rules override everything so that the port filtering on the INPUT chain stop access for everybody else but me?


Solution

  • I have found a way better option. Avoid the DOCKER-USER all together.

    I realized that what I want to protect is the network card interface. So lets say I have a VPS and it has an interface eth0 that connects to the internet then all I need to do is block all incoming traffic for eth0 except the ports I want. For example 80, 443. I can then also add IP exceptions for eth0 like my home and office ipnumbers. I then allow everything else.

    So in short block the internet interface except certain ports and allow everything else.

    Example bash file that I use to quickly set my iptable rules:

    #!/bin/bash
    
    # Set temporary all to accept otherwise the next flush might block us out
    iptables -P INPUT ACCEPT
    iptables -P OUTPUT ACCEPT
    iptables -P FORWARD ACCEPT
    
    # Flush all the existing rules
    iptables -F
    
    # Allow internal connections. 
    iptables -A INPUT -i lo -j ACCEPT
    iptables -A OUTPUT -o lo -j ACCEPT
    
    # Allow established connections
    iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
    iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT
    iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
    
    # Allow IP address
    iptables -A INPUT -p tcp -s IP
    iptables -A FORWARD -p tcp -s IP -j ACCEPT
    
    # Allow http and https
    iptables -A INPUT -p tcp -m multiport --dports 80,443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
    iptables -A OUTPUT -p tcp -m multiport --dports 80,443 -m conntrack --ctstate ESTABLISHED -j ACCEPT
    
    # Block all on eth0 or any other 
    #iptables -A INPUT -i eth0 -j DROP
    #iptables -A FORWARD -i eth0 -j DROP
    
    iptables -P INPUT ACCEPT
    iptables -P OUTPUT ACCEPT
    iptables -P FORWARD ACCEPT