Ever had to move a bunch of servers (in our case about 30) to another location in a hurry? Every wondered if it would be easy to give your clients the same ip address before and after the migration, at least for a little while until they have their DNS’s updated?
Well, it is easy in fact. How? By using a neat little program called tcpproxy. This is actually all you need. You simply wip up a config file;
/etc/tcpproxy.conf
port 22
# old ip
interfaces 192.168.0.1
# new ip
server 192.168.1.1
and run ./tcpproxy
Two servers are moved in need of port 22? Simple, just do:
port 22
# old ip
interfaces 192.168.0.1
# new ip
server 192.168.1.1
# old ip
interfaces 192.168.0.2
# new ip
server 192.168.1.2
etc.
After entering a bunch of servers like this (up to thirty in our case, with every servers having bunches of open ports), you get a bit tired of this format. So let’s get our trusty Perl working this for us.
Personally I like configuration formats which are clear, simple and fast. So I wipped up the following format:
servername:oldip:newip:ports
for example:
killer:34:138:22,80,81,8080
and another one:
killer:34:138:22,80,81,8080
killer2:35:139:22,80,81,143,993
etc.
As you might notice (I hope); the ip address is not complete; in our case, we move from one network to another in which the first 3 numbers in the ip address are the same. For instance:
Before IP: 192.168.0.*
After IP: 192.168.1.*
The script I made to read in the configuration file should have some configuration settings:
# settings
$oldr = “192.168.0”; # old ip address range
$newr = “192.168.1”; # new ip address range
$eth = “eth0”; # ethernet card to make aliases for
An observant reader might notice that I added the ethernet card; this is because we want to use one machine for the forwarding, not as many machines as there were before 🙂 Also we would want the settings for this forwarding machine to be auto-generated. For the above case, we need to have:
ifconfig eth0:0 192.168.0.1 up
ifconfig eth0:1 192.168.0.2 up
To make tcpproxy to be able to listen to incoming requests on those addresses.
In case there already are alias interfaces on $eth, we need to figure out what they are, so we can decide where to start counting new aliases:
# calc interface start
$count = `ifconfig|grep $eth|tail -n 1|awk ‘{print $1}’|grep :|sed -e s/$eth://`;
if ($count eq “”) {
$count = 0;
} else {
$count++;
}
$first = $count;
Next step is to generate all the settings for the /etc/tcpproxy.conf file and to generate a set and unset interface file for you to run to get the computer in the proper mode to listen to all incoming requests:
open(F, $f);
open(SET, “> ./set$eth.sh”);
open(UNSET, “> ./unset$eth.sh”);
print SET “#!/bin/shn”;
print UNSET “#!/bin/shn”;
while() {
chomp;
next if /^$/;
($umln,$ipo,$ipn,$pts) = split(/:/);
print SET “# $umlnnifconfig $eth:$count $oldr.$ipo upn”;
print UNSET “# $umlnnifconfig $eth:$count downn” if $count == $first;
$count++;
foreach(split(/,/,$pts)) {
$port{$_}.=”# $umlnn”;
$port{$_}.=” interface $oldr.$ipon”;
$port{$_}.=” server $newr.$ipnn”;
}
}
close F;
close SET;
close UNSET;
We cannot write the tcpproxy.conf as we go along, because it is only allowed to have one
port X
per set of interfaces and servers. In the above code we collected all ports with their interfaces settings, contained in $port.
We only have to put these into a nice string which is, in fact, the /etc/tcpproxy.conf file; we leave the saving of it to the reader. For fun it is nicely sorted by port 🙂
foreach(sort {$a <=> $b} keys %port) {
$tot .= “port $_n”;
$tot .= $port{$_};
$tot .= “n”;
}
Have fun!