I’ve always had a lot of trouble setting up QEMU so that I’m able to ping from my host to the guest OS, and the documentation out there doesn’t help much. So here are my own instructions.
First. Most instructions out there use bridging at layer 2 in order to join an ethernet and tap (simulated ethernet) device. The biggest problem with this approach is that it doesn’t work the same way with wireless devices. Most likely you would need WDS (only certain hardware supports it), or parprouted to do layer 3 bridging. There are other problems, like the fact that you need to bring down the interface. So no, bridging is not a nice solution. For reference see this thread.
Another approach is to use a proxy arp. This is slightly better because it doesn’t need to bring down the interface, nor needs any special hardware support. However, you need to reserve one IP address for the spoofed ARP address. I chose not to use this approach mostly because I’m not familiar with it. For reference check this howto.
The simplest approach is to use a NAT. Here are the steps.
Solution
As root
in the host, create and setup your tap0
device (192.168.100.0
will be our NAT network):
ip tuntap add tap0 mode tap
ip addr add 192.168.100.1/24 dev tap0
sysctl net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
You’ll need to run your guest using this tap0
interface like this:
qemu-system-x86_64 -net nic -net tap,ifname=tap0,script=no,downscript=no windows.img
A more modern command seems to be:
qemu-system-x86_64 -netdev tap,id=nd0,ifname=tap0,script=no,downscript=no -device e1000,netdev=nd0 windows.img
And in your guest:
- ip addr:
192.168.100.2
- gateway:
192.168.100.1
- dns:
8.8.8.8
(Google’s public DNS, you can check yours in/etc/resolv.conf
)
That’s it. Now you should be able to use ping back-and-forth between the guest and the host, and both should be able to access the Internet 😉
Firewall
If your system has a firewall enabled, you are probably going to have to add more rules. As root
in the host:
iptables -I FORWARD 1 -i tap0 -j ACCEPT
iptables -I FORWARD 1 -o tap0 -m state --state RELATED,ESTABLISHED -j ACCEPT
Update: I’ve updated the instructions to commands generally available in 2023, and tested them in Arch Linux with Windows 10. If you have a problem with the new commands leave a comment.
Pingback: configure nat of qemu - Information technology
Just in case anyone finds this post any time this decade:
I think the recommended way to do NAT in qemu is to let libvirt do it. Docs can be found at:
http://wiki.libvirt.org/page/Networking#NAT_forwarding_.28aka_.22virtual_networks.22.29
LikeLike
one of it is
brctl addbr br-dev
brctl addif br-dev em1
ifconfig br-dev “em1 ip address”
ifconfig em1 0.0.0.0 up
route add default gw 192.168.1.1 via br-dev
and give the br-dev name in the configuration of virt-manager
my vm system is ubuntu.
LikeLike
I still fail to access the guest to host or vice versa by following your solution. Is there any suggestion?
LikeLike
I made the mistake. I didn’t start the iptables. Thanks for your great information.
LikeLike
Thanks a million!!!!! 😀
LikeLike
Just in case, if you have multiple static IPs and want to use one specific ips, just modify the rule in POSTROUTING as –
iptables -t nat -A POSTROUTING -o eth0 -j SNAT –to-source
And all traffic would appear to arrive from there.
LikeLike
Kindly share steps to configure the NAT in windows, Enable IP forwarding and Set iptables rules which should work for both windows 7 as well as on XP
LikeLike
Does anyone knows how ti reproduce this on OS X ? Mac doesn´t support iptables command. I guess that it does have a natd command. Any hint ?
LikeLike
Great, this really worked (Debian 8)! Your post was very helpful, as I also had a difficult time figuring this out from the documentation. Thanks a lot for sharing it!
LikeLike
The first problem is the lack of support for sudo tunctl; the second is the reply that recommends using libvirt, which shows a complex set of steps, none of which appears to use any form of the qemu command, making it a disconnected distraction, rather than an example.
LikeLike
damn man, thanks a lot, was googling and trying 3 days different manuals, but only yours worked 🙂
LikeLike
Thanks man! I tried it on WSL2, surprisingly it works!
LikeLike