The virtual bridged networking provided by libvirt is the easiest way to enable networking on KVM virtual machines. In most cases it should be as simple as starting the default network and specifying the network when defining new virtual machines.

The default libvirt network creates a virtual bridge called virbr0 and it has its own IP address 192.168.122.1/24. When a virtual machine is configured to use this bridge, a new interface is created called vbox1, vbox2 etc. The interface is attached to the virtual bridge and shared with the virtual machine.

The virtual bridge network supports DHCP so that virtual machines can enable DHCP to obtain an IP address on the bridged network. Some iptables rules are added by libvirt so that packets to addresses outside the host are correctly routed.

The default libvirt network can be started with the virsh command.

root@demo ~ # virsh net-start default
Network default started

The configuration of the network looks like this:

root@demo ~ # virsh net-dumpxml default
<network>
  <name>default</name>
  <uuid>4690aefc-dfa3-4a0a-bd4c-e4297126a845</uuid>
  <forward mode='nat'>
    <nat>
      <port start='1024' end='65535'/>
    </nat>
  </forward>
  <bridge name='virbr0' stp='on' delay='0'/>
  <mac address='52:54:00:95:92:6b'/>
  <ip address='192.168.122.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.122.2' end='192.168.122.254'/>
    </dhcp>
  </ip>
</network>

On the host it has created two new interfaces, the virbr0 interface and a virbr0-nic interface. The later isn't so important, it's added to the bridge by default so that the virbr0 has a MAC address.

root@demo ~ # ip addr
..
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:95:92:6b brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000
    link/ether 52:54:00:95:92:6b brd ff:ff:ff:ff:ff:ff

When --network bridge=virbr0 is passed to virt-install, an interface will be added as a PCI device.

root@demo ~ # virsh dumpxml guest-1
<domain type='kvm' id='1'>
..
  <devices>
    ..
    <interface type='bridge'>
      <mac address='52:54:00:8c:7f:94'/>
      <source bridge='virbr0'/>
      <target dev='vnet0'/>
      <model type='virtio'/>
      <alias name='net0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
    </interface>
    ..
  </devices>
..
</domain>

If the virtual machine disk image doesn't configure a network interface, for example if /etc/network/interfaces only contains a loopback configuration like this:

auto lo
iface lo inet loopback

Then when we access the machine via its console, we'll find an interface called ens2 that is down.

root@guest-1:~# ip addr
..
2: ens2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 52:54:00:b3:e8:b7 brd ff:ff:ff:ff:ff:ff
root@guest-nonw:~# ping tarnbarford.net

And we can't access the internet.

root@guest-1:~# ping tarnbarford.net
ping: tarnbarford.net: Temporary failure in name resolution

As the network supports DHCP, we just need to run dhclient on the interface to obtain an IP address and bring the interface up.

root@guest-1:~# dhclient

Now the interface is up and we have been allocated an IP address, 192.168.122.14.

root@guest-1:~# ip addr
..
2: ens2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:b3:e8:b7 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.14/24 brd 192.168.122.255 scope global ens2
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:feb3:e8b7/64 scope link
       valid_lft forever preferred_lft forever

Access to the internet is possible.

root@guest-1:~# ping -c 1 tarnbarford.net
PING tarnbarford.net (178.63.44.71) 56(84) bytes of data.
64 bytes from mail01.tarnbarford.net (178.63.44.71): icmp_seq=1 ttl=59 time=0.401 ms

To make this more permanent, it can be configured in /etc/network/interfaces by appending the following lines.

auto ens2
iface ens2 inet dhcp

After a reboot, the network should be up.

The virtual machine can now access the internet as well as other virtual machines running on the host that are using the same virtual bridge. However, it's still inaccessible from the internet.