DummyNet in VMWare
If your work or hobby involves network software development, chances are you've needed - or would have needed - to simulate real-life conditions in your lab. It really helps to see how your software will function over a less-than-reliable link such as dial-up or satellite without the hassle of actually using one.
There are commercial tools that get the job done (Shunra VE Desktop is one, but they'll ask for a five-figure sum) and there's DummyNet for BSD. If you want a free solution, definitely give DummyNet a try.
If you're a BSD guru this article is not for you. If you have spare hardware and want to set up your dedicated DummyNet box, this article is, again, not for you. If, on the other hand, you want something you can be up and running with in 20 minutes then read on.
There have been many articles published about DummyNet. You should read one or two so you can familiarize yourself with the concept. A very quick intro: DummyNet is part of the BSD routing package. You set up at least two network interfaces on a BSD box, you tell DummyNet what kind of conditions to simulate between two interfaces or even two IP addresses and it will go ahead and do it. Yes, you get to muck around in config files and master typing ipfw add pipe faster than you can think it, but you do get to save a lot of money. And you do get to have the right amount of bandwidth, the right amount of packet loss and the right amount of latency. If you want to be extra-sneaky you can even have DummyNet reorder packets for you.
I'm including a fully configured VMWare image with BSD and DummyNet already set up. All you need to do is put in the right IP addresses, configure the rest of your system to use the BSD VM as the router, and you're good to go.
Here's what we're going to do:
You will have your PC running VMWare (on whatever OS you like), you will have a virtual machine in VMWare (again, running whatever OS you like), and another VMWare guest OS will run BSD and route IP traffic between the two - optionally adding latency and dropping packets as you wish.
VMWare provides ten virtual networks. VMNet0 is typically used for "bridged" connections - connections that use your host PC's network card. VMNet1 is reserved for host-only networking and VMNet8 is used for NAT. We need an unused virtual circuit to link your VMWare guest OS and the BSD router, and this cannot be associated with the host. I picked VMNet2.
If you look at the diagram above, you can see that the host computer is on the 192.168.0.* subnet. I've put the guest virtual machine on the 192.168.20.* subnet, and the BSD "box" has two virtual NICs, one on each network.
You are, of course, not required to use these IP addresses. I will tell you where to change them as we go forward - whenever you encounter references to my addressing scheme just substitute your own IPs.
The BSD Box
Download the pre-built BSD VMWare installation from here. This is a hefty download at 34 megs - it's a full-fledged (but text-only) BSD install with SSH and the like. Some non-essential things (like man pages) have been removed, but I wanted to retain as much functionality as possible. You will need Rar or WinRar to extract the download. It will expand to about 120 megs.
Once you have the file and extracted its contents, load the virtual machine. The login is "root" and the password is "root". Type mc for Midnight Commander if you like.
If you want to change the IP addresses, go to /etc and edit the rc.conf file as shown above. lnc0 is VMNet0 and lnc1 is VMNet2. If you want your guest OS behind DummyNet to access the Internet, you should update the defaultrouter value as well.
You should also edit rc.firewall as above. Go to line 149 and change the "host" IP address (this is your host computer) and also change "client" in line 150 (this is the VMWare guest on VMNet2).
Once you've updated the IP addresses, type /etc/netstart to re-initialize networking, and you're good to go with the BSD part:
mybsd# /etc/netstart devd already running? (pid=257). lnc0: flags=108843
mtu 1500 inet6 fe80::20c:29ff:febe:10a3%lnc0 prefixlen 64 scopeid 0x1 ... add net default: gateway 192.168.0.1 Additional routing options: IP gateway=YES. mybsd#
The guest OS
Open the guest OS you want to put behind DummyNet in VMWare and edit the VM configuration. Specifically, select the Ethernet adapter and change the Network Connection to Custom, then select VMNet2. Like so:
Now boot up the guest OS. Once you're in, change the IP address and default gateway of the guest. This is how this looks like in Windows with my values:
Note that you will need to change the default gateway to the VMNet2 address of your BSD box, but unless you configured a DNS server on the box, you will still need the guest OS to go to your regular DNS servers. Typing "nslookup" on your host computer will tell you the DNS server's address:
C:\temp>nslookup Default Server: MARTONNET1 Address: 192.168.0.1 > exit
There are two things left to do: your host computer does not know about the newly set up route between your guest OS and your host machine. You will need to add the route manually, by typing this at a command promopt:
C:\>route add 192.168.20.0 MASK 255.255.255.0 192.168.0.10 C:\>Unfortunately, you will need to do this after every reboot of the host.
Finally, if you want your guest OS to access the Internet, you will need to tell your Internet router about the new network too. On my Linksys with the DD-WRT firmware I needed to do this:
Note that configuring the router is only required for accessing the Internet from the guest OS. If you want to test between the host and guest only, you just need to enter routing information into your host.
Up and running
Now that you have everything configured properly, open up a command prompt (shell, DOS box, etc) in the guest OS and try to ping your host computer. If all goes well, you will receive replies! Whew.
Now go back to the BSD VM and edit rc.firewall again. Comment the line under #this is normal operation by adding a # at the beginning, and uncomment lines 159 and 160, like this:
Save the file, then type /etc/netstart to reinitialize networking. You should now have a network connection between your host computer and the guest OS that exhibits ~160ms RTT latency and 4% RTT packet loss. (Granted, we've specified 40ms latency and 0.01 = 1% loss in the config file, but this is an ANY to ANY rule and works in both directions, therefore it takes effect four times: receiving the echo request from the client, sending it to the host, receiving the response from the host, and sending the response to the client.)
C:>ping -t 192.168.0.3 Reply from 192.168.0.3: bytes=32 time=172ms TTL=127 ... Reply from 192.168.0.3: bytes=32 time=163ms TTL=127 Request timed out. Reply from 192.168.0.3: bytes=32 time=172ms TTL=127 Reply from 192.168.0.3: bytes=32 time=163ms TTL=127 Reply from 192.168.0.3: bytes=32 time=207ms TTL=127 Ping statistics for 192.168.0.3: Packets: Sent = 946, Received = 907, Lost = 39 (4% loss), Approximate round trip times in milli-seconds: Minimum = 91ms, Maximum = 523ms, Average = 198ms Control-C ^C C:\>Have fun!
I know I said 160ms and the above shows 198 on average. I guess the timing accuracy leaves a bit to be desired - but rest assured, it gets the job done.
Also, the BSD box comes without a swap partition, and has 92 megs of RAM configured. Feel free to adjust it if you like - but going below 64 megs is really not recommended. 92 megs is a good compromise: it allows the box to be run continuously without affecting system performance.