Ram
Ram

Reputation: 1213

Docker inserting iptable Postrouting rules on top of admin added rules

I had to add few iptable entries into NAT table, POSTROUTING chain, to allow docker containers to access internet through a different source-address/source-interface of Host Machine (to_source).

Things are working fine.

Ex:

target     prot opt source               destination
SNAT       all  --  100.100.8.0/22       10.1.2.3       to:100.64.0.5

But, when docker service is restarted, it inserts MASQUERADE rules on top of my entries and hence my fix as above is masked. Docker containers can't access internet now.

Ex:

target     prot opt source               destination
MASQUERADE  all  --  100.100.8.0/22       0.0.0.0/0
SNAT        all  --  100.100.8.0/22       10.1.2.3       to:100.64.0.5

Is there anyway to make my POSTROUTING rules to stay always on top of the chain even after docker restarts?

Upvotes: 8

Views: 1664

Answers (3)

jdhildeb
jdhildeb

Reputation: 3819

It is important to create the rule at the right time - after the docker containers are up, because that's when docker creates the MASQUERADE rules.

Using cron @reboot with a delay would not be reliable, because whenever you restart a container (or bring up a new one), the rules would be in the wrong order.

My solution is a script, executed by cron, which will check the position of my rule(s) and re-insert them if/when necessary.

# we attach a unique comment to our rule so that we can check its position later
unique_comment="docker SNAT source IP"

insert_rules() {
    # put your rules here.  Make sure the first rule is tagged with $unique_comment so it can be identified.
    sudo iptables -t nat -I POSTROUTING 1 -s 172.17.0.0/12 -j SNAT --to-source 1.2.3.4 -m comment --comment "$unique_comment"
    sudo iptables -t nat -I POSTROUTING 2 -s 192.168.0.0/16 -j SNAT --to-source 1.2.3.4
}

delete_rules() {
    pos=$1
    # delete the first two rules from POSTROUTING.  Adjust if necessary.
    sudo iptables -t nat -D POSTROUTING $pos
    sudo iptables -t nat -D POSTROUTING $pos
}


pos=$(sudo iptables -t nat -L POSTROUTING -v -n --line-numbers|grep "$unique_comment" | awk '{ print $1 }')
if [ "$pos" == "1" ]; then
    : # correct position; nothing to do
elif [ "$pos" == "" ]; then
    # rule does not exist; add it.
    insert_rules
else
    # rule is not first; re-insert it.
    delete_rules $pos
    insert_rules
fi

Now create a cron job to execute this script frequently as you need (e.g. every 1 or 2 minutes).

Upvotes: 1

Jacob Tomlinson
Jacob Tomlinson

Reputation: 3783

You can add --iptables=false to your docker daemon startup options which stops it from making changes to the iptables rules at all.

Reference: https://docs.docker.com/engine/reference/commandline/dockerd/

Upvotes: 0

Saad
Saad

Reputation: 954

If Ubuntu is on your host, you can use the iptables-save utility to save the iptables rules to a file after you start the docker daemon. Then, once you flush the old rules, you can simply restore the original docker rules using iptables-restore & the saved rules file.

If you don't want to restore all the old iptables rules, you can alter the saved rules file to keep only the ones you need.

Upvotes: 0

Related Questions