Let Docker and UFW Firewall work together

If you see your Docker container ports got exposed and bypassed all UFW rules, that is normal because Docker will manipulate iptables when creating container. Docker in default will work with iptables nicely without user creating complicated iptables rules. If you don’t want Docker creating iptables rules or you are using UFW, you need to propertly configure them to make then work nicely together.

firewall

There are two ways to prevent Docker exposing itself with iptables.

  1. Prevent Docker from manipulating iptables

    According to Docker’s guides, it is possible to set the iptables key to false in the Docker engine’s configuration file at /etc/docker/daemon.json

    You can achieve that by running below command

    1
    2
    3
    sudo bash -c 'echo "{
    \"iptables\": false
    }" >> /etc/docker/daemon.json'
  2. Put Docker behind UFW

    1. Get your external interface name

      1
      echo $(ip route get 8.8.8.8 | awk -- '{printf $5}')
    2. Add the following to the end of /etc/ufw/after.rules. Replace eth0 with the interface name you got from previous step. Most common interface name is eth0

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      # sudo nano /etc/ufw/after.rules

      # BEGIN UFW AND DOCKER
      *filter
      :ufw-user-forward - [0:0]
      :ufw-docker-logging-deny - [0:0]
      :DOCKER-USER - [0:0]
      -A DOCKER-USER -j ufw-user-forward

      -A DOCKER-USER -j RETURN -s 10.0.0.0/8
      -A DOCKER-USER -j RETURN -s 172.16.0.0/12
      -A DOCKER-USER -j RETURN -s 192.168.0.0/16

      -A DOCKER-USER -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN

      -A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 192.168.0.0/16
      -A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 10.0.0.0/8
      -A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 172.16.0.0/12
      -A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 192.168.0.0/16
      -A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 10.0.0.0/8
      -A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 172.16.0.0/12

      -A DOCKER-USER -j RETURN

      -A ufw-docker-logging-deny -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW DOCKER BLOCK] "
      -A ufw-docker-logging-deny -j DROP

      COMMIT
      # END UFW AND DOCKER
    3. Remove "iptables": "false" from etc/docker/daemon.json

    4. Make sure DEFAULT_FORWARD_POLICY="DROP" in /etc/default/ufw

    5. If you ever add any docker related rules to /etc/ufw/before.rules, remove them.

    6. Test before reboot

    7. Open ports based on your needed. You can allow port access to all containers or specific container.

      To allow public access to port 8080.

      1
      sudo ufw route allow proto tcp from any to any port 8080

      Allow public access to port 80 for container with private address 172.17.0.3

      1
      ufw route allow proto tcp from any to 172.17.0.3 port 80

      Allow DNS

      1
      ufw route allow proto udp from any to any port 53
Ubuntu port 53 already in use. How to free the DNS port Install Isso server free with GCP

Comments