Does Docker automate IP masquerade rules in iptables for bridge networks?

Matthew Crenshaw picture Matthew Crenshaw · Apr 27, 2016 · Viewed 11.9k times · Source

I have docker-1.9.1 running on a QNAP raid machine. It has the default bridge network using subnet 10.0.3.0/24. In iptables I see a rule in the nat table:

-A POSTROUTING -s 10.0.3.0/24 ! -d 10.0.3.0/24 -j MASQUERADE

I am assuming that Docker created this rule itself.

I have created a new bridge network:

docker network create \
--gateway=10.0.5.1 \
--subnet=10.0.5.0/24 \
-o "com.docker.network.bridge.host_binding_ipv4"="0.0.0.0" \
-o "com.docker.network.bridge.enable_icc"="true" \
-o "com.docker.network.driver.mtu"="1500" \
-o "com.docker.network.bridge.name"="lxcbr1" \
-o "com.docker.network.bridge.enable_ip_masquerade"="true" \
isolated_nw

This does not create a rule in iptables. Did I miss a step?

Here's the full setup commands and results, copying @larsks' example:

[/share/Containers] # docker --version
Docker version 1.9.1, build 147ce3e
[/share/Containers] # iptables -t nat -S | grep 10.0.5.0
[/share/Containers] # docker network create \
> --gateway=10.0.5.1 \
> --subnet=10.0.5.0/24 \
> -o "com.docker.network.bridge.host_binding_ipv4"="0.0.0.0" \
> -o "com.docker.network.bridge.enable_icc"="true" \
> -o "com.docker.network.driver.mtu"="1500" \
> -o "com.docker.network.bridge.name"="lxcbr1" \
> -o "com.docker.network.bridge.enable_ip_masquerade"="true" \
> isolated_nw
a7b5c938008169f32fcdfc1d9409716b725cc916b30f472ac6ec2a1d71fb77f0
[/share/Containers] # iptables -t nat -S | grep 10.0.5.0
[/share/Containers] # iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-A POSTROUTING -s 10.0.3.0/24 ! -d 10.0.3.0/24 -j MASQUERADE
[/share/Containers] #

Answer

larsks picture larsks · Apr 27, 2016

I'm using Docker 1.9.1 (on Fedora 23 Atomic), and your command seems to work just fine.

Before creating the network:

# docker --version
Docker version 1.9.1, build 7206621
# iptables -t nat -S | grep 10.0.5.0
<no result>

Create the network:

docker network create \
--gateway=10.0.5.1 \
--subnet=10.0.5.0/24 \
-o "com.docker.network.bridge.host_binding_ipv4"="0.0.0.0" \
-o "com.docker.network.bridge.enable_icc"="true" \
-o "com.docker.network.driver.mtu"="1500" \
-o "com.docker.network.bridge.name"="lxcbr1" \
-o "com.docker.network.bridge.enable_ip_masquerade"="true" \
isolated_nw

Check iptables:

# iptables -t nat -S | grep 10.0.5.0
-A POSTROUTING -s 10.0.5.0/24 ! -o lxcbr1 -j MASQUERADE

...I note that running docker network rm isolated_nw, while it correctly deletes the bridge device, does not seem to remove the iptables rule. This seems to be fixed in more recent versions of Docker (e.g., I'm running 1.11.0 locally, and that version seems to correctly remove the rule on network delete).

Update

If that update to your question has the entire output from iptables -t nat -S, then something else is going on, because you are missing the DOCKER chain in the nat table.

# iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N DOCKER
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 10.0.5.0/24 ! -o lxcbr1 -j MASQUERADE
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

And in fact, I'm surprised that your create network command even completes, because if I manually remove the DOCKER chain and references, attempts to create a new network on my system result in:

Error response from daemon: Failed to program NAT chain: Failed to 
inject docker in PREROUTING chain: iptables failed: iptables --wait
-t nat -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER: iptables 
v1.4.21: Couldn't load target `DOCKER':No such file or directory