When working with LXC containers on Ubuntu hosts, many administrators need to assign dedicated public IPs to containers while maintaining proper network isolation. The common bridge networking approach often leads to routing conflicts where:
# Common symptoms include:
- Host responding to container IPs
- Extremely slow container boot times
- "Redirect Host" errors in ping/traceroute
- Duplicate IP assignments in lxc-ls output
First, let's examine the correct host bridge setup in /etc/network/interfaces:
auto br0
iface br0 inet static
address HOST_PUBLIC_IP/24
gateway HOST_GATEWAY
bridge_ports eth0
bridge_stp off
bridge_fd 0
bridge_maxwait 0
For each container, remove any IP configuration from the LXC config and instead handle it in the container's interfaces file:
# /var/lib/lxc/CONTAINER_NAME/config
lxc.network.type = veth
lxc.network.link = br0
lxc.network.hwaddr = 00:16:3e:XX:XX:XX
lxc.network.flags = up
Inside the container (/etc/network/interfaces), use this precise configuration:
auto eth0
iface eth0 inet static
address CONTAINER_PUBLIC_IP/24
gateway HOST_GATEWAY
dns-nameservers 8.8.8.8 8.8.4.4
post-up ip route add HOST_GATEWAY dev eth0
post-up ip route add default via HOST_GATEWAY
These sysctl settings are essential for proper routing:
# /etc/sysctl.conf
net.ipv4.ip_forward=1
net.bridge.bridge-nf-call-iptables=0
net.bridge.bridge-nf-call-ip6tables=0
net.bridge.bridge-nf-call-arptables=0
If you encounter the "Redirect Host" error, check these solutions:
# Verify ARP filtering is disabled
echo 0 > /proc/sys/net/ipv4/conf/all/arp_filter
echo 0 > /proc/sys/net/ipv4/conf/br0/arp_filter
# Ensure no duplicate IP assignments
ip addr show | grep "YOUR_PUBLIC_IP"
Here's a real-world configuration that works reliably:
# Host bridge config
auto br0
iface br0 inet static
address 203.0.113.45/24
gateway 203.0.113.1
bridge_ports eth0
bridge_stp off
# Container config (LXC)
lxc.network.type = veth
lxc.network.link = br0
lxc.network.hwaddr = 00:16:3e:a1:b2:c3
# Container interfaces
auto eth0
iface eth0 inet static
address 203.0.113.46/24
gateway 203.0.113.1
post-up ip route add 203.0.113.1 dev eth0
post-up ip route add default via 203.0.113.1
When working with LXC containers that require direct public internet access, bridging is often the preferred approach. The typical setup involves:
# Host /etc/network/interfaces
auto br0
iface br0 inet static
bridge_ports eth0
bridge_fd 0
address HOST_PUBLIC_IP
netmask 255.255.255.0
gateway PUBLIC_GATEWAY
dns-nameservers 8.8.8.8
The key to making this work lies in proper container configuration. Here's what your LXC config should contain:
# /var/lib/lxc/CONTAINER_NAME/config
lxc.network.type = veth
lxc.network.link = br0
lxc.network.flags = up
lxc.network.hwaddr = RANDOM_MAC_ADDRESS
The most frequent issues I've encountered (and their solutions):
# Problem: IP conflict between host and container
# Solution: Remove IP aliases from host
sudo ip addr del PUBLIC_IP/32 dev eth0
# Problem: Routing loops
# Solution: Ensure proper ARP filtering
echo 1 > /proc/sys/net/ipv4/conf/all/arp_filter
echo 1 > /proc/sys/net/ipv4/conf/br0/arp_filter
Here's a working example of the container's /etc/network/interfaces:
auto eth0
iface eth0 inet static
address CONTAINER_PUBLIC_IP
netmask 255.255.255.255
pointopoint GATEWAY_IP
post-up route add GATEWAY_IP dev eth0
post-up route add default gw GATEWAY_IP
dns-nameservers 8.8.8.8
To verify your setup is working correctly:
# From host:
ping CONTAINER_IP
lxc-attach -n CONTAINER_NAME -- ping 8.8.8.8
# Check routes:
ip route show
bridge link show
For more complex scenarios, consider these additional settings:
# Prevent NAT issues
echo 0 > /proc/sys/net/bridge/bridge-nf-call-iptables
# Improve performance
echo 0 > /proc/sys/net/bridge/bridge-nf-call-arptables