JP van Oosten

Linux iptables and docker

Feb 22, 2023

Recently, I wanted to move some services that I’m running on my home server and in a VPS to docker containers. This would provide better segmentation of responsibilities, even though it would cost a bit more resources on the machines.

Because the VPS is directly connected to the net, it has a firewall. I based it on iptables, and that has been running well for a long time. Adding docker in the mix is a bit weird, because it does a lot magic with iptables that was a bit above my comfort-level (I’m a programmer, not a network-administrator!) The main thing that it does is open all the ports to all dockers that expose ports.

I'm sorry what GIF

Luckily, the docker documentation on iptables 1 gives us a way to fix that: iptables -I DOCKER-USER -i ext_if ! -s -j DROP. Unfortunately, doing this, meant that I also couldn’t connect to the docker container from the host for, e.g., reverse proxying.

In order to solve this, I created a new network “ingress”, that I can attach containers to: docker network create --ip-range --subnet= ingress. The idea is that I can now create an explicit iptables rule for this network, allowing access from the local machine to the containers in that network. This means that attaching a container to this network (or do you attach a network to a container? 🤔) I can reverse proxy from the host!

The rule I used is: iptables -A INPUT --source --destination -j ACCEPT. The ip is the ingress gateway. This allows traffic to flow between the ingress network and the gateway.

In a docker-compose.yml file, I can now add a network block:

      - default
      - ingress

        external: true
        name: ingress

The default network is only really necessary if you have multiple services running that need to communicate with each other.

  1. Notice how that page links to a HOWTO on Linux NAT for the 2.4 kernel. That kernel came out in 2001!