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
Open /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.
Restart networking:
# 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
Guest Configuration
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
[root@localhost ~]# 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
[root@localhost ~]# host www.google.com
www.google.com has address 216.58.214.4
www.google.com has IPv6 address 2a00:1450:4009:801::2004
[root@localhost ~]# exit
It looks like network is OK on the guest.
This also worked great for Debian Stretch. Thanks!
You’re welcome!
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.