Home Blag Links Wireguard About

Docker-taming: iptables

2020-11-26

It is 2020 and I recently started playing around with Docker. That might seem a bit late, but here's why: When I tried Docker before, it instantaneously messed around with my Iptables. No warning, no safeguards, nothing. Which is why I purged it and didn't give it another chance. Until now.

What helped was deactivating automagic iptables rules in my /etc/docker/daemon.json.

{
  "iptables": false
}

So far so good. Docker containers run fine and do their jobs -- as long as they don't need to interact with each other or connect outbound.

I could just generally allow connections between Docker containers and allow them to connect outbound through the host system. But that's not what I wanted. I wanted to use proper segmentation between Docker containers. This did not work with default settings.

My requirements were:

  • Explicit is better than implicit. Write (and understand!) my own iptables rules.
  • Readability counts: Have human-readable interface names and iptables rules.

This is what I ended up with:

version: '2'
services:
  my-docker-service:
    container_name: my-docker-service
    image: (...)
    restart: unless-stopped
    ports:
      - 32400:32400/tcp
    environment:
      - (...)
    volumes:
      - /data/config:/config
      - (...)
    networks:
      my-custom-dockernet:
        ipv4_address: 172.25.34.10

networks:
  my-custom-dockernet:
    driver: bridge
    enable_ipv6: false
    name: my-custom-dockernet
    ipam:
      driver: default
      config:
        - subnet: 172.25.34.0/24
          gateway: 172.25.34.1
    driver_opts:
      com.docker.network.bridge.name: docker-my-custom-dockernet
toe@t20 ~ % docker network ls
NETWORK ID          NAME                  DRIVER              SCOPE
ad80fe06534f        bridge                bridge              local
8e2cdc4f9bac        host                  host                local
f329b0ce5624        none                  null                local
b88c5de7746f        my-custom-dockernet   bridge              local
toe@t20 ~ % ip addr show
(...)
8: docker-my-custom-dockernet: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:67:2e:ae:bc brd ff:ff:ff:ff:ff:ff
    inet 172.25.34.1/24 brd 172.25.34.255 scope global docker-my-custom-dockernet
       valid_lft forever preferred_lft forever
(...)
toe@t20 ~ % cat /etc/iptables/iptables.rules
(...)
-A FORWARD -i eno1 -o docker-my-custom-dockernet -d 172.25.34.10 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker-my-custom-dockernet -o eno1 -s 172.25.34.10 -j ACCEPT
(...)
toe@t20 ~ % sudo iptables -nvL; sudo iptables -nvL -t nat
(...)
Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in                         out                         source               destination
 332K  485M ACCEPT     all  --  eno1                       docker-my-custom-dockernet  0.0.0.0/0            172.25.34.0/24       state RELATED,ESTABLISHED
 239K   16M ACCEPT     all  --  docker-my-custom-dockernet eno1                        172.25.34.0/24       0.0.0.0/0
(...)
Chain POSTROUTING (policy ACCEPT 8368 packets, 390K bytes)
 pkts bytes target     prot opt in     out     source               destination
 6942  446K MASQUERADE  all  --  *      eno1    0.0.0.0/0            0.0.0.0/0
(...)