Set up a virtual routing bridge (brouter)
A virtual bridge is a software application that implements a communication network between multiple devices on a server, rather than using dedicated hardware. A 'routing' bridge is a special type of bridge that forwards traffic based on the IP addresses of the devices. This is a bit of a misnomer, as bridges by definition operate based on MAC addresses. This type of bridge is used in specific environments where multiple IP addresses share the same MAC address and the receiving device must handle traffic distribution. Otherwise, the functionality is the same.
Basically there are two ways to set up a virtual bridge.
- The virtual (plain) bridge
-
Typically, the bridge "captures" the physical interface of the server and assigns the server as a secondary device. To attach Virtual Machines, virtual interfaces are added as needed. The bridge operates at layer 2 of the OSI model and uses unique MAC addresses to determine the recipient of a data packet.
- The virtual routing bridge
-
This bridge leaves the host’s interface untouched and instead creates an independent bridge to which VMs are attached. It uses the forwarding capability to forward incoming packets that are not destined for the host to the bridge. The destination of data packets is determined locally to the bridge based on IP addresses and routing tables.
This article deals with the latter variant.
Prerequisites
. Fully updated Fedora Server, any version of F37 or newer. F44 is preferred. . Installed virtualization support according to the Adding Virtualization Support guide. . Completed preparations for installing VMs according to the Provisioning the Server VM image guide. . Set up DNS entries for the projected VMs
Steps to configure a basic routing bridge
-
Check the forwarding configuration
$ cat /proc/sys/net/ipv4/ip_forward $ cat /proc/sys/net/ipv6/conf/default/forwardingIn both cases, check that the command returns a value of 1. Libvirt activates IPv4 forwarding, but does not always activate IPv6 forwarding.
$ echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward $ echo 1 | sudo tee /proc/sys/net/ipv6/conf/all/forwardingTo make these changes permanent, create or edit the file at
/etc/sysctl.d/50-enable-forwarding.confby using your preferred editor running undersudo:# local customizations # # enable forwarding for dual stack net.ipv4.ip_forward=1 net.ipv6.conf.all.forwarding=1 -
Check the existing interfaces
$ ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 ... 2: enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> ... state UP group default qlen 1000 inet 148.251.152.29/32 scope global noprefixroute enp2s0 ... inet6 2a01:4f8:210:512d::2/64 scope global noprefixroute ... 3: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> ... state UP group default qlen 1000 ... -
Adjust the IPv6 subnet
As the IP address listing indicates, the external IPv6 subnet is the common full /64 network. Change the subnet in the IP configuration to trigger IPv6 forwarding. Use the original IP address from the IP address listing, but change the /64 to /128 when you modify the connection, as follows.
$ sudo nmcli con mod enp2s0 ipv6.addresses '2a01:4f8:210:512d::2/128' $ sudo nmcli con up enp2s0
|
In the example, the connection name matches the device name. You might need to check the network connection name that the device is attached to, when you run the |
-
Create a routing bridge
The (public) bridge is named vbr1s0, based on the name of the accompanying (public) interface. The IP addresses are the same, but with a different subnet range to trigger forwarding.
In the listing of interfaces, the IPv4 address is a point-to-point connection. Therefore, the bridge uses a subnet, if any, the range that is also assigned in DNS. If the IPv4 interface is also created as a subnet, the bridge is created as a p2p connection instead.
$ sudo nmcli con add con-name vbr1s0 ifname vbr1s0 type bridge stp off \ ipv4.method manual ipv4.addresses '148.251.152.29/27' \ ipv6.method manual ipv6.addresses '2a01:4f8:210:512d::2/64' ipv6.addr-gen-mode eui64Do not specify a zone for the connection so that the bridge is assigned to the default zone,
FedoraServer, to which the Ethernet interface also belongs by default. Ensuring that the connection belongs to the default zone is very important for the firewall permissions.Finally, for IPv4, create the routes and the public addresses of all VMs
$ sudo nmcli con mod vbr2s0 +ipv4.routes "148.251.152.49/32" $ sudo nmcli con mod vbr2s0 +ipv4.routes "148.251.152.52/32" $ sudo nmcli con mod vbr2s0 +ipv4.routes "148.251.152.56/32" -
Double check your entries, especially the IP addresses, to avoid incorrect configuration and time-consuming troubleshooting.
-
Activate the routing bridge
$ sudo nmcli con up vbr1s0 -
Install a VM
Use Cockpit or the command line
$ sudo cp /var/lib/libvirt/boot/Fedora-Server-KVM-37-custom.qcow2 /var/lib/libvirt/images/vm-01.qcow2 $ sudo virt-install --name vm-01 --memory 4096 --cpu host --vcpus 4 --graphics none \ --os-variant fedora37 --import --disk /var/lib/libvirt/images/vm-01.qcow2,format=qcow2,bus=virtio \ --network bridge=vbr1s0,model=virtio --network bridge=virbr0,model=virtioComplete the First Boot Screen. Leave the network configuration as it is. It is easier to configure it after the first login.
-
Login to the VM and configure the public interface
$ sudo nmcli con mod 'Wired connection 1' ipv4.method manual ipv4.addresses '148.251.152.49/32' \ ipv4.gateway '148.251.152.29' ipv4.dns '213.133.98.98' ipv6.method 'manual' \ ipv6.addresses '2a01:4f8:210:512d::10/64' ipv6.gateway '2a01:4f8:210:512d::2' connection.id enp1s0 $ sudo nmcli con up enp1s0 -
If it exists, adjust the internal interface.
$ sudo nmcli con mod 'Wired connection 2' ipv4.method auto ipv6.method disabled connection.zone 'internal' connection.id enp2s0 $ sudo nmcli con up enp2s0 -
Optionally reboot to reinitialize everything
$ sudo reboot
Test the configuration
-
Check the forwarding configuration
$ cat /proc/sys/net/ipv4/ip_forward $ cat /proc/sys/net/ipv6/conf/default/forwardingIn both cases, check that the command returns a value of 1.
-
Check the host configuration Ensure that SELinux is in enforcing mode and firewalld active with zone
FedoraServerwith both the external interface and the virtual bridge attached.$ getenforce $ sudo firewall-cmd --list-all $ sudo firewall-cmd --get-active-zones -
Check IPv6
(a) ping6 external desktop → host (using ipv6 notation) (b) ping6 host → VM (c) ping6 external desktop → VM (d) ssh external desktop → VM (e) traceroute6 external desktop → host (f) traceroute6 external desktop → VM
-
Check IPv4
(a) ping external desktop → host (using ipv4 notation) (b) ping host → VM (c) ping external desktop → VM (d) ssh external desktop → VM (e) traceroute external desktop → host (f) traceroute external desktop → VM
Want to help? Learn how to contribute to Fedora Docs ›