Skip to content

X386 – Ubuntu & Python

Ubuntu and Python Documentation

  • Home
  • About
  • Contact
  • License
  • Privacy Policy

KVM on Ubuntu Server 2 (KVM Networking)

Posted on 26/01/2021 - 25/03/2021 by exforge

KVM Tutorial On Ubuntu Server (KVM Networking)

Copyright (C) 2021 Exforge exforge@x386.xyz

# This document is free text: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.
# This document is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
 

0. Specs

# 0.0. Definition
# KVM virtualization tutorial 2 on Ubuntu 20.04 LTS Server. 
# Please refer to 1st KVM tutorial before reading this one.
# This tutorial specializes on KVM Networking.
#
#
# 0.1. Infrastructure
# Server: (srv) Ubuntu 20.04 LTS Server on a 4 core CPU, 8 GB RAM no GUI 
#   IP: 192.168.0.240/24 and 10.1.1.1/24
# Workstation: (lahana) Ubuntu 20.04 LTS IP: 192.168.0.243
# Network1: 192.168.0.0/24 which is supplied by my internet modem (1st interface)
# Network2: 10.1.1.0/24 with an external switch (2nd interface)
#
# 0.2. Resources
# ISBN: 978-1-78829-467-6 KVM Virtualization Cookbook by Konstantin Ivanov
# ISBN 978-1-83882-871-4 Mastering KVM Virtualization 2nd Ed. by Vedran Dakic, 
#   Humble Devassy Chirammal, Prasad Mukhedkar, Anil Vettathu
 

1. KVM Networks – Configuration Commands

# Although it is possible to produce endless variations, there are 3 basic network types
#   in KVM: Bridged, NAT, and Isolated.
# Before exploring KVM networking more, let's revise the commands for it.
# 
# 1.1. Active Networks
# List KVM Networks:
virsh net-list
# We've already configured a bridged network on tutorial 1, so my server gives the 
#   following output:
#______________________________________________________
 Name           State    Autostart   Persistent
-------------------------------------------------
 host-bridge    active   yes         yes
#______________________________________________________
# 
# To display information about a network, the following command can be used:
virsh net-info NETWORKNAME
virsh net-info host-bridge
# Output on my server:
#______________________________________________________
Name:           host-bridge
UUID:           a67dfcef-86e9-4e4c-832f-bc14443da475
Active:         yes
Persistent:     yes
Autostart:      yes
Bridge:         br0
#______________________________________________________
# 
# We can display the information for the network as an XML file too:
virsh net-dumpxml NETWORKNAME
virsh net-dumpxml host-bridge
# Output on my server:
#______________________________________________________
<network>
  <name>host-bridge</name>
  <uuid>a67dfcef-86e9-4e4c-832f-bc14443da475</uuid>
  <forward mode='bridge'/>
  <bridge name='br0'/>
</network>
#______________________________________________________
#
# 1.2. Adding a Network
# To add a network, we must prepare the configuration in an XML file, and use the name
#   of the file as a parameter.
virsh net-define XMLFILE
# As an example, I'm going to create another bridge on my 2nd interface and add that bridge
#   to the KVM as another network.
# First create the bridge in the netplan file (If your netplan file is named as something
#   else, change it to that.
sudo nano /etc/netplan/01-netcfg.yaml
#____________________________________________________
network:
  ethernets:
    enp3s0f0:
      dhcp4: false
      dhcp6: false
    enx00e04c534458:
      dhcp4: false
      dhcp6: false
  bridges:
    br0:
      interfaces: [ enp3s0f0 ]
      addresses: [192.168.0.240/24]
      gateway4: 192.168.0.1
      mtu: 1500
      nameservers:
        addresses: [8.8.8.8,8.8.4.4]
      parameters:
        stp: true
        forward-delay: 4
      dhcp4: no
      dhcp6: no
    br1:
      interfaces: [ enx00e04c534458 ]
      addresses: [10.1.1.1/24]
      gateway4: 10.1.1.1
      mtu: 1500
      nameservers:
        addresses: [8.8.8.8,4.4.4.4]
      dhcp4: no
      dhcp6: no
  version: 2
  renderer: networkd
