Bridged networking allows KVM guests to connect to the outside network through the physical interface, making them appear as normal hosts to the rest of the network.
Be advised that network bridging will not work when the physical network device (e.g., eth1, wlan0) used for bridging is a wireless device as most wireless device drivers do not support bridging.
Before We Begin
We have KVM up and running. Check this post for more info.
KVM Default Virtual Network
Every standard libvirt installation provides NAT based connectivity to virtual machines out of the box. This is the so called “default virtual network”. We can verify that it is available with:
# virsh net-list --all Name State Autostart Persistent ---------------------------------------------------------- default inactive no yes
When the libvirt default network is running, you will see an isolated bridge device. This device explicitly doesn’t have any physical interfaces added, since it uses NAT with forwarding to connect to outside world.
What we want to have is a public bridge, so that we can assign IP addresses to our virtual machines and make them accessible from our local network.
KVM Public Bridge
Install bridge-utils package:
# apt-get install bridge-utils
/etc/network/interfaces and put the following configuration:
source /etc/network/interfaces.d/* auto lo iface lo inet loopback auto eth0 iface eth0 inet manual auto br0 iface br0 inet dhcp bridge_ports eth0 bridge_stp off bridge_maxwait 5
We have our DHCP server configured to issue a static DHCP lease based on a MAC address. In this case the IP address that should be given is 10.10.1.80/24.
# systemctl restart networking
Verify the IP address has been issued:
# ip ad 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP group default qlen 1000 link/ether 00:30:48:f1:4c:c2 brd ff:ff:ff:ff:ff:ff 3: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 00:30:48:91:3f:0a brd ff:ff:ff:ff:ff:ff inet 10.10.1.80/24 brd 10.10.1.255 scope global br0 valid_lft forever preferred_lft forever
Once the KVM host configuration is complete, a guest can be connected to the virtual network based on the network name.
Start the libvirtd service if it’s not already running:
# systemctl start libvirtd
Let us see what guests are installed:
# virsh list --all Id Name State ---------------------------------------------------- - centos1 shut off - rhel1 shut off
We are going to configure the centos1 guest to use the bridge network.
# virsh edit centos1
We should find similar lines:
<interface type='user'> <mac address='52:54:00:e7:6c:71'/> <model type='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </interface>
User networking connects to the LAN using SLIRP. This provides a very limited form of NAT. User networking does not support a number of networking features like ICMP. Certain applications (like ping) may not function properly. However, the guest operating system will have access to network services, but will not be visible to other machines on the network.
Add the following snippet to the config file replacing the lines above:
<interface type='bridge'> <mac address='52:54:00:e7:6c:71'/> <source bridge='br0'/> </interface>
Note that the MAC address is optional and will be automatically generated if omitted.
Start the guest:
# virsh start centos1 Domain centos1 started
Connect to the guest console, and check network configuration. If it’s bridged, it should receive an IP address from our DHCP pool 10.10.1.0/24. NAT pool is 10.0.2.15/24.
# virsh console centos1 Connected to domain centos1 Escape character is ^] CentOS Linux 7 (Core) Kernel 3.10.0-327.el7.x86_64 on an x86_64 localhost login: root Password: ********** Last login: Tue Aug 9 19:31:55 on hvc0 [[email protected] ~]# ip ad 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 52:54:00:e7:6c:71 brd ff:ff:ff:ff:ff:ff inet 10.10.1.81/24 brd 10.10.1.255 scope global dynamic ens3 valid_lft 86390sec preferred_lft 86390sec inet6 fe80::5054:ff:fee7:6c71/64 scope link valid_lft forever preferred_lft forever [[email protected] ~]# host www.google.com www.google.com has address 22.214.171.124 www.google.com has IPv6 address 2a00:1450:4009:801::2004 [[email protected] ~]# exit
It looks like network is OK on the guest.
This also worked great for Debian Stretch. Thanks!
Confirmed! Finally it works like a charm on my 2nd hands KVM pizza box… Struggled for days before this very good link! Keep up da good work!
No worries, you’re welcome!
It’s a shame that this isn’t configured out of the box, but thanks for taking the time to write up this blog.
Yea, I know. It took me a while to get a KVM bridge configured on top of a bonded interface.