A firewall for Docker that blocks accidental port exposure

Post Reply
User avatar
myVesta
Site Admin
Posts: 972
Joined: Fri Jun 19, 2020 9:59 am
Has thanked: 10 times
Been thanked: 6 times

When you start a Docker container with the parameter "-p 0.0.0.0:port_number:port_number" or in the docker-compose.yml file you have set "ports: ["port_number:port_number"]", in other words, when you expose an internal port to be available to the host server or other dockers, keep in mind that those ports actually become available over the Internet (anyone on the Internet can access that port on your server).

Even if you put DROP in the INPUT chain in iptables, those ports will still be visible over the Internet.

This happens because 'dockerd' inserts DNAT rules into the nat/PREROUTING and nat/DOCKER chains before your standard filter/INPUT chain.
Namely, a TCP/UDP packet comes from the Internet, goes through DNAT in nat/DOCKER, and ends up in filter/DOCKER.
Then the package is no longer intended for eth0 but for docker-bridge (docker0), so the package does not even reach the DROP action and the INPUT chain.

To ensure that no Docker ports are exposed to the Internet, do the following:

Code: Select all

wget -nv https://dl.myvestacp.com/install-docker-firewall.sh -O install-docker-firewall.sh
bash install-docker-firewall.sh
The source code of the script is:

Code: Select all

#!/bin/bash

# Get network interface for the internet 
iface=$(ip r get 8.8.8.8 | grep -oP 'dev \K\S+')

cat <<EOF > /usr/local/sbin/docker-fw.sh
#!/bin/sh
iptables -C DOCKER-USER -i $iface -p tcp -j DROP 2>/dev/null || \
iptables -I DOCKER-USER -i $iface -p tcp -j DROP
iptables -C DOCKER-USER -i $iface -p udp -j DROP 2>/dev/null || \
iptables -I DOCKER-USER -i $iface -p udp -j DROP
EOF
chmod +x /usr/local/sbin/docker-fw.sh

cat <<EOF > /etc/systemd/system/docker-fw.service

[Unit]
Description=Post-Docker firewall rules
After=docker.service network-online.target
Requires=docker.service

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/docker-fw.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now docker-fw.service

Tags:
Post Reply