Unwanted masquerading in docker container
Although I have not added any iptables rules on the host or the two containers, packets from one docker container are modified and given the IP of the docker network gateway:
Container 1:
bash-5.0# ip route
default via 172.16.238.2 dev eth0
10.6.0.0/24 via 172.16.238.1 dev eth0
172.16.238.0/24 dev eth0 scope link src 172.16.238.7
bash-5.0# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
23: eth0@if24: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:10:ee:07 brd ff:ff:ff:ff:ff:ff
inet 172.16.238.7/24 brd 172.16.238.255 scope global eth0
valid_lft forever preferred_lft forever
bash-5.0# ping 1.1.1.1
PING 1.1.1.1 (1.1.1.1): 56 data bytes
--- 1.1.1.1 ping statistics ---
7 packets transmitted, 0 packets received, 100% packet loss
Container 2:
root@c8d6fa7eab4d:/# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
3: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
link/none
inet 100.71.37.47/32 scope global wg0
valid_lft forever preferred_lft forever
17: eth0@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:10:ee:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.16.238.2/24 brd 172.16.238.255 scope global eth0
valid_lft forever preferred_lft forever
root@c8d6fa7eab4d:/# tcpdump -i eth0 dst 1.1.1.1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
16:34:06.910548 IP 172.16.238.1 > one.one.one.one: ICMP echo request, id 5632, seq 36, length 64
16:34:07.910920 IP 172.16.238.1 > one.one.one.one: ICMP echo request, id 5632, seq 37, length 64
16:34:08.911322 IP 172.16.238.1 > one.one.one.one: ICMP echo request, id 5632, seq 38, length 64
16:34:09.911709 IP 172.16.238.1 > one.one.one.one: ICMP echo request, id 5632, seq 39, length 64
16:34:10.912143 IP 172.16.238.1 > one.one.one.one: ICMP echo request, id 5632, seq 40, length 64
16:34:11.912504 IP 172.16.238.1 > one.one.one.one: ICMP echo request, id 5632, seq 41, length 64
16:34:12.912932 IP 172.16.238.1 > one.one.one.one: ICMP echo request, id 5632, seq 42, length 64
^C
7 packets captured
9 packets received by filter
0 packets dropped by kernel
Host:
root@raspberrypi:~# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER all -- anywhere anywhere ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- !172.16.238.0/24 172.16.238.2
MASQUERADE all -- !172.16.238.0/24 172.16.238.2
MASQUERADE all -- 172.17.0.0/16 anywhere
MASQUERADE all -- 172.16.238.0/24 anywhere
MASQUERADE all -- !172.16.238.0/24 172.16.238.2
MASQUERADE all -- 10.6.0.0/24 anywhere /* wireguard-nat-rule */
MASQUERADE all -- !172.16.238.0/24 172.16.238.2
MASQUERADE all -- 172.16.238.0/24 anywhere
MASQUERADE tcp -- 172.16.238.4 172.16.238.4 tcp dpt:https
MASQUERADE tcp -- 172.16.238.4 172.16.238.4 tcp dpt:http
MASQUERADE tcp -- 172.16.238.4 172.16.238.4 tcp dpt:domain
MASQUERADE udp -- 172.16.238.4 172.16.238.4 udp dpt:domain
MASQUERADE tcp -- 172.16.238.5 172.16.238.5 tcp dpt:https
MASQUERADE tcp -- 172.16.238.5 172.16.238.5 tcp dpt:http
MASQUERADE tcp -- 172.16.238.5 172.16.238.5 tcp dpt:domain
MASQUERADE udp -- 172.16.238.5 172.16.238.5 udp dpt:domain
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DOCKER all -- anywhere !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- anywhere anywhere
RETURN all -- anywhere anywhere
DNAT tcp -- anywhere 192.168.178.2 tcp dpt:https to:172.16.238.4:443
DNAT tcp -- anywhere 192.168.178.2 tcp dpt:http to:172.16.238.4:80
DNAT tcp -- anywhere 192.168.178.2 tcp dpt:domain to:172.16.238.4:53
DNAT udp -- anywhere 192.168.178.2 udp dpt:domain to:172.16.238.4:53
DNAT tcp -- anywhere 192.168.178.3 tcp dpt:https to:172.16.238.5:443
DNAT tcp -- anywhere 192.168.178.3 tcp dpt:http to:172.16.238.5:80
DNAT tcp -- anywhere 192.168.178.3 tcp dpt:domain to:172.16.238.5:53
DNAT udp -- anywhere 192.168.178.3 udp dpt:domain to:172.16.238.5:53
# Warning: iptables-legacy tables present, use iptables-legacy to see them
root@raspberrypi:~# iptables-legacy -S -t nat
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
Inter-Container Connectivity (ICC) is enabled by default and it links containers together automatically without using --link
or defining a network
.
If you're looking to disable it, set icc: false
in your Docker daemon configuration (/etc/daemon.json
)
Left undefined or set to true makes the Docker deamon create connected networks along with container creation. These networks are the source of the iptables rules you see.
See more in the official Docker bridge networking tutorial.