#_____________________________________________________
#
# enp3s0f0 is my 1st interface, its name is a bit funny, but my 2nd interface really has
#   a weird name as enx00e04c534458. I guess that is because it is a USB network adapter. 
#   Anyway, don't forget to change the names as your adapters'.
# Now, it is time to create the XML file for the second bridge (namely br1).
sudo nano host-bridge2.xml
#_____________________________________________________
<network>
  <name>host-bridge2</name>
  <uuid>c723a80b-d496-460e-9235-9eced7b218cf</uuid>
  <forward mode='bridge'/>
  <bridge name='br1'/>
</network>
#_____________________________________________________
#
# Now we can define it
virsh net-define host-bridge2.xml
# Start it:
virsh net-start host-bridge2
virsh net-start NETWORKNAME
# Make it autostart (Starts when the server starts)
virsh net-autostart host-bridge2
virsh net-autostart NETWORKNAME
#
# Now we have 2 bridges. If we want a VM in 192.168.0.0/24 network we use br0, if we want it
#   in 10.1.1.0/24 then we use br1.
#
# 1.3. Stopping and Removing KVM Networks
# Stop a KVM Network
virsh net-destroy NETWORKNAME
virsh net-destroy host-bridge2
# Disable autostart property of a KVM Network
virsh net-autostart NETWORKNAME --disable
virsh net-autostart host-bridge2 --disable
# Remove a KVM Network
virsh net-undefine NETWORKNAME
virsh net-undefine host-bridge2
 

2. KVM Networks – Network Types

# When preparing XML files for creating KVM networks, we use UUID and MAC values. These
# UUID and MAC must be unique for each network. Remember to replace them with unique values.
# Random UUID Generator
uuidgen
# Random MAC Address Generator
https://www.browserling.com/tools/random-mac
#
# 2.1. Bridged Networks
# I believe you already have an idea of bridged networks. It is like the host is sharing its
#   interface and network with the VM. VM is in the same network as the host. If there is a 
#   DHCP Server on the network the host resides, the VM can use it to get an IP.
# If you are going to use a server which directly serves information or a service to the 
#   users, most probably you'll use a Bridged Network.
# To use a bridged network, first you need to create the bridge in the netplan file, and 
#   then prepare an XML file and add the network to the KVM with "virsh net-define" 
#   command, as we did in 1.2.
# A sample Bridged Network XML File:
#_____________________________________________________
<network>
  <name>host-bridge2</name>
  <uuid>c723a80b-d496-460e-9235-9eced7b218cf</uuid>
  <forward mode='bridge'/>
  <bridge name='br1'/>
</network>
#_____________________________________________________
# Considerations:
#   Replace host-bridge2 with your chosen network name.
#   Replace c723a80b-d496-460e-9235-9eced7b218cf with your generated uuid.
#   Replace br1 with your bridge name in netplan file.
#
# 2.2. NAT Network
# A NAT (Network Address Translation) Network is similar (actually the same) to your home
#   network behind your internet router. Your host's interface stands like your internet 
#   router and VMs are like your home devices. When VMs want to access to the network, they
#   use host's IP address, but the other devices on the network cannot access to your VMs.
# This type of network is useful when you don't want anyone to access your VMs, but you 
#   want your VMs to access everywhere. 
# An example of Routed Network XML File:
#_____________________________________________________
<network>
  <name>nat</name>
  <uuid>d589efd6-7d61-4f92-976b-bde62956cca7</uuid>
  <forward mode='nat'>
    <nat>
      <port start='1024' end='65535'/>
    </nat>
  </forward>
  <bridge name='brnat' stp='on' delay='0'/>
  <mac address='4a:c3:6a:72:c2:30'/>
  <ip address='192.168.122.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.122.101' end='192.168.122.254'/>
    </dhcp>
  </ip>
