Ubuntu 22.04 changed UFW's default firewall backend from iptables to nftables. For most people this change is completely invisible — UFW still works the same way from the command line. But if you're running Docker, or if you're mixing UFW with other firewall tools, this change matters and can cause rules to stop working in confusing ways.
What changed in Ubuntu 22.04
Ubuntu 22.04 ships with nftables as the default kernel firewall backend. When you install UFW on Ubuntu 22.04, it uses nftables under the hood instead of iptables. The UFW commands you already know (ufw allow, ufw deny, ufw status) all work the same — but the rules they generate are now nftables rules, not iptables rules.
# Check which backend UFW is using: sudo ufw status verbose cat /etc/default/ufw | grep "IPTABLES_BACKEND" # Check nftables rules directly: sudo nft list ruleset # Check iptables (will show nftables rules via compatibility layer): sudo iptables -L
Why this breaks Docker
Docker has been using iptables for network management since the beginning. When Docker starts, it inserts rules into iptables chains — DOCKER, DOCKER-USER, DOCKER-ISOLATION-STAGE-1 — to manage container networking and port forwarding.
On Ubuntu 22.04, Docker still uses iptables even though UFW is now using nftables. This means Docker's rules and UFW's rules are in completely separate systems that don't interact with each other. UFW doesn't know about Docker's containers. Docker doesn't know about UFW's deny rules.
The result is the classic Docker UFW bypass: you add a UFW deny rule for a port, but the Docker container on that port is still accessible from the internet because Docker's iptables rules bypass UFW's nftables rules entirely.
# Verify Docker is still using iptables on Ubuntu 22.04: sudo iptables -L DOCKER --line-numbers # You'll see Docker's rules here even though UFW uses nftables
Check your current UFW backend
cat /etc/default/ufw
Look for IPT_SYSCTL and IPTABLES_BACKEND. On Ubuntu 22.04 you'll typically see the backend set to nftables or the file may not specify it explicitly (defaulting to nftables).
# Also check the actual active firewall: sudo nft list tables # If you see tables like "inet ufw6" — UFW is using nftables sudo iptables -L INPUT | head -5 # If you see DOCKER chains — Docker is using iptables
The fix: bind Docker ports to localhost
The cleanest fix for the Docker/nftables conflict is to not expose Docker ports publicly in the first place. Bind all container ports to 127.0.0.1 and use Nginx or Traefik as a reverse proxy for public access.
# In docker-compose.yml — bind to localhost only:
services:
myapp:
ports:
- "127.0.0.1:3000:3000" # Only accessible locally
# NOT: "3000:3000" — this binds to 0.0.0.0 and bypasses UFW
db:
ports:
- "127.0.0.1:5432:5432" # Database never public
With this setup, the container ports are only accessible via localhost. Nginx on port 80/443 (which UFW allows) proxies traffic to the container. Docker's iptables bypass becomes irrelevant because there's nothing public to bypass to.
Alternative: force Docker to use iptables compatibility mode
If you need Docker ports to be directly accessible and want UFW to control them, you can configure Docker to use iptables in a way that interacts better with nftables:
# /etc/docker/daemon.json:
{
"iptables": true,
"ip6tables": true
}
sudo systemctl restart docker
Note: Even with this setting, Docker's iptables rules and UFW's nftables rules operate in separate subsystems. The most reliable approach remains binding containers to 127.0.0.1 rather than relying on firewall rules to block container ports.
What about Ubuntu 20.04?
Ubuntu 20.04 uses iptables as the default backend. UFW and Docker both use iptables, so there's a different interaction — Docker's rules can actually interfere with UFW's rules in iptables. The Docker UFW bypass problem exists on both versions, just through different mechanisms.
# On Ubuntu 20.04 — check iptables backend: sudo update-alternatives --display iptables # Should show iptables-legacy or iptables-nft
Quick summary
- Ubuntu 22.04: UFW uses nftables, Docker uses iptables — they don't interact
- Ubuntu 20.04: UFW uses iptables, Docker uses iptables — they interact but Docker bypasses UFW
- On both versions: bind container ports to 127.0.0.1 to avoid the problem entirely
- UFW commands work the same on both versions — the backend change is invisible to daily use
Audit your UFW rules for Docker bypass risk, nftables conflicts, and missing default-deny on Ubuntu 22.04.
Open Firewall Auditor →