6

I have a VM host (KVM) that's connected to a wireless router. I'd like the virtual guests to be in the same broadcast domain as the host; i.e, receive their IP from the router's DHCP. (=Layer 2 bridging)

According to KVM documentation it's impossible: Important Note: Unfortunately, wireless interfaces cannot be attached to a Linux host bridge, so if your connection to the external network is via a wireless interface ("wlanX"), you will not be able to use this mode of networking for your guests. (I tried it anyway, and indeed, it doesn't work :) )

There are some resources in the Internet that suggest how to make a routed interface, and it works for me. But it's Layer 3, and the guests reside in a different IP subnet.

However, I used VirtualBox in the past - and wireless bridging works there.

I've found superuser question regarding VirtualBox, that explains: Many virtual machine programs come with a special "bridge" or "filter" driver which attaches to existing network interfaces and allows the program to send and receive packets (Ethernet frames) directly.

That's exactly the outcome I want - KVM virtualization with Ethernet bridging (Layer 2). Sadly, it appears that libvirt/KVM don't include such as a driver. But I assume that it can be achieved with some other Unix tool.

3

I had exactly the same requirement as Zvika. By the way, his post on the subject is excellent. The alternative I found is this: configure a routed network in KVM in the range 192.168.1.160/28 (so, dedoimedo third solution, the "dirty hack") and then, instead of creating an ARP proxy the Zvika's way, I used parprouted, which is available in Ubuntu/Mint as a package with the same name. With parprouted, you can just type:

sudo parprouted virbr1 wlan0

et voilà, traffic works in both ways to/from the guest VM and the other devices in 192.168.1.0/24 network, as well as to/from external systems (e.g. Internet sites) if that network is behind a NAT.

This was hard, anyway, I spent days searching on this subject and no source was as clear as Zvika's blog entry!!

  • 1
    It might be noteworthy that this solutions supports only unicast and parprouted is terribly outdated. – Daniel B Jun 27 '15 at 14:04
2

The official documentation is way too pessimistic. As always, someone smart has figured it out: you find the (lengthy) instructions to do this here. I tried it, it's a cinch.

Edit:

I am not sure why the first solution posted in the articled referenced above does not work for you, it did for me and you provide no extra information. Still, you may wish to consider an alternative solution, here, provided by Bohdi Zazen, which uses proxy-arp. I never tried this (sol. n.1 worked for me, so what was the point), but you may give it a chance.

  • I've also seen that article. Indeed, he is smart. However, the first method (brctl) refuses to work with my wlan0 interface. The Alternative setup works for me, but it's Layer 3 - i.e., it creates 2 different networks that are connected together, but the virtual guest network is different that the host<->router network. And finally, I don't understand how the very dirty hack of using the same IP subnet should work; if a device that's connected to the router's network try to reach one of guests, it'd send the traffic to the router; but the router isn't aware of the pirate VM subnet... – Zvika Dec 30 '13 at 18:15
  • @Zvika Edited my answer to reply to your comment. – MariusMatutiae Dec 30 '13 at 18:34
  • Pay attention, that at the end of his article he shows a ping from Windows7 Physical machine (ip .103) pinging the virtual adapter with .161 address - but he didn't show a ping to the virtual guest (ip .168) - because it's unreachable to the Windows machine. – Zvika Dec 30 '13 at 18:34
  • Actually, the first solution is quite similar to what the official document suggest for eth0 bridging. Dedoimedo himself says For instance, on some laptops, Wireless adapters do not really support this mode of work. I assume that's the reason this is thought to be officially unsupported. I'm not near that machine now, and I don't remember the exact error message, but brctl addif br0 wlan0 failed. Thanks for the Bodhi Zazen reference, I'll try it and update – Zvika Dec 30 '13 at 18:40
  • thanks. The link you gave me for Bodhi Zazen was very helpful. Although I didn't use his solution as-is, the idea of Proxy ARP was what I looked for. Hopefully, I'll write an article to explain the method that I used - some mixture of Dedoimedo's and Bodhi Zazen's solutions. – Zvika Jan 2 '14 at 9:03