</network>
#_____________________________________________________
# Considerations:
#   Replace nat with your chosen network name.
#   Replace d589efd6-7d61-4f92-976b-bde62956cca7 with your generated uuid.
#   Replace brnat with your chosen bridge name.
#   Replace 52:54:00:6e:a9:d8 with your generated MAC address.
#   Our nat bridge will have 192.168.122.1/24 IP and a DHCP server will announce addresses
#     between 192.168.122.101 and 192.168.10.254. Change these values as you like.
#
# 2.3. Isolated Network
# An Isolated Network, as the name implies, is isolated. Noone can go out, noone can come in.
#   The VMs in the isolated network cannot reach outside, and the devices outside cannot 
#   reach the VMs in the isolated network.
# Although it is very useful for testing purposes, there might be some situations that 
#   isolated network could be very useful. Consider you have a web server and a database 
#   server. The DB server can only be accessed by the web server and the web server will be 
#   accessed by everyone. You can put the DB server in an isolated network and define 2 
#   interfaces for the web server as 1 in a bridged network and the other one in the 
#   isolated network. That way, noone other than the web server can access the DB server.
# An example of Isolated Network XML File:
#_____________________________________________________
<network>
  <name>isolated</name>
  <uuid>a67bbbaf-81e9-4e4c-832f-bc14443da475</uuid>
  <bridge name='brisolated' stp='on' delay='0'/>
  <mac address='4a:c3:6a:72:c2:26'/>
  <domain name='myisolateddomain'/>
  <ip address='192.168.20.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.20.101' end='192.168.20.200'/>
    </dhcp>
  </ip>
</network>
#_____________________________________________________
# Considerations:
#   Replace isolated with your chosen network name.
#   Replace a67bbbaf-81e9-4e4c-832f-bc14443da475 with your generated uuid.
#   Replace brisolated with your chosen bridge name.
#   Replace 55:33:00:dd:dd:ee with your generated MAC address.
#   Our nat bridge will have 192.168.20.1/24 IP and a DHCP server will announce addresses
#     between 192.168.20.101 and 192.168.20.200. Change these values as you like.
 

3. Case Study A: Bridged and Isolated Networks Together

# 3.1. Specs:
#   Our host has a bridged network on 192.168.0.0/24 (Network 1)
#   Our host has an isolated network on 192.168.20.0/24 (Network 2)
#   Our VM1 has 2 interfaces, 1 in Network1 and 1 in Network2
#   Our VM2 has 1 interface in Network2
#   After the installations, VM2 will be accessed by VM1 only, but VM1 will be accessed
#     by all the devices on the network.
# 
# 3.2. Create the Networks
# We already have Network1, lets create Network2
# Prepare XML File
nano isolated.xml
#_____________________________________________________
<network>
  <name>isolated</name>
  <uuid>a67bbbaf-81e9-4e4c-832f-bc14443da475</uuid>
  <bridge name='brisolated' stp='on' delay='0'/>
  <mac address='4a:c3:6a:72:c2:26'/>
  <domain name='myisolateddomain'/>
  <ip address='192.168.20.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.20.101' end='192.168.20.200'/>
    </dhcp>
  </ip>
</network>
#_____________________________________________________
#
# Create the network
virsh net-define isolated.xml
# Start it:
virsh net-start isolated
# Make it autostart 
virsh net-autostart isolated
#
# 3.3. Create VM1 and VM2
# VM1
sudo virt-install --name vm1 \
    --connect qemu:///system  --virt-type kvm \
    --memory 1024 --vcpus 1 \
    --disk /srv/kvm/vm1.qcow2,format=qcow2,size=10 \
    --cdrom /srv/isos/ubuntu20.04.iso  \
    --network bridge=br0 \
    --network bridge=brisolated \
    --graphics vnc,port=5901,listen=0.0.0.0 \
    --os-type linux --os-variant ubuntu20.04 \
    --noautoconsole
# VM2
sudo virt-install --name vm2 \
    --connect qemu:///system  --virt-type kvm \
    --memory 1024 --vcpus 1 \
    --disk /srv/kvm/vm2.qcow2,format=qcow2,size=10 \
    --cdrom /srv/isos/ubuntu20.04.iso  \
    --network bridge=brisolated \
    --graphics vnc,port=5902,listen=0.0.0.0 \
    --os-type linux --os-variant ubuntu20.04 \
    --noautoconsole
