The Best of Both Worlds

Running Linux inside Windows using QEMU.
Accessing Linux's httpd and sshd

In order to access the Web server and Linux's secure shell, I added these parameters to the qemu.exe command:

-redir tcp:88:10.0.2.15:80 -redir tcp:22::22

The first -redir parameter makes QEMU answer any requests to port 88. Actually, it is not going to answer it itself but redirects it to server 10.0.2.15, port 80, which is the Linux Web server. I chose port 88 (different from 80) in case I need to run any other Web service (such as EasyPHP) in Windows, so they don't have conflicts with each other. To test that it's working, open http://127.0.0.1:88/ in a browser. Make sure that the Linux network interface has been configured (with dhclient) after the Linux server has been started.

The second -redir parameter makes QEMU redirect any connections to port 22 (secure shell) to Linux's port 22. If the server IP is missing, the default value is 10.0.2.15, which corresponds to the IP given by the emulated DHCPD to the emulated system (Linux). To access the shell of a Linux server from Windows, I use PuTTY by connecting to 127.0.0.1 port 22. Accessing the Linux shell through PuTTY is much more convenient than accessing it through the QEMU console, because I can open several terminals at the same time, and I can copy/paste between Linux and Windows. I also can enlarge PuTTY terminals and adjust fonts and colors. It also is possible to use pscp to copy files between Windows and Linux through SSH.

If you want to make these Linux services (httpd and sshd) accessible to the network as well (so they can be accessed from other computers on the local network), open the Windows firewall for them: Control Panel→Windows Firewall→Exceptions→Add Program. Then browse, select D:\QEMU\qemu.exe, and press OK. Next, open Control Panel→Windows Firewall→Exceptions→Add Port, and add ports 88 and 22. Also check the box Change scope... when you add or edit a program or port.

Figure 3. Opening Port 22 in the Windows Firewall

More Complex Networking between Windows and Linux

I also want to access other Linux services, such as Samba and FTP. Adding another -redir parameter for each port that I want to access is not convenient, and it's not an elegant solution anyway. I want to be able to access Linux from Windows without any restrictions. It does not seem to be so easy, because all that Windows can see is the qemu.exe process, and it has no idea what goes on inside it. So, how can Windows communicate directly with the Linux that runs inside QEMU? It is possible by creating a tap virtual Ethernet adapter using OpenVPN.

I downloaded openvpn-2.0.9-install.exe and installed it. During the installation, I checked only the components TAP-Win32 Virtual Ethernet Adapter, Add OpenVPN to Path and Add Shortcuts to Start Menu, because I didn't need the others. I changed the destination folder to D:\QEMU\OpenVPN, because I prefer to group the related tools together. I received some warnings that this software has not passed Windows testing, but I continued anyway, trusting that open-source testing is stronger than Windows testing.

After installation, I selected the menu Start→OpenVPN→Add a new TAP-Win32 virtual Ethernet adapter to create a new tap interface. Again, I received the same warnings, but continued anyway. Now, in Network Connections, I find a new network connection named Local Area Connection 1. I right-click on it and rename it tap1.

Then, I modified start-linux.bat by adding these parameters to QEMU:

-net nic,vlan=0 
-net tap,vlan=0,ifname=tap1
-net nic,vlan=1
-net user,vlan=1

The parameter -net nic tells QEMU to create a new network interface for the emulated system. Because this parameter has been used twice, Linux is going to run in a machine that has two network interfaces, eth0 and eth1. The parameter -net user creates a virtual interface on the other side (the Windows side). It is the network interface that was created previously by default (the one that has a built-in DHCP server associated with it), even though we didn't specify any -net parameters. The parameter -net tap tells QEMU to use the virtual Ethernet adapter tap1, which we created previously, and to connect it to the virtual network. The vlan options that are used with the -net parameters tell QEMU how to connect these virtual interfaces to each other. All the interfaces that have the same vlan number are connected to the same virtual hub/switch. So, we have two switches in our virtual network that is emulated by QEMU.

The last two lines of linux-start.bat now look like this:

net start kqemu
qemu.exe -L . -m 256 -kernel-kqemu -hda \\.\PhysicalDrive0 
 ↪-localtime -redir tcp:88:10.0.2.15:80 -redir tcp:22::22 
 ↪-net nic,vlan=0 -net tap,vlan=0,ifname=tap1 
 ↪-net nic,vlan=1 -net user,vlan=1

Note that the QEMU parameter -soundhw all is now missing. I removed it because one of the sound devices was creating conflicts with the network devices, so they were not recognized properly as eth0 and eth1. If you can't do without a sound device, at least append it at the very end of the line; the parameters' order does matter.

The order of the -net parameter declarations matters as well. I have noticed that if -net user is declared before -net tap, eth0 and eth1 are switched with each other, and there is also a failure to initialize eth0 during the Fedora initialization scripts. Keep this in mind, in case you have any similar problems.

After starting QEMU, we have a (virtual) physical network (Figure 4).

Figure 4. Physical Network

To check the “physical” connections of the network, press Ctrl-Alt-2 to switch to the QEMU monitor. Then, in the (qemu) prompt, give the command info network. Finally, press Ctrl-Alt-1 to get back to the Linux console. Here's the output from the command:

VLAN 0 devices:
  tap: ifname=tap1
  ne2000 pci macaddr=52:54:00:12:34:56
VLAN 1 devices:
  user redirector
  ne2000 pci macaddr=52:54:00:12:34:57

Now, we need just to configure the network settings properly, such as IPs, gateway and DNS.

