Network setup for KVM guests
Host
Bridge setup
Install 'bridge-utils' :
sudo apt-get install bridge-utils 16h 7m
Add bridge device :
# 'br0' can be watherver you like.
brctl addbr br0
Edit '/etc/network/interfaces' to add a bridge device and configure it on startup :
# The loopback network interface
auto lo
iface lo inet loopback
# The primary network interface
# Change eth0 to refelct your actual if name
allow-hotplug eth0
# Disable DHCP on physical device and use it on br0 instead
iface eth0 inet manual
# Bridge setup
iface br0 inet dhcp
bridge_stp off
bridge_maxwait 0
bridge_fd 0
# Add physical interface and all vnetX virtual interfaces (in 0-99 range)
bridge_ports eth0 regex vnet[0-9]?[0-9]
# You can set the bridge device MAC address with
#bridge_hw XX:XX:XX:XX:XX:XX
If your DHCP server is configured to deliver fixed IP adresses based on MAC, replace eth0's MAC with br0's on your router in order to give it the same local IP.
Virsh : use bridge for network
Create an xml file with the following content :
nano /tmp/br0.xml
<network>
<name>br0</name>
<forward mode="bridge"/>
<bridge name="br0" />
</network>
Then set it as network :
virsh net-define /tmp/br0.xml
and start/autostart it :
virsh net-start br0
virsh net-autostart br0
You can also use 'virt-manager' and set your network via the XML editor.
(Optional) Add a route to your public IP range
# Edit to reflect your actual IP range and bridge device name
sudo ip route add 0.0.0.0/32 dev br0
See Configure a local and public IP below for the matching configuration on the guest.
Guest
(Optional) Basic nftables ruleset
The following ruleset accepts SSH and HTTP(s) by default.
In your '/etc/nftables.conf':
#!/usr/sbin/nft -f
flush ruleset
table inet firewall {
chain inbound_ipv4 {
# accepting ping (icmp-echo-request) for diagnostic purposes.
# However, it also lets probes discover this host is alive.
# This sample accepts them within a certain rate limit:
#
# icmp type echo-request limit rate 5/second accept
}
chain inbound_ipv6 {
# accept neighbour discovery otherwise connectivity breaks
#
icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept
# accepting ping (icmpv6-echo-request) for diagnostic purposes.
# However, it also lets probes discover this host is alive.
# This sample accepts them within a certain rate limit:
#
# icmpv6 type echo-request limit rate 5/second accept
}
chain inbound {
# By default, drop all traffic unless it meets a filter
# criteria specified by the rules that follow below.
type filter hook input priority 0; policy drop;
# Allow traffic from established and related packets, drop invalid
ct state vmap { established : accept, related : accept, invalid : drop }
# Allow loopback traffic.
iifname lo accept
# Jump to chain according to layer 3 protocol using a verdict map
meta protocol vmap { ip : jump inbound_ipv4, ip6 : jump inbound_ipv6 }
# Allow SSH on port TCP/22 and allow HTTP(S) TCP/80 and TCP/443
# for IPv4 and IPv6.
tcp dport { 22, 80, 443} accept
# Uncomment to enable logging of denied inbound traffic
# log prefix "[nftables] Inbound Denied: " counter drop
}
chain forward {
# Drop everything (assumes this device is not a router)
type filter hook forward priority 0; policy drop;
}
# no need to define output chain, default policy is accept if undefined.
}
source:Simple ruleset for a server
(Optional) Configure a local and public IP
Debian 10/11/12
Setup a guest with two network interfaces ; one for local IP and one for public IP.
You should get two network interfaces in the host, e.g ; enp1s0 and enp2s0.
In '/etc/network/interfaces' :
auto lo
iface lo inet loopback
# Use DHCP for enp1s0 to get a LAN IP
auto enp1s0
iface enp1s0 inet dhcp
# Set static public IP on enp2s0
auto enp2s0
iface enp2s0 inet static
# Edit to fit your range
address 0.0.0.1
broadcast 0.0.0.255
netmask 255.255.255.255
Then reboot the guest to apply these settings.
Debian 13 Cloud image
If you're using a cloud image, chances are you need to tell 'netplan' to use NetworkManager instead of systemd-networkd :
- Disable systemd-networkd :
sudo systemctl disable systemd-networkd sudo systemctl mask systemd-networkd sudo systemctl stop systemd-networkd - Install and enable NetworkManager:
sudo apt install network-manager sudo systemctl unmask NetworkManager sudo systemctl enable NetworkManager sudo systemctl start NetworkManager - Change netplan config to use NM by replacing the content of '/etc/netplan/90-default.yaml' with:
# Let NetworkManager manage all devices on this system. # For more information, see netplan(5). network: version: 2 renderer: NetworkManager - Configure your interfaces using 'nmcli' or 'nmtui'
- Reboot
Links
Sources
https://wiki.debian.org/KVM#Setting_up_bridge_networking
https://wiki.debian.org/BridgeNetworkConnections#Configuring_bridgingin.2Fetc.2Fnetwork.2Finterfaces
https://wiki.debian.org/QEMU#Networking
https://manpages.debian.org/bookworm/bridge-utils/bridge-utils-interfaces.5.en.html
https://wiki.libvirt.org/VirtualNetworking.html
https://wiki.debian.org/Netplan
https://www.linkedin.com/pulse/linux-networking-enable-networkmanager-disable-systemd-soheil-amiri
Related discussions
https://serverfault.com/questions/536114/libvirtd-getting-vps-to-use-existing-bridge
https://unix.stackexchange.com/questions/245628/configure-public-ip-addresses-in-kvm-vms
https://serverfault.com/questions/846834/how-to-assign-public-ip-to-kvm-virtual-machine-from-29-subnet#846986
https://serverfault.com/questions/461070/assign-public-and-private-ip-addresses-for-a-kvm-guest