What Docker Networks and iptables have to say

Docker Network Model

Docker has multiple network modes, including host, none,bridge Overay and so on. Next, we discuss the relationship between Docker network and iptables with Docker's default bridge network, Docker 0.

Docker 0 network is a virtual bridge network built by Docker. The default gateway address is 172.17.0.1. Docker's default network is the Docker 0 network, which means that any container of the specified network in Docker will join the bridge network, and the containers in the network can communicate with each other.

# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
        inet6 fe80::42:c0ff:febb:bb1e  prefixlen 64  scopeid 0x20<link>
        ether 02:42:c0:bb:bb:1e  txqueuelen 0  (Ethernet)
        RX packets 353181  bytes 163487291 (155.9 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 297594  bytes 126028894 (120.1 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Container requests data externally

If the container in Docker 0 requests external data, its packet will be sent to gateway 172.17.0.1. When the packet arrives at the gateway, the host's routing table will be queried to determine from which network card the packet will be sent. iptables is responsible for snat conversion of data packets, and the original address is converted to the address of the corresponding network card, so the container is invisible to the outside world.

External requests for container data

To access the data in the container, the external needs to map the port of the container to the host. At this point, docker will add forwarding rules to iptables and forward the received data to the container.

Docker and iptables

The following figure shows the process of data packet transfer in iptable

Create a container for port mapping

Next, let's look at how container packets are passed in the iptable Create a redis container that maps port 6379 to port 36379 of the host.

# docker run --name redistest -d -p 36379:6379 172.16.1.129/redis/3.0.7:v1.1
b4c3fc06cdaccc2080f9e4845ebb2d2b789632ddaecb6e7b2e3bdf863c416014

View the nat table of iptables

# 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 OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  anywhere            !loopback/8           ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
CATTLE_NAT_POSTROUTING  all  --  anywhere             anywhere            
MASQUERADE  all  --  172.17.0.0/16        anywhere            
MASQUERADE  all  --  172.18.0.0/16        anywhere            
MASQUERADE  tcp  --  172.17.0.3           172.17.0.3           tcp dpt:6379

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere            
RETURN     all  --  anywhere             anywhere            
DNAT       tcp  --  anywhere             anywhere             tcp dpt:36379 to:172.17.0.3:6379

You can see that the nat table of iptables has a Docker subchain with a data in it.

DNAT       tcp  --  anywhere             anywhere             tcp dpt:36379 to:172.17.0.3:6379

This data is responsible for mapping the host tcp36379 port to 172.17.0.3:6379.

Docker subchains are referenced by PREROUTING and OUTPUT chains

  • PREROUTING: Change the destination address of a packet when it reaches the firewall

  • OUTPUT: Filter all locally generated data packets (filtering of data packets from source addresses)

That is to say, the packets accessed by the external host 36379 are snat and pnat converted here in nat, and the destination address is 172.17.0.3:6379.

Container accesses external data packages for dnat and pnat, converting 172.17.0.3:6379 to 36379 ports of the host.

View the filter table for iptables

# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:ssh

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
DOCKER-ISOLATION  all  --  anywhere             anywhere            
DOCKER     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
DOCKER     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere            
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited
DROP       all  --  anywhere             anywhere            

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain DOCKER (2 references)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             172.17.0.3           tcp dpt:6379

Chain DOCKER-ISOLATION (1 references)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere            
DROP       all  --  anywhere             anywhere            
RETURN     all  --  anywhere             anywhere            

There is also a DOCKER subchain, which is referenced by the FORWARD chain.

  • FORWARD Chain: Filter all data packets passing through the machine (source address and destination address are not local data packets)

That is to say, after switching the address through nat, the packet of the test container will be forwarded to 172.17.0.3 instead of the host, and the filtering rule is Accept, that is, through.

Matters needing attention

Some of the network functions of docker are accomplished by iptables forwarding. The forwarding rules are added dynamically after the start of the docker process, which means that if you restart iptables, the docker forwarding rules will be lost.

There are two solutions:

  1. Add iptables rules dynamically and modify / etc / sysconf / iptables (recommended)

Adding iptables rules dynamically can make the rules take effect immediately (restart invalidation)

iptables -A INPUT -p tcp --dport 46379 -j ACCEPT

Modify the / etc/sysconf/iptables file to save your changes. If the server restarts, this rule will be added automatically.

vi /etc/sysconf/iptables
  1. Restart docker after restarting iptable

Impact: Restarting docker will cause all containers to restart, possibly causing short-term business failures.

This method is not recommended. If the firewall has been restarted, leading to docker business failure, restart dcoker with the following command.

systemctl restart docker

Keywords: Docker iptables network Redis

Added by grilldor on Sun, 16 Jun 2019 04:25:56 +0300