1. Overview

QEMU (Quick Emulator) is a type-2 hypervisor that can emulate a complete computer. It can boot many guest operating systems, including Linux.

QEMU supports several networking backends that interact with the emulated Network Interface Card (NIC). The User Mode networking backend is the default one. However, it has some limitations. Not being able to ping the host network from the guest machine by default is one of them.

In this tutorial, we’ll discuss how to ping the host network from a guest emulated by QEMU while using the User Mode networking backend.

2. QEMU’s User Mode Networking

QEMU’s User Mode networking is generally the simplest networking backend if we just want to access the Internet from the QEMU guest virtual machine and doesn’t require root privileges.

In User Mode networking, an internal DHCP server in the guest starts automatically. This DHCP server’s IP address is 10.0.2.2 by default. The QEMU guest gets its IP address from this DHCP server. The DHCP server isn’t reachable from the host.

The internal DHCP server is also the default gateway for the guest to communicate with the host.

Although User Mode networking is the simplest networking backend, it has some limitations. For example, the networking performance is poor. Additionally, ICMP traffic between the host and guest isn’t allowed by default. However, TCP and UDP work. Notably, the guest isn’t available from the host network.

Other modes of QEMU networking backends are Tap, VDE, and socket networking.

3. Example Setup

The setup used in our examples consists of a host and a QEMU guest virtual machine.

3.1. The Host

The IP address of the host machine in our example setup is 10.0.2.15. The host’s distro is Fedora 36 running on VirtualBox.

3.2. The Guest

Now, let’s start a QEMU guest virtual machine in a terminal in the host:

$ qemu-system-x86_64 -m 4G -hda my_virtual_disk.qcow2 -boot d -cdrom linuxmint-21.2-cinnamon-64bit.iso -netdev user,id=net0,dhcpstart=10.0.2.30 -device virtio-net-pci,netdev=net0

We use the qemu-system-x86_64 command for running a guest machine using QEMU. We can specify the characteristics of the guest machine using command-line options. For example, the guest has 4 GB of RAM, which we specify using the -m 4G option.

We specify the virtual disk that the guest uses using the -hda my_virtual_disk.qcow2 option. my_virtual_disk.qcow2 is a disk image file in the host created by the qemu-img command. The format of the disk image file is QCOW2, which is QEMU’s native format.

The -boot d option specifies to boot from the first CD-ROM. Additionally, the -cdrom linuxmint-21.2-cinnamon-64bit.iso option specifies to use the ISO image file linuxmint-21.2-cinnamon-64bit.iso present in the current directory of the host. Therefore, the QEMU guest has the Linux Mint 21.2 distro.

The -netdev user,id=net0,dhcpstart=10.0.2.30 option configures the User Mode networking backend. The id=net0 option gives the symbolic name net0 for the network backend. Additionally, the dhcpstart=10.0.2.30 option specifies that the internal DHCP server in the QEMU guest must lease IP addresses starting from 10.0.2.30. Otherwise, the host and the guest have the same IP addresses since the internal DHCP server of the guest assigns IP addresses starting from 10.0.2.15 by default.

Finally, the last option of qemu-system-x86_64, namely -device virtio-net-pci,netdev=net0, specifies the network card to be used, virtio-net-pci, and tells the network backend net0 to use this device.

We use the default values for the other characteristics of the QEMU guest such as the number of CPUs and the graphics card.

3.3. The Problem

Having started the QEMU guest, let’s check the IP address of the guest using ifconfig in a terminal opened in the guest:

$ ifconfig | grep inet | grep -v inet6
        inet 10.0.2.30  netmask 255.255.255.0  broadcast 10.0.2.255
        inet 127.0.0.1  netmask 255.0.0.0

The IP address of the guest is 10.0.2.30, whereas 127.0.0.1 is the loopback address. We filter the output of ifconfig using grep to list only the IPv4 addresses.

Now, let’s ping the host from the guest:

$ ping -c 1 10.0.2.15
PING 10.0.2.15 (10.0.2.15) 56(84) bytes of data.
From 10.0.2.30 icmp_seq=1 Destination Host Unreachable

--- 10.0.2.15 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms

We sent only one ICMP Echo Request message using the -c option of ping. However, we weren’t successful in pinging the host from the guest.

We’ll try to solve this problem in the subsequent sections.

4. Checking the Routing Table

Let’s check the routing table in the guest using netstat:

$ netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         10.0.2.2        0.0.0.0         UG        0 0          0 ens3
10.0.2.0        0.0.0.0         255.255.255.0   U         0 0          0 ens3

The -r option of netstat displays the kernel routing tables while the -n option shows numerical addresses instead of symbolic host names.

