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.
Old config:
# This is the network config written by 'subiquity'
network:
ethernets:
enp5s0:
dhcp4: true
version: 2
Updated config:
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 FORWARD
means to insert a rule into theFORWARD
chain-m physdev
means to match with thephysdev
extension1--physdev-is-bridged
means “Matches if the packet is being bridged and therefore is not being routed.”-j ACCEPT
means to accept (allow) the packet
Bridging vagrant-libvert
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 Vagrantfile
:
# 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 :ip
parameter:
config.vm.network "public_network",
:dev => "br0",
:mode => "bridge",
:type => "bridge",
:ip => "192.168.1.200"
References
- 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
- KVM/Networking
- UFW blocks libvirt bridged traffic