KVM provides NAT based networking to enable guest operating systems to get connectivity to the outside world. The guests sharing the same bridge are however able to communicate to each other even if no physical connection is made on the physical interface of the host. This default configuration makes it easy to get started with KVM without a lot of configuration.
NAT as the default config is convenient but has some short comings. Read more
- NAT used private IP addresses, this makes it difficult to use public IP addresses or your own custom IP addresses.
- Guest operating systems are not visible outside the host operating system. This means you cannot directly access a guest virtual machine if you are outside the host.
- Network throughput and latency performance is affected.
Install KVM
sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils
Replace default bridge
We are going to replace the default KVM bridge configuration. KVM installs a virtual bridge that all the guest VMs connect to and provides its own subnet and DHCP to configure the guest’s network and uses NAT to access the outside world. We will configure a public bridge that runs on the host network and uses an external DHCP server that is on the host network.
Disable default networking
Use ip link
command to view the default network configuration
needle@needle:~$ ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP
mode DEFAULT group default qlen 1000
link/ether 54:be:79:f3:1d:5a brd ff:ff:ff:ff:ff:ff
6: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
state UP mode DEFAULT group default qlen 1000
link/ether 52:44:10:1d:5b:20 brd ff:ff:ff:ff:ff:ff
7: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel master
virbr0 state DOWN mode DEFAULT group default qlen 1000
link/ether 52:44:10:1d:5b:20 brd ff:ff:ff:ff:ff:ff
KVM installs virbr0
and virbr0-nic
by default.
Use the commands below to remove the default KVM network:
virsh net-destroy default
virsh net-undefine default
If you run ip link
again and the virbr0
and virbr0-nic
are deleted.
needle@needle:~$ ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP
mode DEFAULT group default qlen 1000
link/ether d4:be:d9:f3:1e:5f brd ff:ff:ff:ff:ff:ff
Setup custom bridge
We will edit the /etc/netplan/00-installer-config.yaml
file to
add a bridge. Below is an example after edit:
network:
ethernets:
enp0s1:
dhcp4: false
dhcp6: false
bridges:
br0:
interfaces: [ enp0s1 ]
addresses: [10.10.0.5/24]
gateway4: 10.10.0.1
mtu: 1500
nameservers:
addresses: [8.8.8.8,8.8.4.4]
parameters:
stp: true
forward-delay: 4
dhcp4: no
dhcp6: no
version: 2
enp0s1
is my NIC’s name.
My host has been assigned an IP address 10.10.0.5/24 with the gateway as 10.10.0.1
. The gateway is my router.br0
is the bridge and it is attached to enp0s1
which is my physical networking card (NIC). The bridge will now handle all the networking and not the physical interface, in this case enp0s1
.
Run sudo netplan apply
command to apply the configuration. If you now run the ip link
command you will see something like this:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp0s1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel
master br0 state UP group default qlen 1000
link/ether 30:1d:52:ac:a9:65 brd ff:ff:ff:ff:ff:ff
10: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
state UP group default qlen 1000
link/ether 00:1d:72:ac:d9:95 brd ff:ff:ff:ff:ff:ff
inet 10.10.0.5/24 brd 10.10.0.255 scope global br0
valid_lft forever preferred_lft forever
inet6 fe50::25d:71ff:feac:d985/64 scope link
valid_lft forever preferred_lft forever
br0
has the IP address and enp0s1
belongs to the bridge br0
.
Set bridge to KVM
Create a file and named main-bridge.xml
like below:
<network>
<name>host-bridge</name>
<forward mode="bridge"/>
<bridge name="br0"/>
</network>
Make the bridge default for VMs run the following commands:
virsh net-define main-bridge.xml
virsh net-start main-bridge
virsh net-autostart main-bridge
Check the bridge setup for KVM, run this command:
virsh net-list --all
You should see something like this:
needle@needle:~$ virsh net-list --all
Name State Autostart Persistent
------------------------------------------------
main-bridge active yes yes
The bridge is setup and is set to autostart when the host boots.