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:
- Maintains security through UFW
- Preserves Docker container networking
- 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