2026-03-22 · Security IncidentDockerUFW

Docker UFW Bypass: How Exposed Containers Lead to Server Compromise

UFW is active. The deny rule is listed. The Redis port is open to the internet anyway. This is how the Docker UFW bypass leads from misconfiguration to compromised server — and how to verify you're not currently affected.

The Docker UFW bypass is not a theoretical vulnerability. It's a misconfiguration that has exposed production databases, Redis instances, and internal APIs to the public internet thousands of times — on servers whose owners believed their firewall was protecting them.

How it happens

Linux packet routing evaluates iptables chains in order: PREROUTING → DOCKER → FORWARD → INPUT. UFW manages the INPUT chain. When a packet arrives destined for a Docker container port, Docker's rules in the FORWARD chain accept it before the packet ever reaches UFW's INPUT rules.

The result: a developer runs ufw deny 6379 to block Redis. They check ufw status and see the deny rule listed. They assume they're protected. Their Redis instance is publicly accessible anyway — through the DOCKER chain that UFW never touches.

Documented exposure patterns

Pattern 1 — Database exposure

Redis (:6379), MongoDB (:27017), PostgreSQL (:5432), and MySQL (:3306) bound to 0.0.0.0 via Docker port mappings are consistently found by Shodan scans. Unauthenticated Redis instances in particular have been used for cryptomining by scanning for port 6379 and issuing CONFIG SET commands to write SSH keys to ~/.ssh/authorized_keys.

Pattern 2 — Internal API exposure

Internal services (admin panels, metrics endpoints, internal APIs) deployed in Docker with ports: "PORT:PORT" and no authentication, intended to be "protected by the firewall", are accessible from the public internet. The firewall appears active. The service is reachable.

Pattern 3 — AI inference endpoint exposure

Ollama and other local LLM servers running in Docker with ports: "11434:11434" are discoverable via Shodan on port 11434. Exposed instances allow anyone to run inference on the host's hardware at no cost to the attacker.

The attack timeline

Day 0
Developer deploys Docker service with ports: "6379:6379". Adds ufw deny 6379. Checks status — looks protected.
Day 0–3
Automated Shodan-style scanners discover port 6379 open on the server's public IP. Add to target list.
Day 1–14
Unauthenticated Redis receives CONFIG SET commands. Attacker writes SSH key to root's authorized_keys or sets up a cron job to download and execute a cryptominer.
Day 14+
Owner notices CPU spike, unusual outbound traffic, or VPS provider flags the account for abuse. By this point the server has been running a miner for days or weeks.

Verification — check right now

# From another machine (mobile data, NOT your home network):
curl http://YOUR_SERVER_IP:6379
nc -zv YOUR_SERVER_IP 6379

# Or from the server itself — check what Docker exposed:
sudo iptables -L DOCKER --line-numbers | grep ACCEPT

The fix

Bind container ports to localhost only
# Before — exposed to internet:
ports:
  - "6379:6379"

# After — localhost only:
ports:
  - "127.0.0.1:6379:6379"
Or use DOCKER-USER chain for server-wide protection
sudo iptables -I DOCKER-USER -j DROP
sudo iptables -I DOCKER-USER -s 127.0.0.1 -j ACCEPT
sudo apt install iptables-persistent && sudo netfilter-persistent save

Related

Paste your ufw status verbose output to detect Docker bypass risk and exposed ports on your server.