# Now you can connect VM1 and VM2 from your workstation and install them. 
# 
# 3.4. Considerations for Isolated Networks
# If a VM is in an isolated network, and if it has no connections to other networks, it 
#   cannot connect to the internet. That means, VM1 can connect to the internet and VM2 
#   cannot connect to the internet. 
# Actually, when we put it in an isolated network, we accepted that it won't connect to 
#   other networks. But we need internet to install or update application.
# I have a not so bad solution for this situation. Install squid proxy to the host, make it 
#   listen to Isolated Network IP of host (192.168.20.1), allow all IPs to access it. 
#   Configure your VMs to use "apt" command through a proxy.
# I won't go in the details of installing and configuring squid proxy here, there are tons 
#   of materials on the internet about it. 
# Configure your VM to use apt commands through a proxy:
# !!! Run on your VM !!!
sudo nano /etc/apt/apt.conf
# Add following line:
#_____________________________________________________
Acquire::http::proxy "http://10.1.1.1:3128";
#_____________________________________________________
#
# If you use username/password for the proxy, use the following format:
#_____________________________________________________
Acquire::http::proxy "http://user:pass@proxyserver:port";
#_____________________________________________________
 

4. Case Study B: Separating Host and VM Access with 2 NICs

# I don't know if it would be a best practice but definitely it will be a good practice to
#   separate host's and VMs' network. That means, we will connect our host to our network 
#   with 2 interfaces; 1 interface will be used for accessing the host and the other will be
#   used to access VMs.
#
# 4.1. Specs:
#   Both interfaces of host are connected to my internet router.
#   Our host has a bridged network on 192.168.0.0/24 (192.168.0.240-NIC 1)
#   Our host has a standart network on 192.168.0.0/24 (192.168.0.241-NIC 2) 
#   Our VM will have 1 interface on bridged network. 
#   The first nic will be used by VMs and the second nic will be used to access the host.
#
# 4.2. Host Network Configuration
# Before the KVM network configuration, we need to configure the server's network. 
# Edit netplan file (change if your netplan file has a different name):
sudo nano /etc/netplan/01-netcfg.yaml
#_______________________________________________________
network:
  ethernets:
    enp3s0f0:
      dhcp4: false
      dhcp6: false
    enx00e04c534458:
      addresses: [192.168.0.241/24]
      gateway4: 192.168.0.1
      nameservers:
        addresses: [8.8.8.8,4.4.4.4]
  bridges:
    br0:
      interfaces: [ enp3s0f0 ]
      addresses: [192.168.0.240/24]
      gateway4: 192.168.0.1
      nameservers:
        addresses: [8.8.8.8,8.8.4.4]
  version: 2
  renderer: networkd
#_______________________________________________________
#
# Apply the configuration, (You'd better restart the host)
sudo netplan apply
#
# 4.3. KVM Network Configuration
# We already configured our br0 bridge on KVM. But in case you didn't do it, or removed it.
# If you already have it, skip this step.
nano host-bridge.xml
#___________________________________________
<network>
  <name>host-bridge</name>
  <forward mode="bridge"/>
  <bridge name="br0"/>
</network>
#___________________________________________
# Define the KVM Network
virsh net-define host-bridge.xml
# Start and make it autostarted:
virsh net-start host-bridge
virsh net-autostart host-bridge
#
# 4.4. Create a VM on the Bridged Network
# Now if we create a VM on br0 bridge, it will use the first interface of the host, and 
#   we will keep using the second interface at 192.168.0.241
sudo virt-install --name vm3 \
    --connect qemu:///system  --virt-type kvm \
    --memory 1024 --vcpus 1 \
    --disk /srv/kvm/vm3.qcow2,format=qcow2,size=10 \
    --cdrom /srv/isos/ubuntu20.04.iso  \
    --network bridge=br0 \
    --graphics vnc,port=5901,listen=0.0.0.0 \
    --os-type linux --os-variant ubuntu20.04 \
    --noautoconsole
 

5. Case Study C: NAT KVM Network

# We will create a VM, in a NAT network.
# 5.1. Specs:
# Server: 
#   Interface 1 is in bridged mode (as in 4.)
#   Interface 2 is in standard mode (as in 4.)
#   A NAT KVM network will be added through interface 2
# VM (Named vmn):
#   An interface will be connected to the nat network
#
# 5.2. Host Network Configuration
# There is no change needed if you applied 4.2. Otherwise do it now.
#
# 5.3. KVM NAT Network Configuration
# Prepare XML File
nano nat.xml
#_______________________________________________________________
<network>
  <name>nat</name>
  <uuid>d589efd6-7d61-4f92-976b-bde62956cca7</uuid>
  <forward mode='nat'>
    <nat>
      <port start='1024' end='65535'/>
    </nat>
  </forward>
  <bridge name='brnat' stp='on' delay='0'/>
  <mac address='4a:c3:6a:72:c2:30'/>
  <ip address='192.168.122.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.122.101' end='192.168.122.254'/>
    </dhcp>
  </ip>
