QEMU Windows Guest: Networking
There are different kind of backend networks that we can use with QEMU. In order to specify the backend network, we need to use the -netdev command-line option. This is directly connected to the -net command-line option. The -netdev has multiple syntaxes presented below that directly correspond to the -net syntaxes. The actual syntax is "-netdev type,id=name,..." where the types below are: user, tap, bridge, socket, vde, and hubport.
[python]
-netdev user,id=id[,option][,option][,...]
-netdev tap,id=id[,fd=h][,ifname=name][,script=file][,downscript=dfile][,helper=helper]
-netdev bridge,id=id[,br=bridge][,helper=helper]
-netdev socket,id=id[,fd=h][,listen=[host]:port][,connect=host:port]
-netdev vde,id=id[,sock=socketpath][,port=n][,group=groupname][,mode=octalmode]
-netdev hubport,id=id,hubid=hubid
FREE role-guided training plans
When deciding which networking type we would like to use in our guest system, we can choose among the options described below.
- User networking is the default networking type.
- Tap networking uses the tap device in the host to provide networking capabilities to the guest.
- Bridge networking can be used when we would like network devices to see our virtual machines.
- Socket networking can be used to create guest virtual machines that can see each other over the network.
- VDE networking uses the virtual distributed Ethernet.
- Hubport networking
It's advisable that we use the virtio driver for networking, which is often included in the operation system. Instead of booting with "-net nic" option, we can boot with "-net nic,model=virtio" option to enable virtio support. Windows will try to find the driver for it and, if it won't find it, it will present a dialog like this:
To solve the problem, we need to download the "virtio-win-0.1-65.iso" virtio driver from the https://alt.fedoraproject.org/pub/alt/virtio-win/latest/images/bin/ website, which is presented below:
After downloading the virtio driver, we have to add the "-net nic,model=virtio -cdrom virtio-win-0.1-65.iso" options to the QEMU-kvm command. After starting Windows operating system, the network will still not be detected automatically. This is why we need to go to the Device Manager, as presented on the picture below, and right-click on the "Ethernet Controller" and then select "Update Driver Software."
Once the popup has opened, we need to select our newly mounted iso image residing at drive letter D: to be scanned for virtio device driver. This can be seen on the picture below.
After pressing the "PK" button, Windows will scan directory D: for the virtio device driver, which is found, but we must confirm that we want to install it as shown below:
When trying to install the new virtio driver, my whole Windows operating system crashed, so I wasn't able to install this version of the virtio device driver. Instead, I downloaded the latest stable driver version, virtio-win-0.1-52.iso, and installed it. The installation has completed successfully, as can be seen in the picture below.
After installation, we don't need to restart the Windows operating system and the networking will start to work as expected, using the virtio network device driver. At that point, we can remove the "-cdrom virtio-win-0.1-65" option, because the driver was already installed and we don't need to mount that iso image to the drive letter D:.
Networking Modes
We should also discuss what kind of networking is available in QEMU. We'll try to present the same networking options as are used with Virtualbox/VMWare, which might be more familiar. In Virtualbox we have the following networking options:
- NAT: the Virtualbox itself acts as a router to the guest machine, so the guest machines gets an IP address from the DHCP server integrated into the Virtualbox. When a virtual machine connects to the internet, the Virtualbox is doing the NATing to translate the IP addresses for the guest VM to be able to access the internet.
- Bridged: Virtualbox uses the host network driver to inject and sniff packets from it. This is used when we would like our guest VMs to appear as they were physically connected to the network. If we attach a packet sniffer like Wireshark to the used host network interface, we will be able to sniff packets from the host, as well as from all guest virtual machines.
- Host-Only: a new software interface is created on the host that can be used for the host to see the guest virtual machines, but the VMs themselves cannot connect to the outside world.
- Internal: the virtual machines can only talk between themselves, but cannot talk to the world outside the host.
The best way to see the difference between those models is by taking a look at the table below, which presents the main differences when comparing the networking modes. The "y" means "yes" and the "n" means "no."
You can use the above table to evaluate the networking modes when deciding which one to use. Configuring each of the above modes is quite easy in Virtualbox, but when it comes to QEMU, we have to do some work to get them working the way want.
NAT Networking (User Networking/SLIRP)
This provides a way for the virtual machine to use the internet, but the virtual machines don't see each other and we also can't access the VM from the host. This option is used by default if we don't specify any other option and is the slowest among all provided. When using this option, ping also doesn't work, so don't try to ping some host on the internet to try to make sure that networking works; instead, use nslookup to do a DNS query. When using this option, the gateway will reside at 10.0.2.2, DNS server at 10.0.2.3, SMB at 10.0.2.4, and the guest operating system will have IP address 10.0.2.15. We can change the settings of this default mode by issuing the "-netdev user" command-line option. An example command that we can use is the following:
[python]
> -netdev user,id=net0,net=192.168.1.0/24,dhcpstart=192.168.1.100
The parameters can be one of the following:
- net sets the IP address network.
- dhcpstart specifies the first IP address the built-in dhcp server can assign.
- restrict restricts network capabilities to the guest only, so the guest doesn't have access to the host and the internet.
- hostname specifies the hostname that will be assigned to the guest.
- smb enables the built-in smb server, which enables the guest operating system to access the host files in the specified directory. If we would like this to work, the host operating system must have samba installed.
- hostfwd is used to redirect incoming tcp/udp connection trying to connect to the host on hostaddr:hostport to the guest on guestaddr:guestport. The syntax of the exact command can be seen below. This is useful if we would like to enable other clients on our LAN to connect to the guest's service running on ip:port through host.
> QEMU-kvm -net user,hostfwd=[tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport
- guestfwd forwards guest tcp connections to the service on ip:port to the character device.
If we boot QEMU with the "-netdev user,id=net0 -device e1000,netdev=net0" options, then we'll get the 10.0.2.15 IP address, as shown in the picture below:
In this mode, the VM cannot connect to the devices on the network and the network devices cannot connect to the VM, but VM has access to the Internet.
Host-Only Networking
With host-only networking mode, the host itself is the one that has access to the virtual machines and virtual machines can see each other. The network devices can't see the virtual machines and the virtual machines can't see the network devices. The difference between this mode and internal networking is that, in this mode, the host sees the virtual machines, while in the internal networking, even the host doesn't see them; they can only see themselves. The virtual machines also don't have access to the Internet. We can create this mode by creating a new tap network interface and use that for the networking without using any kind of bridge to join collision domains.
If we would like to use host-only networking mode, we have to create a tap1 interface and associate it with an IP address. We should use the tap interface in standalone mode by associating it with a static IP address. Since the host-only guest virtual machines don't have access to the Internet, we shouldn't add the interface to the bridge to get a link to the outside world. We can define the static IP address in the /etc/conf.d/net simply by using the following:
[python]
config_tap1="172.16.2.0 broadcast 172.16.2.255 netmask 255.255.255.0"
We should definitely edit the networking configuration file and restart the net.tap1 init script, but if we want to do it quickly, we might also execute the commands below (in host):
[python]
# ifconfig tap1 172.16.2.1 netmask 255.255.255.0
Then in the Windows guest we also need to set the static IP address to the interface and we need to set the gateway to the IP address of the host, which is 172.16.2.1. The picture below presents the options we need to use if we want to set up a usable network.
After changing the settings we can normally ping the guest IP address from host, which is shown below:
[python]
# ping -c 3 172.16.2.2
PING 172.16.2.2 (172.16.2.2) 56(84) bytes of data.
64 bytes from 172.16.2.2: icmp_seq=1 ttl=128 time=0.578 ms
64 bytes from 172.16.2.2: icmp_seq=2 ttl=128 time=0.253 ms
--- 172.16.2.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.246/0.359/0.578/0.154 ms
We can also ping from guest VM to host, which is shown in the picture below:
Thus we've successfully configured the host-only networking mode, which can be used to connect the guest virtual machines with the host, but not with other devices on the network.
If we would rather use DHCP server, we can install dnsmasq and edit the /etc/dnsmasq.conf configuration file to contain something like the configuration directives below:
[python]
listen-address=127.0.0.1
interface=tap1
dhcp-range=172.16.2.2,172.16.2.100,12h
This will start the DHCP server, which will listen for DHCP requests on interface tap1 and will give out the IP addresses from 172.16.2.2 to 172.16.2.100. If we restart the Windows guest virtual machine and enable "Obtain IP address automatically," the dnsmasq will provide the IP address to Windows. We can see that in the picture below, where the IP address was set to 172.16.2.91.
Internal Networking
The internal networking is basically the same as host-only networking except that we should add an iptables rule to the host to not allow guest virtual machines to talk to the host. This should enable the virtual machines to keep talking to each other, but prevent them from talking to the host.
References:
[1] QEMU-img man page, http://linux.die.net/man/1/QEMU-img.
[2] QEMU-kvm man page, http://linux.die.net/man/1/QEMU-kvm.
[3]Updating the guest initramfs with the virtio driver, http://www.linux-kvm.org/page/Boot_from_virtio_block_device#Windows_XP.
[4] Ebtables, http://ebtables.sourceforge.net/.
FREE role-guided training plans
[5] Explaining how to mangle the packets, http://www.netfilter.org/documentation/HOWTO/NAT-HOWTO-6.html.