Docker UFW Bypass

Docker UFW bypass is a known misconfiguration where Docker's iptables rules expose container ports to the internet, ignoring UFW's deny rules.
DockerUFWiptablesFirewallSecurity

Docker UFW bypass occurs because Docker inserts its own iptables rules directly into the DOCKER chain, which is evaluated before UFW's INPUT chain rules. When you run a container with -p 8080:80 or set ports: in docker-compose.yml, Docker adds an iptables ACCEPT rule that allows external traffic to reach the container regardless of your ufw deny rules.

This is not a bug — it's Docker's intended behavior for container networking. The problem is that most system administrators assume UFW protects all ports on the server. For standalone services this is true. For Dockerized services it is not, unless you explicitly configure Docker to respect UFW.

Why This Happens

Linux packet flow for incoming traffic evaluates iptables chains in order: PREROUTING → DOCKER → FORWARD → INPUT. UFW manages the INPUT chain. Docker manages the DOCKER and FORWARD chains. A packet destined for a Docker container never reaches the INPUT chain — it's routed through FORWARD before UFW can block it.

How to Fix It

The standard fix is to add DOCKER-USER chain rules or to bind container ports only to 127.0.0.1 (e.g., 127.0.0.1:8080:80) so Docker does not expose the port on the public interface. For server-wide protection, the /etc/docker/daemon.json approach with "iptables": false is an option but breaks Docker's networking for external container access.

Related Tools

Fix Guides

Frequently Asked Questions

Does UFW protect Docker containers?
No. UFW manages the Linux INPUT chain. Docker containers use the FORWARD chain, which UFW does not control by default. Docker ports are accessible from the internet even if UFW has no allow rule for them.
How do I check if Docker is bypassing UFW?
Run: sudo iptables -L DOCKER --line-numbers. Any ACCEPT rules in that chain bypass UFW. You can also use the ConfigClarity Firewall Auditor — paste your ufw status verbose output and it will flag Docker bypass risk.
What is the safest Docker port binding?
Bind to 127.0.0.1: use 127.0.0.1:8080:80 in docker-compose.yml. This exposes the port only on the loopback interface, accessible via Nginx reverse proxy but not directly from the internet.

Related Fix Guides