Once I had a way to install virtual machines on my Ubuntu home lab server, my next goal was to be able to directly SSH into them from my laptop. By default, the Vagrant-installed
libvirt virtual machines all connect to a virtual subnet. In order to be able to connect from other computers in my home, I needed to set up Bridged Networking.
Updating Netplan Configuration
In order to set up Bridged Networking, I first had to update how my server configures its network. Ubuntu 20.04 Server uses Netplan, so I had to update
/etc/netplan/00-installer-config.yaml. While I was at it, I converted from using DHCP (with a static lease defined by my router) to using a static IP instead.
# This is the network config written by 'subiquity' network: ethernets: enp5s0: dhcp4: true version: 2
network: ethernets: enp5s0: dhcp4: false dhcp6: false bridges: br0: interfaces: [ enp5s0 ] addresses: [ 192.168.1.22/24 ] gateway4: 192.168.1.1 mtu: 1500 nameservers: addresses: [ 192.168.1.1 ] parameters: stp: true forward-delay: 4 dhcp4: no dhcp6: no version: 2
The updates were applied using
netplan appl, and my ethernet card was bridged to the
br0 bridge device.
Updating ufw firewall rules
I spent many hours trying many things to get
vagrant-libvirt, and also VMs created directly using
virt-install, to be able to access the internet via the bridge network. It turned out that the first thing I needed to do was update my firewall settings. I have a firewall set up using
ufw to only allow SSH and a couple of specific application ports, and to deny everything else. What I hadn't realized was that the settings also prevent the bridge from properly forwarding between the bridge interface and the physical one.
I didn't want to completely disable the firewall, even though that was the simplest solution to allow the VMs to be able to access the internet via the bridge. What I found worked best for my configuration was to add a rule to
/etc/ufw/before.rules to allow the bridge interface to talk with the physical one:
-I FORWARD -m physdev --physdev-is-bridged -j ACCEPT
-I FORWARDmeans to insert a rule into the
-m physdevmeans to match with the
--physdev-is-bridgedmeans “Matches if the packet is being bridged and therefore is not being routed.”
-j ACCEPTmeans to accept (allow) the packet
According to the vagrant-libvirt README.md documentation, one should be able to set up a public (bridge) connection by defining the network as public in the
# Create a public network, which generally matched to bridged network. # Bridged networks make the machine appear as another physical device on # your network. config.vm.network "public_network", :dev => "br0", :mode => "bridge", :type => "bridge"
Note, that while this does set up a second virtual network device within the VM, that device will not be bound to an IPv4 address. Thanks to an example in this GitHub issue, I realized that I could assign a static IP address simply by adding in an
config.vm.network "public_network", :dev => "br0", :mode => "bridge", :type => "bridge", :ip => "192.168.1.200"
- Creating an Ubuntu 20.04 KVM Networked Bridge Interface
- How to Setup Bridge Networking with KVM on Ubuntu 20.04
- How to Configure Network Bridge in Ubuntu
- Running Vagrant/libvirt: trying to establish public/private networks
- cannot access vagrant machine via ssh from public network
- UFW blocks libvirt bridged traffic