2

It is not "wireless adapter" doesn't support bridging. It is access point and WiFi host-to-ap protocol. When you establish connection you authenticate your adapter's MAC. The protocol has a space for three MACs: immediate authenticated participants and third - for any end point behind AP. So WiFi mobile station could send packet to any MAC, but only use its own MAC as source address. You couldn't send any packet with another source MAC other that authenticated - AP will reject that packet.

There is also WiFi protocol capable of true bridging, called WDS. That is done by allowing four MAC addresses in the packet: two - immediate authenticated participants, i.e. bridging APs, and two - end points (source and destination) whose packet is being transferred by WiFi bridge.

Read here http://wiki.mikrotik.com/wiki/Manual:Wireless_Station_Modes#802.11_limitations_for_L2_bridging about this.

It's a pity WDS is not well standartized, and each vendor evaluates it on its own in an incompartible way. Only if the WiFi alliance were more... user-oriented organization, they'll done spec better and we'll be able to do wifi bridging here and there, between arbitrary vendor solutions, and indeed between guest machines and wireless network!

Proxy-ARP is not L2 solution though, it is ROUTING solution, i.e. L3. It tricks both sides so you could have same subnet here and there, but still this is routing and by the way this somewhat messes up network. See MAC table on any machine to see what is going there: all MACs for "that side" are MAC of our proxy-arp router.

For true L2 solution you could try linux "MAC NAT" feature which is configured with ebtables utility. Since this is the only true L2 solution I know, I tend to think it is used by VirtualBox. However, it basically looks like proxy-arp. You certainly should be able to implement this this with KVM and libvirt.

0

According to KVM's docs, it is not possible to use a bridge with a wireless NIC. I do not know the reason why even though I used to bridge the guest on VirtualBox.

I have spent some few hours to figure out how to connect the guest to the host's wireless network and I found out the easiest way to do it is using a TAP device. The only disadvantage of this method is that you can't use DHCP on the guest and you have to manually give it an IP address from the wireless network subnet (Which may cause IP conflicts or inconvenience in case of deploying lots of VMs).

Here are the steps to connect the guest on the host's wireless network using a TAP device:

0/ Enable IPv4 routing for the Linux kernel

sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"

1/ Create a tap device named tap0 accessible from user guest (Replace with your username) without sudo:

sudo ip tuntap add mode tap tap0 user guest
sudo ip link set tap0 up

2/ Assign an IP address to the tap0 device (It doesn't have to be from the wireless network subnet):

sudo ip addr add 10.10.10.10/24 dev tap0

3/ Use parprouted (You might have to install it) to implement proxy arp bridging which allows bridging the guest Ethernet behind the host's wireless NIC.

sudo parprouted wlan0 tap0

(Replace wlan0 with your host's wireless interface)

4/ Adding some routing tables entries to allows packets to travel through the ends of the tap device:

sudo iptables -A INPUT -i tap0 -j ACCEPT
sudo iptables -A FORWARD -i tap0 -j ACCEPT
sudo iptables -A FORWARD -o tap0 -j ACCEPT

On the guest assign a static IP address from the host's wireless network subnet. For example if your wlan0 is on 192.168.1.0/24 then the guest can be configured with

sudo ip addr add 192.168.1.30/24 dev eth0

(eth0 is your guest's NIC)

or permanently in /etc/network/interfaces with:

auto eth0
iface eth0 inet static
  address 192.168.1.30
  netmask 255.255.255.0
  network 192.168.1.0
  broadcast 192.168.1.255
  gateway 192.168.1.25

Launch your guest with:

kvm -hda guest.img -m 512 -net nic -net tap,ifname=tap0,script=no

Now pinging works between all machines connected on your wireless network and the guests.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.