2006-02-08

如何在QEMU中通過TUN/TAP使用網絡

After spending perhaps the most frustrating evening of my life attempting to make a Windows 98 guest in qemu talk to the world via TUN in Linux, I thought I'd share my observations with the list and gather some feedback. Firstly, I could not find ~anywhere~ a decent high-level, conceptual outline of what a TUN network 'looks like' in Linux; and that seems to lead to a lot of confusion, both for me personally, and on this list generally (I came across many, many incorrect qemu-ifup scripts etc that just Don't Work on various threads archived on this list and elsewhere). Now that I have made TUN bend to my will, I thought I'd clear up some confusion and draw some pictures, for the future benefit of anyone else like me trying to untangle this mess with the help of google ;)

First up; what does a TUN client network 'look like'? Here's how I visualise it:

real NIC
|
v
------| <-192.168.0.10 (real NIC IP)
| |--------------------------------->THE WORLD
|____|
^ <-192.168.0.10 (Pretend real NIC IP)
|
| <-Pretend network link
|
v <-10.0.0.1 (Pretend fake tun0 IP)
------|
| | <-Fake 'tun0' NIC
|____|
^ <- 10.0.0.1 (tun0 IP)
|
| <-Pretend connection to guest OS
|
v <- 10.0.0.x (ie 10.0.0.10) QEMU guest NIC IP
------|
| | <-QEMU guest OS NIC
|____|


In other words, conceptually, tun0 actually sits 'between' the host OS and the guest (whether this is actually the case or not I leave as an intellectual exercise for the reader). So, the tun0 address and the qemu guest OS address should be different, but should both be on the same subnet, and that subnet should be utterly different to anything else on your network. Intellectually I can appreciate the possibility that it shouldn't *have* to be on a different subnet, but in practice I met with utter and complete failure attempting to make tun0 and the guest OS NIC live on the same subnet as all the 'real' NICs.

Therefore, all traffic to the 'real world' goes from the guest, to tun0 (ie, in the guest OS set the address of the default gateway to be the tun0 address), and from tun0 out to the world via the real NIC address. To make all this work, you need a script that puts the house in order for tun0.

Your real NIC, because all of the traffic is routing through it, has to have an appropriate iptables rule to masquerade traffic, and ip forwarding needs to be enabled for the host OS. Here is a simple script that does everything necessary (ie, this is a working, complete qemu-ifup):

--------8<--------snip
#!/bin/bash
iptables --flush #Clear out all previous rules ('/etc/init.d/iptables stop' may also work)
echo 1 >/proc/sys/net/ipv4/ip_forward #Enable IP forwarding for the host OS
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE #Enable masquerading on your real NIC so tun0 can get in and out
ifconfig $1 10.0.0.1 #Bring up tun0 on a different subnet from the host
--------8<--------snip

This should work as far as tun0 goes, but this kills all preset iptables
rules. Which is fine if you're not using iptables. To preserve other iptables
I've added Masquerade to my saved rules via:

From terminal as root
#iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
#/etc/rc.d/init.d/iptables save

And eliminated the "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE "
command from my qemu-ifup script. Of course iptables must be set to start on
boot.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.