QEMU/Bridge with Wifi Routing
When there are several VMs running and the developer wants them to interact with each other, he or she creates a bridge. As discussed in QEMU/Options an Ethernet connection may easily be bridged with the virtual machine(s). However, there are times when the developer is using a wireless network and still want to interact with the VMs. In this case, the wireless interface cannot be part of the bridge easily. Also, another possibility is that the network on the ethernet is desired to have an independent state from the VMs and should not be included in the bridge. This guide deals with such conditions.
Prerequisites
- app-emulation/qemu
- net-dns/dnsmasq
- sys-apps/usermode-utilities
- net-misc/bridge-utils
- net-firewall/iptables
Emerge the packages. Dnsmasq is not necessary but it can become very handy in case one does not want to setup the networking section of the guest and the host manually or the VMs depend on having a dhcp server running.
Creating the Bridge
As an example, we would like to bridge two virtual machines. If there is one, then only configure it so. If more are running, they can easily be added here. Edit the main network configuration file:
#Configure TUN/TAP interface for the first VM
tuntap_tap0="tap"
config_tap0=null
#Configure TUN/TAP interface for the second VM
tuntap_tap1="tap"
config_tap1=null
#Configure the bridge interface
config_br0="172.16.100.1/12" # We do need to set the bridge manually.
bridge_br0="tap0 tap1" # If you have more VMs, add them.
rc_net_br0_need="net.tap0 net.tap1" # If you have more VMs, add them.
The bridge interface IP must already be determined and it itself cannot rely on
dhcp
here.The interfaces must exist so:
root #
ln -s /etc/init.d/net.lo /etc/init.d/net.br0
root #
ln -s /etc/init.d/net.lo /etc/init.d/net.tap0
root #
ln -s /etc/init.d/net.lo /etc/init.d/net.tap1
Finally, start the bridge networking:
root #
/etc/init.d/net.br0 start
Setting up Dnsmasq
Configure dnsmasq:
# We want dnsmasq to listen on br0 interface.
interface=br0
# We provide a dhcp range for dnsmasq
dhcp-range=172.16.100.50,172.16.100.150,12h
The subnet for the dhcp-range must be the same as what specified for config_br0 earlier, otherwise the VMs will not be able to get IPs.
Start the service:
root #
/etc/init.d/dnsmasq start
Network options for Qemu VMs
Set the network options for the first VM like this:
-netdev tap,ifname=tap0,script=no,downscript=no,id=mynet0 -device virtio-net-device,netdev=mynet0,mac=00:12:35:56:78:9a
The interface has been specified tap0
and also a mac address has been set. Setting a mac address is important as it helps the VMs be distinguishable.
For the second VM it can be done in the same way but with its own interface and mac address:
-netdev tap,ifname=tap1,script=no,downscript=no,id=mynet1 -device virtio-net-device,netdev=mynet1,mac=00:12:34:56:78:9a
Qemu is allergic to some mac addresses. So every one will not work.
Here the network adapter virtio-net-device
has been utilized for better performance. Make sure that the necessary steps have been followed to build the driver inside the VM and provide the support in the host. For more information refer to the necessary kernel configurations in QEMU and QEMU/Linux_guest and QEMU/Windows_guest.
If the VMs do not get the desired IPs, iptables might be blocking the connection.
The fun of routing to Wifi
At this point, the VMs should be working and they should get an IP address from dnsmasq. If they do not get the IP, consult /var/log/messages
. While they should be able to see each other from each of them, still they cannot see the outside. Neither the host can interact with them. This can even be a desired behaviour if the developer wants to have the VMs operate in an isolated network from the internet. If we had included the Ethernet interface in the bridge, the problem would have been solved, however, as it was said in the beginning, maybe one does not want to involve eth0 as it might be configured by another application or maybe the host system is connected through Wifi. In the second case simply including the wireless interface in the bridge will not work.
There are several approaches here, however, these three lines from net-firewall/iptables will provide the simplest solution. What is more, the versatility is in the fact that it does not matter that what interface one wants to route to--it can be wlan0 or eth0 or whatever. Before starting, make sure to have IP forwarding enabled:
net.ipv4.ip_forward = 1
And execute:
root #
sysctl -p /etc/sysctl.conf
Now, in this example, the bridge interface is br0 and the host system is connected through wlan0.
First, help the traffic get through the wlan0:
root #
iptables -A FORWARD -i br0 -o wlan0 -j ACCEPT
root #
iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
Then, let the system know that the known traffic can get back at br0:
root #
iptables -A FORWARD -i wlan0 -o br0 -m state --state RELATED,ESTABLISHED -j ACCEPT
Now the VMs can fully access outside and the host while the main host network interface is not part of the bridge.