Resolving Docker-Libvirt Network Conflicts: UFW Bridge Fix for Ubuntu 18.04


2 views

When Docker and Libvirt coexist on Ubuntu 18.04 with UFW firewall management, their iptables rules can create bridge network conflicts. The core symptom manifests as:

  • Host unable to ping Libvirt/KVM guests
  • Interrupted communication between bridge interfaces
  • UFW port forwarding rules failing for Docker containers

Docker's default iptables rules interfere with Libvirt's bridge (br0) forwarding. While iptables -I FORWARD -i br0 -o br0 -j ACCEPT works temporarily, we need a persistent solution that:

  1. Maintains security through UFW
  2. Preserves Docker container networking
  3. Survives system reboots

Edit UFW's before.rules to permanently allow bridge traffic:

sudo nano /etc/ufw/before.rules

Add this rule before the final COMMIT:

# Allow Libvirt bridge traffic
-A ufw-before-forward -i br0 -o br0 -j ACCEPT

After saving the file, apply changes and verify:

sudo ufw disable && sudo ufw enable
sudo iptables -L FORWARD -v | grep br0

Expected output should show the br0-to-br0 forwarding rule.

Solution Pros Cons
Disable Docker iptables Fixes bridge communication Breaks container networking
Manual iptables rule Immediate effect Not persistent across reboots
UFW before.rules modification Persistent and secure Requires one-time config

For customized Docker networking while preserving Libvirt:

# /etc/docker/daemon.json
{
  "iptables": true,
  "bridge": "none",
  "fixed-cidr": "10.58.26.0/24",
  "default-gateway": "10.58.26.1"
}

Remember to restart services after changes:

sudo systemctl restart docker libvirtd

While our solution opens br0 bridge traffic, it maintains:

  • UFW's default deny policy
  • Stateful packet inspection
  • Logging capabilities

For production environments, consider adding rate limiting:

-A ufw-before-forward -i br0 -o br0 -m limit --limit 60/minute -j ACCEPT

When Docker and libvirt coexist on the same Ubuntu 18.04 system with UFW firewall management, we encounter network bridge interference. Docker's default iptables rules disrupt communication between the host and libvirt guests via br0 bridge, while disabling Docker's iptables breaks container networking.

The fundamental issue stems from Docker manipulating the FORWARD chain in ways that block bridge traffic. Examining the current rules reveals the problem:


sudo iptables -L FORWARD -v
Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DOCKER-USER  all  --  any    any     anywhere             anywhere            
    0     0 DOCKER-ISOLATION-STAGE-1  all  --  any    any     anywhere             anywhere            
    0     0 ACCEPT     all  --  any    docker0  anywhere             anywhere             ctstate RELATED,ESTABLISHED
    0     0 DOCKER     all  --  any    docker0  anywhere             anywhere            
    0     0 ACCEPT     all  --  docker0 !docker0  anywhere             anywhere            
    0     0 ACCEPT     all  --  docker0 docker0  anywhere             anywhere            

To maintain security while fixing the bridge connectivity, we need to modify UFW's before.rules:


sudo nano /etc/ufw/before.rules

Add this rule before the final COMMIT line:


# Allow bridged traffic for libvirt
-A ufw-before-forward -i br0 -o br0 -j ACCEPT

After implementing the solution, verify both Docker and libvirt functionality:


# Test libvirt connectivity
ping -c 4 [libvirt_guest_ip]

# Test Docker container networking
docker run --rm -it -p 8080:80 nginx
curl localhost:8080

# Check iptables rules persistence
sudo iptables -L FORWARD -v | grep br0

Several other solutions were evaluated but rejected for security or functionality reasons:

  • Disabling Docker's iptables (breaks container networking)
  • Adding manual iptables rules (not persistent across reboots)
  • Using Docker's --iptables=false option (limits functionality)

The implemented solution maintains security because:

  • It only allows traffic between interfaces on the same bridge
  • UFW still controls all other forwarding traffic
  • Docker's security rules remain intact for external traffic

If issues persist after implementation:


# Check UFW status with verbose output
sudo ufw status verbose

# Verify rule processing order
sudo iptables -L -v -n --line-numbers

# Restart networking components
sudo systemctl restart ufw docker libvirtd