Debian – Configure iptables for Docker manually and allow Internet access for containers

debianfirewalliptables

I was really unhappy with Docker's behavior regarding modifying my firewall rules because it just opens all ports on my server.
So I have installed iptables-persistent and set up some firewall rules that block all incoming traffic except for port 22, 80 and 443 and I ensured that Docker stops messing with these rules by creating /etc/systemd/system/docker.service.d/noiptables.conf with the following content:

[Service]
ExecStart=
ExecStart=/usr/bin/dockerd --iptables=false -H "fd://"

and then rebooted the server.

Now my problem is that my Docker containers can't access the Internet (interface: ens3) anymore.

These are my rules:

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -o ens3 -j MASQUERADE
COMMIT

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]

# Allow localhost
-A INPUT -i lo -j ACCEPT
-A OUTPUT -o lo -j ACCEPT

# ICMP
-A INPUT -p icmp -j ACCEPT

# Docker
-A FORWARD -i docker0 -o ens3 -j ACCEPT
-A FORWARD -i ens3 -o docker0 -j ACCEPT


# Incoming
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -j DROP

# Outgoing
-A OUTPUT -j ACCEPT

# Routing
-A FORWARD -j DROP


COMMIT

I stored them in /etc/iptables/rules.v4 and /etc/iptables/rules.v6 and made sure they are loaded by running sudo netfilter-persistent reload.

According to this guide: https://blog.daknob.net/debian-firewall-docker/
The *nat section would do the job, but it doesn't.

My system:

$ sudo iptables --version
iptables v1.6.1

$ uname -r
4.11.0-1-amd64

$ sudo lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description:    Debian GNU/Linux testing (buster)
Release:        testing
Codename:       buster

Best Answer

First, you have never mentioned net.ipv4.ip_forward net.ipv4.ip_forward. Enable that if you haven't.

Ensure that you can access the internet. curl httpbin.org/ip is a nice and easy way to check that.

If you did, ensure that your rules are active by checking the output of iptables-save

If they are, debug it, here are the pseudo-steps:

  1. Inside the docker, ping an external IP, say 8.8.8.8 and ensure that you do not receive any reply. Do not use a hostname. Let's keep DNS problems out of our scenario. Keep it running for the next step.

  2. Inside the container, check all interfaces one by one with tcpdump and look for packages destined to 8.8.8.8. This must be docker0 according to the rules you've pasted to your question.

  3. Check your host's routing table and ensure that the default route, 0.0.0.0 is on the interface ens3

You should get enough information to solve the problem.