Reputation: 1213
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
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
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
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