The user redirector interface on the Windows side is configured automatically by QEMU, with IP 10.0.2.2/24, and we don't have access to it, so we cannot modify it. If you check in Network Connections, you will find that the virtual interface tap1 now appears to be connected. To configure it, right-click on it and select Properties, then select Internet Protocol (TCP/IP) and Properties again. In the configuration window, set a fixed-IP address of 192.168.10.10 and netmask 255.255.255.0. It's just like a usual network interface configuration.

Figure 5. Configuration of the Network Interface tap1

To check that the network configuration is okay, run ipconfig at the command prompt, and you'll see this output for tap1:

Ethernet adapter tap1:

        Connection-specific DNS Suffix  . : 
        IP Address. . . . . . . . . . . . : 192.168.10.2
        Subnet Mask . . . . . . . . . . . : 255.255.255.0
        Default Gateway . . . . . . . . . : 

This output is displayed when QEMU is running; otherwise, the information for tap1 will be something like: Media disconnected.

Now, we're done with network configuration on the Windows side. This has to be done only once. All that is left is configuring the network interfaces on the Linux side.

First, log in as root. To check that you already have two network interfaces, run ip addr, and it should list eth0 and eth1. You can configure eth0 automatically, like this: dhclient eth0, as we did previously, and it will get an IP from QEMU's built-in DHCP server. Then, you can continue with eth1's manual configuration.

However, I prefer to use scripts whenever possible, and I want to make sure that eth0 always gets the IP 10.0.2.15/24, no matter what, because this is important for the -redir parameters shown previously. So, I do the network configuration on the Linux side by running this script (which has to be rerun whenever the system is rebooted):

bash# cat /usr/local/config/net-config-qemu.sh
#!/bin/bash
### configure the network when Linux is being
### emulated from Windows by QEMU

### network settings
IP0=10.0.2.15/24       ## eth0
IP1=192.168.10.10/24   ## eth1
GW=10.0.2.2            ## gateway
DNS=10.0.2.3

### configure eth0
ip link set dev eth0 up
ip address flush dev eth0
ip address add $IP0 dev eth0

### configure eth1
ip link set dev eth1 up
ip address flush dev eth1
ip address add $IP1 dev eth1

### set the gateway
ip route add to default via $GW

### set the DNS server
echo "nameserver $DNS" > /etc/resolv.conf

To check that the network configuration is okay, run ip addr, ip route and cat /etc/resolv.conf. Here's output from these commands:


[root@fedora6 ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff
    inet 192.168.10.10/24 scope global eth1
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 52:54:00:12:34:57 brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 scope global eth0
4: sit0: <NOARP> mtu 1480 qdisc noop
    link/sit 0.0.0.0 brd 0.0.0.0
[root@fedora6 ~]#
[root@fedora6 ~]# ip route
10.0.2.0/24 dev eth0  proto kernel  scope link  src 10.0.2.15
192.168.10.0/24 dev eth1  proto kernel  scope link  src 192.168.10.10
default via 10.0.2.2 dev eth0
[root@fedora6 ~]#
[root@fedora6 ~]# cat /etc/resolv.conf
nameserver 10.0.2.3
[root@fedora6 ~]#

Now, all that remains is making sure the network is working as expected. The first check is to ping from Linux 10.0.2.2. If it is not working, it's possible that you need to switch eth0 and eth1. Sometimes, the network interface with MAC 52:54:00:12:34:56 is recognized by Linux as eth0, and the other as eth1, and sometimes it is recognized as eth1 and the other as eth0. This depends on the Linux distribution (Fedora, Slackware or whatever else). So, it is possible that eth0 and eth1 have gotten the wrong IP addresses from the configuration script, and in that case, the ping won't work. To solve this problem, modify the IP addresses that are assigned to eth0 and eth1 in the script /usr/local/config/net-config-qemu.sh, and run it again.

Now that the ping with 10.0.2.2 is working, try to ping 192.168.10.2 (tap1) from Linux. In general, it doesn't work. This is strange, because the ping to 192.168.10.10 from the command prompt in Windows does work. The problem is with the Windows firewall. To fix this, open the Control Panel, double-click Windows Firewall, select Advanced tab, select tap1 and click on Settings, then choose the ICMP tab, and here, check Allow incoming echo request. After this, the ping to 192.168.10.2 should work.

Figure 6. Allowing the tap1 Interface to Be Pinged

Don't try to ping to 10.0.2.15 from the command prompt in Windows, because it can't possibly work. Do you wonder why? Me too.

The next thing to try is accessing some Linux services from Windows using the IP 192.168.10.10. Try to open http://192.168.10.10 in a browser, and you will see the pages that are served by the Linux Web server. Try also to log in through PuTTY to 192.168.10.10, port 22, and you will access the Linux shell.

Finally, we have a first-class bidirectional network connection between Windows and Linux, which can be used to access any Linux services from Windows.

______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Booting Windows from Linux via Qemu

jmit7521's picture

The article is great and I successfully booted my Linux installation via Qemu. I am interested in booting my Windows installation from the Linux side using Qemu. If you have any suggestions please post them.

Thanks,
JPM

I have tried (months ago)

Dashamir's picture

I have tried (months ago) with something like: '-hda /dev/hda' , and I remember that I have failed.
Anyway, a QEMU virtual machine has different "physical" devices compared with your real machine.
So, if the windows partition is booted inside it, I guess that it is going to find "new hardware" etc.
It is something similar to removing the hard disk and booting it inside another machine.
While linux is flexible enough to endure this kind of migration, I am not sure about windows, it has
to be tried.

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState