Creating a bridge for virtualizing with KVM

2 minute read

This post applies to Ubuntu given that it uses the netplan paradigm.

Reason

There are multiple ways to allow a KVM VM to have access to the external network, but usually, people implement either a NAT or a bridge method. I went for the latter because it felt more “natural”: my host serves as a gateway (bridge) to the rest of the network, each VM will have their own IP…

Installation

I suppose that you have installed everything you need for the virtualization part, so I jump directly to the bridging part:

1user $ sudo apt install bridge-utils

Configuring netplan

My host has 4 network interfaces, but I’m only using the first one, the others are not wired.

Now, let’s configure our netplan configuration file:

 1network:
 2  ethernets:
 3    eno1:
 4      dhcp4: false
 5      dhcp6: false
 6    eno2:
 7      dhcp4: true
 8    eno3:
 9      dhcp4: true
10    eno4:
11      dhcp4: true
12  version: 2
13
14  bridges:
15    br0: 
16      addresses: [ 10.0.20.2/24 ] 
17      gateway4 : 10.0.20.1
18      mtu: 1500
19      nameservers:
20        addresses:
21          - 1.1.1.1
22          - 8.8.8.8
23      parameters:
24        stp: true
25        forward-delay: 4
26      dhcp4: false
27      dhcp6: false
28      interfaces:
29        - eno1

So basically, we won’t provide eno1 an IP address, but directly give it to br0 then tell br0 to use eno1 as its interface.

The reason why the br0 addresses is a /24 is to allow all those addresses to be routed over that interface.

Bridging consideration and tuning

By default, all packets going through the bridge are then passed to the iptables / netfilter modules. This may cause issues where packets are blocked by your local rules. What you probably want, it’s to avoid this and send packets directly to the physical network, then let an external firewall to manage the rules. Also, by setting these settings to “no” will improve network (and CPU) performances given that no filter processing will take place. You can read more about this here.

So let’s disable those settings by creating (or apending if it already exists) a file /etc/sysctl.d/bridge.conf and fill it with:

net.bridge.bridge-nf-call-ip6tables=0
net.bridge.bridge-nf-call-iptables=0
net.bridge.bridge-nf-call-arptables=0

Now, let’s create a udev rule to apply these everytime the netfilter module is loaded in the kernel.

Create a file called /etc/udev/rules.d/99-bridge.rules and add this line:

ACTION=="add", SUBSYSTEM=="module", KERNEL=="br_netfilter", RUN+="/sbin/sysctl -p /etc/sysctl.d/bridge.conf"

You may apply those settings immediatly by running the /sbin/sysctl -p /etc/sysctl.d/bridge.conf above command or restart, up to you.

Applying

Now, we can apply these settings:

1user $ sudo netplan apply