- About
- Bridged networking with qemu on Linux
- Howto do QEMU full virtualization with bridged networking
- STEP 1) Enable KVM in the BIOS
- STEP 2) Install QEMU
- STEP 3) Prepare the network 1 – the bridge device
- STEP 4) Prepare the network 2 – the tun/tap for the virtual machine
- STEP 5) Create a QEMU hard drive
- STEP 6) Boot up the QEMU KVM virtual server
- * Boot the virtual server from a virtual CD/DVD
- Leave a Reply Cancel reply
- Find Us
- About This Site
About
I’m Nicholas FitzRoy-Dale, a software developer from London, UK. I’m interested in embedded systems and operating system research, code optimisation, 8-bit music, rock climbing, shiny things.
Bridged networking with qemu on Linux
This document describes setting up qemu system emulation with an IP address which is visible on the host’s network using systemd-networkd and qemu-bridge-helper. This makes the system running inside qemu accessible externally. This procedure was developed on a Debian 10 (Buster) system but should work with any system capable of using systemd for network configuration.
The hardest part of this process was digging through the layers of HOWTOs on the Internet which recommended things which were either deprecated in modern Linux systems or simply don’t work. As such, I expect the details to go out of date quickly, but the high level shouldn’t change quite so fast:
- You’ll need to create a network bridge device and bind your default-route NIC to it.
- You can then create a tap device attached to the bridge for qemu to use. Qemu can set up the necessary tap device using qemu-bridge-helper if you have configured it appropriately.
- Having done this, you will still need to configure the host’s firewall to allow packets to move across the bridge.
Create your bridge using systemd-networkd. This follows the Arch instructions. To summarise:
- Define the bridge itself by creating /etc/systemd/network/br0.netdev:
[NetDev] Name=br0 Kind=bridge
[Match] Name=en* [Network] Bridge=br0
[Match] Name=br0 [Network] DHCP=ipv4 IPForward=true
Enable systemd-networkd: sudo systemctl enable systemd-networkd.service
Start or restart systemd-networkd: sudo sudo systemctl start systemd-networkd.service
This will change the IP address of your default route interface (it will now be the bridge).
Make qemu-bridge-helper setuid: to set up a bridge as a normal user, qemu-bridge-helper must be run as root. Do this by adding the setuid bit, sudo chmod +s /usr/lib/qemu/qemu-bridge-helper (understand the security implications, which, as far as I can make out, are that unprivileged users could create arbitrary bridges bypassing firewall rules (in the best case), or effectively become root (which is the worst case for any setuid binary, because it may have security bugs)).
Allow user access to the bridge from qemu-bridge-helper: Create or modify /etc/qemu/bridge.conf:
Allow packet forwarding across the bridge: Actually you don’t need to do anything here, because you added IPForward=true above. If you hadn’t, you would only be able to access the host IP from inside the Qemu-hosted machine.
sudo iptables -I FORWARD -m physdev —physdev-is-bridged -j ACCEPT
Fix name resolution: If you were previously using NetworkManager for your networking, you will need to switch to systemd-resolved instead, because systemd-networkd expects it. sudo systemctl enable systemd-resolved.service, sudo systemctl start systemd-resolved.service, and cd etc; sudo rm resolv.conf; sudo ln -s /run/systemd/resolve/resolv.conf resolv.conf. More information; also search «resolv» here.)
Configure the qemu run by adding -nic bridge to your qemu command line.
Why do we need a bridge anyway?: From the Arch wiki (which is a great resource): a bridge is a network switch, but implemented in software. Above, we created a bridge and added the default-route NIC to it. When qemu starts and runs qemu-bridge-helper, it creates a new tap device, which is effectively a virtual NIC with its own MAC address, and connects that device to the bridge. With our iptables configuration, that’s all we need to do: routing to the right network segment is done by the kernel.
Howto do QEMU full virtualization with bridged networking
This howto rather continues the previous one “Howto do QEMU full virtualization with MacVTap networking” with the exception it will be showed how to use a classic setup of the networking – the use of bridge device. Because this setup requires a specific configuration for every Linux distro if we do not just add the bridge manually it is separated in this howto. For the clear and full howto, we would repeat the two first steps just to enable this howto to be independent of the original one mentioned above.
So use full virtualization under Linux you can use QEMU and no other library or manager like virt-manager. QEMU is simple enough and with a couple of parameters to it, you can start KVM virtual machines with near-native performance. To use KVM you must enable it in the BIOS of your server (or desktop machine).
STEP 1) Enable KVM in the BIOS
- For Intel machine you must find option Intel Virtualization Technology (or Intel VT-x) probably in BIOS menu of Chipset, Advanced CPU Configuration or other.
- For AMD machine the virtualization cannot be disabled so it is enabled by default, but you can check for additional virtualization features to enable like Virtualization Extensions, Vanderpool and other.
- Enable also additional features – Intel VT-d or AMD IOMMU, if they are available.
Reboot your machine and check if the KVM is supported:
srv@local ~$ cat /proc/cpuinfo |grep -E "vmx|svm" flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap xsaveopt dtherm ida arat pln pts .
STEP 2) Install QEMU
Under CentOS 7 you can just install couple of packets – that’s all you need:
yum install -y qemu qemu-common qemu-img qemu-kvm-common qemu-system-x86 qemu-user bridge-utils
apt-get install qemu-kvm bridge-utils
STEP 3) Prepare the network 1 – the bridge device
Under CentOS 7 add the following configuration file
DEVICE=br0 TYPE=Bridge BOOTPROTO=none ONBOOT=yes IPADDR0=192.168.0.1 PREFIX0=24 #GATEWAY0=192.168.0.1 NETMASK=255.255.255.0 IPV6_FAILURE_FATAL=no NM_CONTROLLED=no ZONE=public
If you want to use a real IP set to your virtual machine, you should set a real IP here and uncomment the GATEWAY0 with the real gateway IP. If real IP is used then you should include the main Internet network interface to the bridge by adding at the end of the configuration file /etc/sysconfig/network-scripts/ifcfg-eth0 (if eth0 is your network interface):
And restart the network
srv@local ~$ systemctl restart network
Under Ubuntu add to the file
# Bridge auto br0 iface br0 inet static address 192.168.0.10 netmask 255.255.255.0 # gateway 192.168.0.1 bridge_ports none bridge_stp off bridge_fd 0 bridge_maxwait 0
If you want to use real IP set to your virtual machine, you should set a real IP here and uncomment the GATEWAY0 with the real gateway IP and replace the “none” in the option “bridge_ports” with the name of your main Internet network interface. For example:
And restart the network
srv@local ~$ /etc/init.d/networking restart
Or we can add the bridge device manually:
srv@local ~$ brctl addbr br0 srv@local ~$ ip link set dev br0 up srv@local ~$ ip addr add 192.168.0.1/24 dev br0
If we use real IP we have to add the main Internet network interface to the bridge, so when you set up the network in our virtual machine with a real IP it will work with no more additional configurations, but if we use a local IPs like our setup here and we want to have Internet in our virtual machine we must enable masquerade and linux routing. You can do it with:
srv@local ~$ echo 1 > /proc/sys/net/ipv4/ip_forward #NAT with firewalld srv@local ~$ firewall-cmd --add-masquerade --permanent #NAT with iptables srv@local ~$ iptables -t nat -A POSTROUTING -o br0 -j MASQUERADE
Use either firewalld or iptables setup, depends on your system configuration, just check if firewalld is running with:
srv@local ~$ firewall-cmd --list-all
If you receive an error, saying command not found or firewalld is not running, you should use the “NAT with iptables”
So the network is ready!
STEP 4) Prepare the network 2 – the tun/tap for the virtual machine
After we have added a bridge device tun/tap device, which will be used for the QEMU virtual machine must be added:
srv@local ~$ ip tuntap add tap0 mode tap srv@local ~$ brctl addif br0 tap0
STEP 5) Create a QEMU hard drive
srv@local ~$ cd /mnt/storage1/disks/ srv@local ~$ qemu-img create -f qcow2 vm_harddisk.qcow2 100G Formatting 'vm_harddisk.qcow2', fmt=qcow2 size=107374182400 encryption=off cluster_size=65536 lazy_refcounts=off
or you can enable encryption (but on every start of your virtual machine you must set the key through the qemu console to start the virtual machine):
srv@local ~$ qemu-img create -f qcow2 vm_harddisk_e.bin -o encryption 100G Formatting 'vm_harddisk_e.bin', fmt=qcow2 size=107374182400 encryption=on cluster_size=65536 lazy_refcounts=off
STEP 6) Boot up the QEMU KVM virtual server
srv@local ~$ qemu-system-x86_64 -enable-kvm -cpu host -smp 4 -runas qemu -daemonize -vnc 127.0.0.1:1 \ -drive file=/mnt/storage1/disks/vm_harddisk.qcow2,index=0,cache=none,aio=threads,if=virtio \ -boot d -net nic,model=virtio,macaddr=00:00:00:00:00:01 -net tap,ifname=tap0 \ -balloon virtio -m 2048 -monitor telnet:127.0.0.1:5801,server,nowait
- “-enable-kvm” – enable the KVM – full virtualization with near native performance
- “-cpu host” – will expose all supported host CPU features (only supported in KVM mode)
- “-smp 4” – sets 4 processors to the virtual machine
- “-daemonize” – start the command in daemon mode
- “-runas qemu” – run under user, you can run thwo whole virtual machine from a user created especially for it, no need to run it with root, even it is recommended to run it under unprivileged user
- “-vnc 192.168.1.10:1” – start a VNC server on this IP:PORT = 192.168.1.10:5901, the IP must present on the server or you can use 0.0.0.0:1 for 0.0.0.0:5901, but in every situation limit the access by a firewall
- “-drive file=/mnt/storage1/disks/vm_harddisk.qcow2,index=0,cache=none,aio=threads,if=virtio” – set the main hard drive of the system
- “-boot d” – boot from the first hard drive
- “-net nic,model=virtio,macaddr=00:00:00:00:00:01 -net tap,ifname=tap0” – set the network interface using the tap device created by STEP 3) and STEP 4)
- “-balloon virtio” – use balloon driver to be able to hot add or hot remove RAM (newer version this option is depricated and it can be skipped)
- “-m 2048” – set virtual RAM size to megs
- “-monitor telnet:127.0.0.1:5801,server,nowait” – set the management console for the this virtual server, you can connect with:
srv@local ~$ telnet 127.0.0.1 5801 Trying 127.0.0.1. Connected to 127.0.0.1. Escape character is '^]'. QEMU 2.0.0 monitor - type 'help' for more information (qemu) telnet> Connection closed.
Boot the virtual machine from the hard drive given by “-drive” with network “-net” (couple of options), the RAM uses baloon memory and could be adjusted on-the-fly and sets the vncserver to listen for connection on port IP:port = 192.168.1.1:5901 (probably you’ll want to change this with a the real IP of your server, but be careful to set up a firewall rule for 5901 – the vnc port) and a management console listening on IP:port 127.0.0.1:5801.
* Boot the virtual server from a virtual CD/DVD
Probably the first time booting you might need to boot from an installation disk, this could be done by the following command:
srv@local ~$ qemu-system-x86_64 -enable-kvm -cpu host -smp 4 -runas qemu -daemonize -vnc 127.0.0.1:1 -cdrom /mnt/storage1/disks/isos/CentOS-7-x86_64-NetInstall-1708.iso -boot c -drive file=/mnt/storage1/disks/vm_harddisk.qcow2,index=0,cache=none,aio=threads,if=virtio -net nic,model=virtio,macaddr=00:00:00:00:00:01 -net tap,ifname=tap0 -balloon virtio -m 2048 -monitor telnet:127.0.0.1:5805,server,nowait
- “-boot c” – First boot device is now CD/DVD. “c” is for CD, “d” is for disk
- “-cdrom /mnt/storage1/disks/isos/CentOS-7-x86_64-NetInstall-1708.iso” – added the installation disk to the virtual machine
A newer QEMU version may need adding “script=no,downscript=no” to the tap0 interface!
srv@local ~$ qemu-system-x86_64 -enable-kvm -cpu host -smp 4 -runas qemu -daemonize -vnc 127.0.0.1:1 -cdrom /mnt/storage1/disks/isos/CentOS-7-x86_64-NetInstall-1708.iso -boot c -drive file=/mnt/storage1/disks/vm_harddisk.qcow2,index=0,cache=none,aio=threads,if=virtio -net nic,model=virtio,macaddr=00:00:00:00:00:01 -net tap,ifname=tap0,script=no,downscript=no -m 2048 -monitor telnet:127.0.0.1:5805,server,nowait
Leave a Reply Cancel reply
Find Us
Address
101010010100 Main Street
Earth, EA 101010101010100
E-mail
info@ahelpme.com
Hours (in the TimeBank)
1000000:00:0:00:00 in time…
About This Site
Highly skilled hominins inhabited planet Earth a long long ago! And these hominins have a need to share some knowledge here.