Set up Linux network bridges to enable communication between virtual machines, containers, and physical networks. Configure bridge interfaces using netplan, bridge utilities, and implement security policies for production environments.
Prerequisites
- Root or sudo access
- Physical network interface
- Basic understanding of Linux networking
- Virtual machine or container runtime (optional)
What this solves
Network bridges create virtual switches that connect multiple network interfaces, enabling virtual machines and containers to communicate with each other and access physical networks. This tutorial shows you how to configure bridge interfaces for VM networking, container communication, and implement security policies using modern Linux networking tools.
Step-by-step configuration
Update system packages
Start by updating your package manager to ensure you have the latest networking tools available.
sudo apt update && sudo apt upgrade -y
Install bridge utilities
Install the bridge utilities package which provides brctl and other bridge management tools for Linux networking.
sudo apt install -y bridge-utils net-tools vlan
Enable IP forwarding
Enable IP forwarding to allow traffic to pass between bridge interfaces and enable routing between networks.
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Configure bridge interface with Netplan (Ubuntu/Debian)
Create a netplan configuration for a bridge interface that will serve as the primary bridge for VM and container networking.
network:
version: 2
renderer: networkd
ethernets:
ens18:
dhcp4: false
dhcp6: false
bridges:
br0:
interfaces: [ens18]
dhcp4: true
parameters:
stp: true
forward-delay: 4
br1:
dhcp4: false
addresses:
- 192.168.100.1/24
parameters:
stp: true
forward-delay: 4
ip link show to list available interfaces.Configure bridge interface with NetworkManager (AlmaLinux/Rocky/Fedora)
Use NetworkManager to create bridge interfaces on Red Hat-based systems with nmcli commands.
# Create primary bridge for external connectivity
sudo nmcli connection add type bridge con-name br0 ifname br0
sudo nmcli connection modify br0 bridge.stp yes
sudo nmcli connection modify br0 ipv4.method auto
Add physical interface to bridge
sudo nmcli connection add type bridge-slave con-name br0-port1 ifname ens18 master br0
Create internal bridge for VM/container communication
sudo nmcli connection add type bridge con-name br1 ifname br1
sudo nmcli connection modify br1 bridge.stp yes
sudo nmcli connection modify br1 ipv4.method manual ipv4.addresses 192.168.100.1/24
Activate bridges
sudo nmcli connection up br0
sudo nmcli connection up br1
Apply network configuration
Apply the network configuration and verify that bridge interfaces are created successfully.
sudo netplan apply
sudo systemctl restart systemd-networkd
Configure VM networking with bridge interface
Set up virtual machine networking to use the bridge interface for direct network access and communication.
bridged
# Define and start the libvirt network
sudo virsh net-define /etc/libvirt/qemu/networks/bridged.xml
sudo virsh net-start bridged
sudo virsh net-autostart bridged
Configure container bridge networking
Create custom Docker bridge networks that use your configured bridge interfaces for container communication.
# Create custom bridge network for containers
sudo docker network create \
--driver bridge \
--subnet=192.168.100.0/24 \
--gateway=192.168.100.1 \
--opt parent=br1 \
container-bridge
Create VLAN-tagged bridge network
sudo docker network create \
--driver bridge \
--subnet=192.168.200.0/24 \
--gateway=192.168.200.1 \
--opt parent=br1.200 \
vlan-bridge
Implement bridge security policies
Configure bridge security using iptables rules and bridge filtering to control traffic flow between networks.
#!/bin/bash
Enable bridge netfilter
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables
echo 1 > /proc/sys/net/bridge/bridge-nf-call-ip6tables
Allow established connections
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
Allow traffic within bridge networks
iptables -A FORWARD -i br0 -o br0 -j ACCEPT
iptables -A FORWARD -i br1 -o br1 -j ACCEPT
Control inter-bridge communication
iptables -A FORWARD -i br0 -o br1 -j DROP
iptables -A FORWARD -i br1 -o br0 -m state --state NEW -j DROP
Log dropped packets
iptables -A FORWARD -j LOG --log-prefix "BRIDGE-DROP: "
iptables -A FORWARD -j DROP
sudo chmod 755 /etc/iptables/bridge-rules.sh
sudo /etc/iptables/bridge-rules.sh
Configure VLAN integration
Set up VLAN tagging on bridge interfaces to enable network segmentation and traffic isolation.
# Create VLAN interfaces
sudo vconfig add br1 100
sudo vconfig add br1 200
Configure VLAN interface addresses
sudo ip addr add 192.168.101.1/24 dev br1.100
sudo ip addr add 192.168.201.1/24 dev br1.200
Bring up VLAN interfaces
sudo ip link set dev br1.100 up
sudo ip link set dev br1.200 up
Configure bridge monitoring and logging
Set up monitoring for bridge interfaces to track traffic, detect issues, and log network events.
[Unit]
Description=Bridge Interface Monitor
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/bridge-monitor.sh
Restart=always
User=root
[Install]
WantedBy=multi-user.target
#!/bin/bash
while true; do
# Log bridge status
echo "$(date): Bridge status" >> /var/log/bridge-monitor.log
brctl show >> /var/log/bridge-monitor.log
# Check bridge connectivity
for bridge in br0 br1; do
if ip link show $bridge | grep -q "state UP"; then
echo "$(date): $bridge is UP" >> /var/log/bridge-monitor.log
else
echo "$(date): WARNING - $bridge is DOWN" >> /var/log/bridge-monitor.log
fi
done
sleep 300
done
sudo chmod 755 /usr/local/bin/bridge-monitor.sh
sudo systemctl enable --now bridge-monitor
Optimize bridge performance
Apply performance tuning to bridge interfaces for high-throughput networking workloads.
# Bridge performance tuning
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-filter-vlan-tagged = 0
Network buffer tuning
net.core.netdev_max_backlog = 5000
net.core.rmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_default = 262144
net.core.wmem_max = 16777216
Bridge forwarding database
net.bridge.bridge-nf-filter-pppoe-tagged = 0
sudo sysctl -p /etc/sysctl.d/99-bridge-performance.conf
Verify your setup
Check that bridge interfaces are configured correctly and functioning properly.
# Check bridge status
brctl show
Verify bridge interfaces
ip addr show br0
ip addr show br1
Test bridge connectivity
ping -c 4 -I br0 8.8.8.8
Check bridge forwarding database
brctl showmacs br0
Verify Docker networks
sudo docker network ls
Test VM network connectivity
sudo virsh net-list --all
Check iptables rules
sudo iptables -L FORWARD -v -n
Monitor bridge traffic
sudo tcpdump -i br0 -c 10
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Bridge interface not created | Network configuration syntax error | Check netplan syntax: sudo netplan --debug apply |
| VMs cannot reach network | Bridge not connected to physical interface | Verify bridge ports: brctl show |
| Container networking fails | Docker bridge conflicts | Remove conflicting networks: docker network prune |
| Poor bridge performance | Default buffer sizes too small | Apply performance tuning: sysctl -p /etc/sysctl.d/99-bridge-performance.conf |
| VLAN traffic not working | VLAN module not loaded | Load 8021q module: sudo modprobe 8021q |
| Bridge loops detected | STP not enabled | Enable spanning tree: brctl stp br0 on |
Next steps
- Configure network bonding and VLAN tagging for high availability and network segmentation
- Configure Tailscale mesh VPN with subnet routing and ACL policies for secure network access
- Configure advanced iptables rules for bridge network security
- Set up Open vSwitch for advanced virtual machine networking
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Default values
PHYSICAL_INTERFACE=""
BRIDGE_SUBNET="192.168.100.0/24"
BRIDGE_IP="192.168.100.1"
# Logging functions
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# Usage message
usage() {
cat << EOF
Usage: $0 [-i interface] [-s subnet] [-g gateway]
Options:
-i interface Physical network interface to bridge (auto-detected if not specified)
-s subnet Bridge subnet (default: 192.168.100.0/24)
-g gateway Bridge gateway IP (default: 192.168.100.1)
-h Show this help message
Examples:
$0 -i ens18
$0 -i eth0 -s 192.168.200.0/24 -g 192.168.200.1
EOF
exit 1
}
# Parse command line arguments
while getopts "i:s:g:h" opt; do
case $opt in
i) PHYSICAL_INTERFACE="$OPTARG" ;;
s) BRIDGE_SUBNET="$OPTARG" ;;
g) BRIDGE_IP="$OPTARG" ;;
h) usage ;;
*) usage ;;
esac
done
# Cleanup function
cleanup() {
log_error "Installation failed. Cleaning up..."
# Remove any partial configurations
if [ -f /etc/netplan/99-bridge.yaml.backup ]; then
mv /etc/netplan/99-bridge.yaml.backup /etc/netplan/99-bridge.yaml 2>/dev/null || true
fi
exit 1
}
trap cleanup ERR
# Check if running as root
if [[ $EUID -ne 0 ]]; then
log_error "This script must be run as root"
exit 1
fi
# Detect distribution
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_INSTALL="apt install -y"
PKG_UPDATE="apt update && apt upgrade -y"
NETWORK_METHOD="netplan"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf update -y"
NETWORK_METHOD="networkmanager"
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
PKG_UPDATE="yum update -y"
NETWORK_METHOD="networkmanager"
;;
*)
log_error "Unsupported distribution: $ID"
exit 1
;;
esac
else
log_error "Cannot detect distribution"
exit 1
fi
# Auto-detect network interface if not specified
if [ -z "$PHYSICAL_INTERFACE" ]; then
PHYSICAL_INTERFACE=$(ip route | grep default | head -1 | awk '{print $5}')
if [ -z "$PHYSICAL_INTERFACE" ]; then
log_error "Cannot auto-detect network interface. Please specify with -i option."
exit 1
fi
log_info "Auto-detected network interface: $PHYSICAL_INTERFACE"
fi
# Verify interface exists
if ! ip link show "$PHYSICAL_INTERFACE" &>/dev/null; then
log_error "Network interface $PHYSICAL_INTERFACE does not exist"
exit 1
fi
log_info "[1/8] Starting bridge network configuration for $ID"
# Update system packages
log_info "[2/8] Updating system packages..."
$PKG_UPDATE
# Install bridge utilities
log_info "[3/8] Installing bridge utilities..."
if [ "$PKG_MGR" = "apt" ]; then
$PKG_INSTALL bridge-utils net-tools vlan iproute2
else
$PKG_INSTALL bridge-utils net-tools iproute
fi
# Enable IP forwarding
log_info "[4/8] Enabling IP forwarding..."
if ! grep -q "net.ipv4.ip_forward = 1" /etc/sysctl.conf; then
echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
fi
if ! grep -q "net.ipv6.conf.all.forwarding = 1" /etc/sysctl.conf; then
echo 'net.ipv6.conf.all.forwarding = 1' >> /etc/sysctl.conf
fi
sysctl -p
# Configure bridge based on network method
log_info "[5/8] Configuring bridge interfaces..."
if [ "$NETWORK_METHOD" = "netplan" ]; then
# Backup existing netplan config
if [ -f /etc/netplan/99-bridge.yaml ]; then
cp /etc/netplan/99-bridge.yaml /etc/netplan/99-bridge.yaml.backup
fi
# Create netplan bridge configuration
cat > /etc/netplan/99-bridge.yaml << EOF
network:
version: 2
renderer: networkd
ethernets:
$PHYSICAL_INTERFACE:
dhcp4: false
dhcp6: false
bridges:
br0:
interfaces: [$PHYSICAL_INTERFACE]
dhcp4: true
parameters:
stp: true
forward-delay: 4
br1:
dhcp4: false
addresses:
- $BRIDGE_IP/$(echo $BRIDGE_SUBNET | cut -d'/' -f2)
parameters:
stp: true
forward-delay: 4
EOF
chmod 644 /etc/netplan/99-bridge.yaml
# Apply netplan configuration
log_info "[6/8] Applying netplan configuration..."
netplan apply
systemctl restart systemd-networkd
else
# NetworkManager configuration
# Create primary bridge for external connectivity
nmcli connection add type bridge con-name br0 ifname br0 2>/dev/null || true
nmcli connection modify br0 bridge.stp yes
nmcli connection modify br0 ipv4.method auto
# Add physical interface to bridge
nmcli connection add type bridge-slave con-name br0-port1 ifname $PHYSICAL_INTERFACE master br0 2>/dev/null || true
# Create internal bridge for VM/container communication
nmcli connection add type bridge con-name br1 ifname br1 2>/dev/null || true
nmcli connection modify br1 bridge.stp yes
nmcli connection modify br1 ipv4.method manual ipv4.addresses $BRIDGE_IP/$(echo $BRIDGE_SUBNET | cut -d'/' -f2)
# Apply NetworkManager configuration
log_info "[6/8] Applying NetworkManager configuration..."
nmcli connection up br0 2>/dev/null || true
nmcli connection up br1 2>/dev/null || true
systemctl restart NetworkManager
fi
# Configure basic iptables rules for bridge security
log_info "[7/8] Configuring bridge security policies..."
# Enable bridge netfilter
modprobe br_netfilter
echo 'br_netfilter' >> /etc/modules-load.d/bridge.conf 2>/dev/null || echo 'br_netfilter' >> /etc/modules
# Basic iptables rules for bridge security
iptables -I FORWARD -m physdev --physdev-is-bridged -j ACCEPT 2>/dev/null || true
iptables -I FORWARD -i br1 -o br1 -j ACCEPT 2>/dev/null || true
# Save iptables rules based on distribution
if [ "$PKG_MGR" = "apt" ]; then
if command -v netfilter-persistent &> /dev/null; then
netfilter-persistent save
fi
else
if command -v iptables-save &> /dev/null; then
iptables-save > /etc/sysconfig/iptables 2>/dev/null || true
fi
fi
# Verification
log_info "[8/8] Verifying bridge configuration..."
# Wait for interfaces to come up
sleep 5
# Check if bridges exist
if ip link show br0 &>/dev/null && ip link show br1 &>/dev/null; then
log_success "Bridge interfaces br0 and br1 created successfully"
else
log_error "Failed to create bridge interfaces"
exit 1
fi
# Check bridge status
if brctl show | grep -q br0 && brctl show | grep -q br1; then
log_success "Bridge utilities functioning correctly"
else
log_warning "Bridge utilities may not be functioning properly"
fi
# Check IP forwarding
if [ "$(cat /proc/sys/net/ipv4/ip_forward)" = "1" ]; then
log_success "IP forwarding enabled"
else
log_warning "IP forwarding not enabled"
fi
# Display final status
echo
log_success "Bridge network configuration completed successfully!"
echo
echo "Bridge Status:"
brctl show
echo
echo "IP Configuration:"
ip addr show br0 2>/dev/null || true
ip addr show br1 2>/dev/null || true
echo
log_info "You can now use these bridges for VM and container networking"
log_info "Primary bridge (br0): External connectivity"
log_info "Internal bridge (br1): VM/container communication on $BRIDGE_SUBNET"
Review the script before running. Execute with: bash install.sh