- Published on
KVM bridge network on Ubuntu Desktop
- Authors
- Name
- Vincenzo Campagnano
Even if is not very common, I were using KVM on Ubuntu Desktop just to give it a shot and test his performance.
An useful trick using a VM is to set his network interface (NIC) in bridge mode. Doing it you can see the IP address of your VM inside the LAN as if it's a real (separated) machine connected to your network.
One of the many advantages is that you can reach the VM from other systems connected to the same LAN as well.
Let's break in in the setup steps.
Add a bridge interface to Ubuntu desktop using nmcli
In the examples below "eth0" is the name of my physical interface. By default on Ubuntu and most distributions that will almost certainly be different, for example: "eno1", "ens1", or "enp2s0".
To see what everything looks like before starting:
nmcli con show
I renamed "Wired Connection 1' to the name of my physical interface:
sudo nmcli con mod 'Wired Connection 1' con-name eth0
So let's start out by creating the bridge itself:
nmcli con add ifname br0 type bridge con-name br0
Now add the physical interface as its slave:
nmcli con add type bridge-slave ifname eth0 master br0
Disable STP:
nmcli con mod br0 bridge.stp no
Now down the physical interface:
nmcli con down eth0
For this machine I want a static address:
nmcli con mod br0 ipv4.addresses 10.1.1.16/24
nmcli con mod br0 ipv4.gateway 10.1.1.1
nmcli con mod br0 ipv4.dns '10.1.1.1,8.8.8.8,8.8.4.4'
Don't forget to set your search domain:
nmcli con mod br0 ipv4.dns-search 'example.com'
Then tell Network Manager this will be a manual connection:
nmcli con mod br0 ipv4.method manual
Finally, bring up the new bridge interface:
nmcli con up br0
Run nmcli device show
to confirm your changes, and then restart NetworkManager (sudo systemctl restart NetworkManager.service
) to make sure the configuration sticks.
Setting up a bridged network for KVM guests
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
During my experiment, 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 for virbr0
and/or libvirt
with with sudo iptables -L -v -n
.
My versions: 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:
sudo iptables -A INPUT -i br0 -j ACCEPT
sudo iptables -A FORWARD -i br0 -j ACCEPT
sudo iptables -A FORWARD -o br0 -j ACCEPT
sudo iptables -A OUTPUT -o br0 -j ACCEPT
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:
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
Make it persistent by editing /etc/sysctl.conf
:
sudo nano /etc/sysctl.conf
Uncomment or add:
net.ipv4.ip_forward=1
Apply:
sudo sysctl -p
3. Restart the Network and Verify
sudo systemctl restart NetworkManager
sudo systemctl restart libvirtd
Check the rules:
sudo iptables -L -v -n
4. Verify the VM Network
Inside the VM, check:
ip a
If still no IP, try manually requesting one:
sudo dhclient
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:
sudo apt install iptables-persistent -y
sudo netfilter-persistent save
This ensures the rules stay after a reboot.
And that's all
Happy virtualization,
vinzcamp8
References
- https://gist.github.com/plembo/f7abd2d9b6f76e7afdece02dae7e5097
- you can see my comment on here https://gist.github.com/plembo/a7b69f92953a76ab2d06533754b5e2bb
- other solution (maybe faster) but not tested by me https://www.redhat.com/en/blog/setup-network-bridge-VM