vbox (and qemu) tap/vboxnetflt networking; bridging vs wifi

Juergen Lock vbox-devel-l at jelal.kn-bremen.de
Thu Jan 7 19:04:01 UTC 2010


Hi!

 As noted earlier on freebsd-emulation, wifi users have a problem when
they want to expose a VM guest on their lan:  simply bridging it to the
wifi interface usually doesn't work because hosts on wifi can only use a
single mac address.  As I now found out, vbox on (at least) Linux/Windows
hosts attempts to work around this issue by implementing a shared mac
feature that gets enabled if you use bridged mode on a wifi nic there,
so I tried enabling that for FreeBSD hosts too:
	http://people.freebsd.org/~nox/vbox/patch-sharedmac.txt
(patches are under MIT license and for vbox 3.1.2 as featured in the
recent ports CFT, I haven't checked if they also apply to the older
version still in ports) - and Beat tested that yesterday since I don't
have wifi here myself, he couldn't get it working properly.  Maybe the
FreeBSD vboxnetflt code needs to be adjusted for this too?

 But...  I also made another patch to make vbox dtrt when you use
bridged mode with a tap interface,
	http://people.freebsd.org/~nox/vbox/patch-tapdirect.txt
and he tested using that to do routing + proxy arp for the guest IP,
and _that_ worked. :)  (As mentioned before in other -emulation threads,
tap can also be used with if_bridge to do basically the same thing as
vbox' bridged mode (vboxnetflt) now does via netgraph, I won't cover
that here again - see e.g. my original vbox tap thread for an example:
	http://lists.freebsd.org/pipermail/freebsd-emulation/2009-August/006693.html
btw you can select the tap interface in the GUI now if it is configured
so you don't need VBoxManage for that anymore.)

 Anyway, here goes the routing example:
	kldload if_tap
	sysctl net.link.tap.user_open=1
	sysctl net.link.ether.inet.proxyall=1
	sysctl net.inet.ip.forwarding=1
	chown root:vboxusers /dev/tap0
	chmod 660 /dev/tap0
	ifconfig tap0 <ip> netmask <netmask>
The tap0 (and guest) IPs here need to be in a sub-subnet of your host's
physical network (the wifi interface's in this case), and the usual
cidr subnetting rules apply, i.e. since you need two IPs in the subnet
(tap0 and guest) and you want to avoid IPs with all of the lower bits
set or cleared you need at least a /30, i.e. netmask 0xfffffffc.
(You should also be able to use if_bridge to bridge multiple guest's
tap interfaces together in which case only the bridge interface needs
an IP, but then of course you need a larger subnet.)  So, assuming your
network is 192.168.0/24 (and you have no other hosts in the following
subnet) you can try:
	ifconfig tap0 192.168.0.17 netmask 0xfffffffc
and in the guest configure the emulated nic as 192.168.0.18 with the
same netmask and the tap interface IP as gateway.  dns then can be the
same as the host uses (see /etc/resolv.conf) and that's it, the guest
should have network and be reachable from the lan as 192.168.0.18.

 The only downside of doing it this way is the tap interface loses
its IP when vbox closes it and the ifup/down script feature has been
removed from vbox so you need to rerun the `ifconfig tap0 ...' each
time before you start the guest again.  (Maybe that can be avoided
if you set net.link.tap.up_on_open=1, put only the tap interface on
an if_bridge and give that bridge interface the IP instead, I haven't
tried.)

 Oh and btw, direct tap networking like this also still seems to
perform better than the current FreeBSD vboxnetflt implementation,
so if guest network performance is important...  And doing it the
routing way instead of bridging also protects from guests messing with
your lan's arp tables, altho in that case you probably shouldn't set
net.link.ether.inet.proxyall but setup specific proxy arp entries
only for your guest(s) IP(s).  [1]

 And finally, the same applies to qemu, only there you can of course
still put the `ifconfig tap0 ...' in /usr/local/etc/qemu-ifup (using
sudo unless you run qemu as root.)

 Cheers,
	Juergen

[1] The details of this depend on your host's FreeBSD version, on
7.x and before you can do:
	arp -s <guest IP> auto pub only
before(!) configuring the tap interface, while on 8.x and -current
this doesn't work anymore because of the new routing code, but there
this instead seems to work:
	arp -s <guest IP> auto pub
- also before configuring the tap interface.  And note this arp entry
gets deleted along with the tap interface's route when vbox closes
it so you need to rerun that command each time before you start the
guest again too.


More information about the freebsd-emulation mailing list