Last time I explained how I needed a quick and easy way to change the IP address of my Windows XP workstation, found a method that sort of worked using the netsh tool, but ultimately discovered that method to be unsatisfactory due to it disruptively tearing down the network interface each time.

But there is a better method. This time I'll show how this problem can be overcome - with a lot of help from free and open source software we can change the effective IP address of our client program as seen from the server without tearing down all the ancillary connections we want to keep alive.

We do this using a NAT gateway.

Preparing a Virtual Machine

Given that I only have admin access to the Windows workstation running our client process, it seemed a natural choice to use a virtual machine for the NAT gateway VMWare Server for Windows is available for free after registration, and I already had it installed. I also had a basic install of Ubuntu 7.04 configured and ready to go in a clean VM. It's always a good idea to take a copy of a VM after completing the OS installation, and in this case I was glad to see that I had remembered to do so.

First of all I had to add a new NIC to the VM. By default, a VM is configured with only one NIC. I couldn't see how to add a new one using the VMWare Server GUI, but it can be done manually by finding the .vmx file for the VM, opening it in your favourite text editor and adding an entry for Ethernet1 below the Ethernet0 line like this:

Ethernet0.present = "TRUE"
Ethernet1.present = "TRUE"

There may be other lines regarding Ethernet0 but don't worry about these. VMWare Server will add the other lines for Ethernet1 as necessary.

Now when the Ubuntu VM starts, it has two NICs. Ubuntu comes configured to automatically use DHCP for eth0 and eth1 which is fine for our purposes.

Setting up the NAT gateway

For what I wanted to accomplish, IP Masquerading looked like a perfect fit. By routing selected traffic from the Windows host machine into one interface of the NAT VM, it should come out of the other interface with its source address modified. The NAT VM would also take care of traffic going back the other way. The Windows host machine can then be configured to route selected traffic via the NAT gateway or not, in order to change the effective IP as required.

To configure IP Masquerading, boot the VM, login to a terminal and get a root prompt (this is Ubuntu so no root account as such)

$ sudo -S

Now as root, add the masquerade rules to the postrouting chain to output on eth1

$ iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE

Then finally tell the kernel yes, we really do want to start forwarding packets

$ echo 1 > /proc/sys/net/ipv4/ip_forward

Done. It really is that simple.

See the Masquerading made simple HOWTO or the full Linux IP Masquerade HOWTO for more details or troubleshooting.

Using the NAT gateway to change effective IP of Windows machine

In order to change the IP address that the server process sees when our client tries to talk to it, we can now just change the routing table on the Windows machine so that we use our NAT gateway instead of the default LAN gateway. The easiest way to do this is to add a new route with a lower metric (cost).

First of all, we need to know the IP address of eth0 on the NAT VM. Use ifconfig to get the IP address used by eth0 and eth1. The IP address of eth0 is the one to which we route traffic from the Windows machine, the IP address of eth1 is the one from which NATed packets will be sent onwards.

In our case, eth0 has the IP 192.168.1.83 which is used in the commands below.

From a command prompt on the Windows machine, start using the NAT gateway by adding a route as follows:

$ route add 192.168.1.0 mask 255.255.255.0 192.168.1.83 metric 1

To revert back to normal, delete the route

$ route delete 192.168.1.0 mask 255.255.255.0 192.168.1.83 metric 1

To automatically alternate between the 2 every 10 seconds, try the following (all on one line, split here for clarity)

for /l %a in (1,1,10000) do 
@echo %a Enabling NAT &
@route add 192.168.1.0 mask 255.255.255.0 192.168.1.83 metric 1 &
@sleep 10 &
@echo %a Disabling NAT &
@route delete 192.168.1.0 mask 255.255.255.0 192.168.1.83 metric 1 &
@sleep 10