The default gateway for the 10.0.2.0/24 subnet is 0.0.0.0 according to the output of netstat, meaning there is no gateway since the guest is directly connected to this network. So, when we ping the host from the guest, ICMP Echo requests are directly sent to 10.0.2.15. But pinging isn’t successful since the host and guest networks are different although their subnets are the same (10.0.2.0/24).

Now, let’s remove the entry corresponding to the 10.0.2.0/24 subnet from the routing table using ip route del:

$ sudo ip route del 10.0.2.0/24 dev ens3
$ netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         10.0.2.2        0.0.0.0         UG        0 0          0 ens3

There isn’t any specific entry in the routing table matching the 10.0.2.0/24 subnet anymore. Deletion of a route from the routing table requires root privileges, so we use ip route del together with sudo.

Let’s ping the host from the guest:

$ ping -c 1 10.0.2.15
PING 10.0.2.15 (10.0.2.15) 56(84) bytes of data.
64 bytes from 10.0.2.15: icmp_seq=1 ttl=64 time=0.993 ms

--- 10.0.2.15 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms

rtt min/avg/max/mdev = 0.993/0.993/0.993/0.000 ms

We can ping the host successfully. Since there is no specific route corresponding to the destination address 10.0.2.15 in the routing table, the ICMP Echo Requests are directed to the default gateway 10.0.2.2 because of the first entry in the routing table. The gateway in the QEMU guest can communicate with the host network, so it further relays the ICMP Echo Request to the host network and receives the ICMP Echo Reply.

However, if we start the QEMU guest with a different subnet from the host subnet, then we won’t have a problem since the ICMP Echo Requests will be directed to the gateway.

5. The net.ipv4.ping_group_range Kernel Parameter

Sometimes, a QEMU guest virtual machine may not ping the host network because of the value of the net.ipv4.ping_group_range kernel parameter. This parameter shows the range of group IDs allowed to create ICMP Echo Requests. It consists of two integers that correspond to the minimum and maximum group IDs.

Let’s check the value of net.ipv4.ping_group_range in the QEMU guest using sysctl:

$ sysctl net.ipv4.ping_group_range
net.ipv4.ping_group_range = 0    2147483647

The minimum and maximum group IDs are 0 and 2147483647, respectively. Users with a group ID within this range can create ICMP Echo Requests. The minimum and maximum values are included in this range.

However, some distributions may not allow non-root users to send ICMP Echo Request messages by default. In this case, the minimum and maximum values of net.ipv4.ping_group_range are 1 and 0 by default, respectively. This means that only the root user can create ICMP Echo Requests.

Let’s check the group ID of the user in the QEMU guest using the id command:

$ id -G
999 4 24 27 30 46 115 136

The -G option of id lists all the group IDs the user belongs to. The root user has the group ID 0, and our user isn’t in the root group.

Before changing the value of net.ipv4.ping_group_range to “1 0”, let’s check whether we can ping the host:

$ ping -c 1 10.0.2.15
PING 10.0.2.15 (10.0.2.15) 56(84) bytes of data.
64 bytes from 10.0.2.15: icmp_seq=1 ttl=64 time=0.972 ms

--- 10.0.2.15 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms

rtt min/avg/max/mdev = 0.972/0.972/0.972/0.000 ms

We can ping the host successfully. Now, let’s change the value of net.ipv4.ping_group_range to ˆ1 0″ using sysctl and see what happens:

$ sudo sysctl -w net.ipv4.ping_group_range="1 0"
net.ipv4.ping_group_range = 1    0

The -w option of sysctl updates the value of the specified kernel parameter. Updating kernel parameters requires root privileges, so we use sysctl together with sudo. Having updated net.ipv4.ping_group_range, let’s ping the host again:

$ ping -c 1 10.0.2.15
ping: connect: Network is unreachable

As is apparent from the output of ping, we can’t ping the host anymore. We’ve essentially prevented non-root users from pinging the host by setting the net.ipv4.ping_group_range to “1 0”.

Therefore, another reason for an unsuccessful ping from the guest to the host may be the value of net.ipv4.ping_group_range.

6. Conclusion

In this article, we discussed how to ping the host network from a guest machine emulated by QEMU while using the User Mode networking backend.

First, we gave a brief introduction to QEMU’s User Mode networking backend. We also presented an example setup consisting of a host and a QEMU virtual machine.

Then, we saw two different methods. In the first one, the guest couldn’t ping the host since both networks had the same subnet number, but in fact, they were separated from each other. However, removing the entry in the routing table corresponding to the local subnet solved the problem.

Finally, we learned about the net.ipv4.ping_group_range kernel parameter in the second method. We saw that it specifies the range of group IDs that can send ICMP Echo Requests. If it has the value 1 0, only the root user can send ICMP Echo Requests.