This will work with either networkd or NetworkManager as a resolver. In fact, this is the only way to do bridged KVM (libvirtd) networking with NetworkManager.
If you're using NetworkManager (on a desktop or laptop, for example) on your KVM host, follow these instructions to set up a bridge interface.
Once you have the host bridge set up, proceed as follows:
- Create a bridge network device inside KVM. Edit and save the below text as file host-bridge.xml:
<network>
<name>host-bridge</name>
<forward mode="bridge"/>
<bridge name="br0"/>
</network>
Then execute these commands (as a user in the libvirt group):
$ virsh net-define host-bridge.xml
$ virsh net-start host-bridge
$ virsh net-autostart host-bridge
- Make it possible for hosts outside of KVM to talk to your bridged guest by making the following changes on the KVM host.
Load the br_netfilter module:
$ sudo modprobe br_netfilter
Persist on reboot by creating /etc/modules-load.d/br_netfilter.conf:
$ sudo echo "br_netfilter" > /etc/modules-load.d/br_netfilter.conf
Create /etc/sysctl.d/10-bridge.conf:
# Do not filter packets crossing a bridge
net.bridge.bridge-nf-call-ip6tables=0
net.bridge.bridge-nf-call-iptables=0
net.bridge.bridge-nf-call-arptables=0
Apply the config now:
$ sudo sysctl -p /etc/sysctl.d/10-bridge.conf
Check result:
$ sudo sysctl -a | grep "bridge-nf-call"
- Configure the guest to use host-bridge. Open up the Virtual Machine Manager and then select the target guest. Go to the NIC device. The drop down for "Network Source" should now include a device called "Virtual netowrk 'host-bridge'". The "Bridge network device model" will be "virtio" if that's your KVM configuration's default.
Select that "host-bridge" device.
If you inspect the guest's XML (by using virsh dumplxml guestname
), it shoud look something like this:
<interface type='network'>
<mac address='52:54:8b:d9:bf:a2'/>
<source network='host-bridge'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>'
Be sure to save your changes!
-
Go up to your router and add a DHCP reservation and DNS mapping for the guest (assuming you want a dynamic address and want to be able to easily find the guest later). Otherwise, be prepared to manually configure networking on the guest.
-
Start (or restart) the guest.
I needed to do these steps in addition
I followed all the steps but my guest VM still didn't get an IP in the end.
In my case the problem was in the default firewall rules enabled by
libvirt
on the host. You can check if there are rules forvirbr0
and/orlibvirt
with withsudo iptables -L -v -n
.My setup:
ubuntu desktop 22.04.05
,libvirtd (libvirt) 8.0.0
.By default, KVM sets up firewall rules for its NAT (
virbr0
), but since you’re using a bridge (br0
), you need to allow traffic explicitly. These are the extra steps I've done:1. Allow Traffic for br0 in iptables
Try adding the following rules to accept traffic on br0:
This allows all traffic in/out of
br0
.2. Enable IP Forwarding (If Needed)
Since
virbr0
uses NAT, it might have forwarding already enabled. If not, enable it:Make it persistent by editing
/etc/sysctl.conf
:Uncomment or add:
Apply:
3. Restart the Network and Verify
Check the rules:
4. Verify the VM Network
Inside the VM, check:
If still no IP, try manually requesting one:
Also check and correct your network configurations in
/etc/netplan/
to automatically request an IP on the right interface.5. Make iptables Rules Persistent
If this worked, save the rules:
This ensures the rules stay after a reboot.