Adding a NAT-and-bridged network to virt-manager/libvirt/kvm

Introduction

My basic OS installation includes configuring a bridge br0 plumbed into eth0:

banana# cat /etc/network/interfaces
...
auto br0
iface br0 inet static
    address 130.183.2.35
    netmask 255.255.255.0
    gateway 130.183.2.1
    bridge_ports eth0
...
banana#

With this configuration virt-manager will not allow me to create a NAT-ted network also plumbed into br0:

(Notice that ‘br0’ does not appear in the list of destination devices.)

It seems like a few people have seen this problem.  Some solutions involve getting virt-manager/libvirt to manage the br0 interface but it looks like managing network interfaces in virt-manager is deprecated, and, indeed, my virt-manager has no ‘Interfaces’ tab:

This seems to be a problem only with virt-manager; by using virsh it can be accomplished, although note that virsh has no create-net-as command, so a bit of XML needs to be written.

Procedure

  1. Create an XML template for your new virtual network by running:
    RANDOM_UUID=$(uuidgen)
    RANDOM_MACADDR=$(perl -e 'printf("%02x:%02x:%02x:%02x:%02x:%02x", 0x52, 0x54, 0x00, map { int(rand(256)) } 1..3);')
    cat > /tmp/$$.xml <<EOF
    <network>
      <name>my-network</name>
      <uuid>$RANDOM_UUID</uuid>
      <forward dev='br0' mode='nat'>
        <nat>
          <port start='1024' end='65535'/>
        </nat>
        <interface dev='br0'/>
      </forward>
      <bridge name='virbr0' stp='on' delay='0'/>
      <mac address='$RANDOM_MACADDR'/>
      <ip address='192.168.100.1' netmask='255.255.255.0'>
        <dhcp>
          <range start='192.168.100.128' end='192.168.100.254'/>
        </dhcp>
      </ip>
    </network>
    EOF
  2. Edit the file /dev/$$.xml and change to suit your requirements:
    • the name of the network
    • the host’s IP address on that network
    • the netmask
    • the DHCP address range (or remove the ‘<dhcp>…</dhcp>’ XML stanza altogether)
  3. Run:
    virsh net-define /tmp/$$.xml
    virsh net-start $(sed -n 's/.*<name>\([^<]*\).*/\1/p' /tmp/$$.xml)

See also