</network>
#_______________________________________________________________
# Remember to generate a new uuid and a new MAC address
# Remember to rename enx00e04c534458 to your second interface name
#
# Define the KVM Network
virsh net-define nat.xml
# Start and make it autostarted:
virsh net-start nat
virsh net-autostart nat
#
# 5.4. Create the VM
sudo virt-install --name vmn \
    --connect qemu:///system  --virt-type kvm \
    --memory 1024 --vcpus 1 \
    --disk /srv/kvm/vmn.qcow2,format=qcow2,size=10 \
    --cdrom /srv/isos/ubuntu20.04.iso  \
    --network bridge=brnat \
    --graphics vnc,port=5902,listen=0.0.0.0 \
    --os-type linux --os-variant ubuntu20.04 \
    --noautoconsole
# Your VM will be able to connect to your network, but the devices on your
#   network will not be able to connect to it.
 

6. Adding and Removing Networks From a VM

# I assume that we have bridged and isolated networks ready on our host.
#
# 6.1. Specs
# VM Name: vm
# Initial Network: host-bridge (bridge br0)
# Network to be added: isolated
# Network to be removed: host-bridge (br0)
#
# We will create a VM with br0, then we will add it to the isolated network, and then
#   we will remove the br0 network.
#
# 6.2. Create a VM with Bridged Network
sudo virt-install --name vm \
    --connect qemu:///system  --virt-type kvm \
    --memory 1024 --vcpus 1 \
    --disk /srv/kvm/vm.qcow2,format=qcow2,size=10 \
    --cdrom /srv/isos/ubuntu20.04.iso  \
    --network bridge=br0 \
    --graphics vnc,port=5902,listen=0.0.0.0 \
    --os-type linux --os-variant ubuntu20.04 \
    --noautoconsole
#
# 6.3. Add an Interface to the VM at the Isolated Network
virsh attach-interface vm bridge brisolated --target ens1 --config
# Add an interface to the VM named vm, network type is bridge and bridge name is brisolated,
#   interface name on the VM (--target) will be ens1 and it will be active after shutdown
#   and start again.
# Restart the VM, either by logging into it, or using the following commands at the host:
virsh destroy vm
virsh start vm
# "virsh reboot" does not work, it restarts the VM but the interface does not become active.
#
# 6.4. Configure the New Network at the VM
# The new interface ens1 will become active at the VM but it won't start, because it is not
#  configured. We need to configure it using the netplan file.
sudo nano /etc/netplan/00-installer-config.yaml
# Change it as below
#______________________
network:
  ethernets:
    enp1s0:
      dhcp4: true
    ens1:
      dhcp4: true
  version: 2
#______________________
# 
# Activate it
sudo netplan apply
# Now the VM will have an IP from 192.168.20.0/24 (isolated) network for the 2nd interface.
#
# 6.5. Remove the Bridged Network from the VM
# We want to remove the Bridged Network from the VM, we will accomplish it by removing its
#   first interface (enp1s0). 
# To do it, we need the MAC Address of the interface. Run the following command on the VM:
# !!! Run on the VM !!!
ip link show
# It will display something like below:
#____________________________________________________________________________
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 52:54:00:fe:4a:51 brd ff:ff:ff:ff:ff:ff
3: ens1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 52:54:00:70:55:cf brd ff:ff:ff:ff:ff:ff
#____________________________________________________________________________
# My first interface is enp1s0, most probably yours will be the same, or something like it.
#   At the line under the one starting with "2: enp1s0...", the part after link/ether is
#   the MAC Address. Mine is: 52:54:00:fe:4a:51
#
# Now we return back to our host
virsh detach-interface ubuntu2 bridge --mac 52:54:00:fe:4a:51 --config
# When you shutdown and start your VM, the interface will be gone.
 

Posted in Ubuntu

Post navigation

KVM On Ubuntu Server 1 (Beginner)
ISPmail On Ubuntu
Proudly powered by WordPress | Theme: micro, developed by DevriX.