I am fortunate enough to be a part of a great group called NYC Networkers. I have been asked to come up with relevant topics in the networking area and teach them to members of the group who RSVP to the meetup. Last Sunday, I did a meetup on “Basic LoadBalancing Principals,” and a decent-sized crowd was there. I threw in as a part of my live demonstration that if, in a pinch, you could do basic load balancing (this case, it is load distribution) using an IOS device and our good old friend NAT, and a few people asked if I could write a blog post about it so it will live on in internet immortality. So, without further adieu, here it is!
Our topology is basic, with one router acting as a host, one route acting like an entire ISP, and four routers acting like servers, as depicted in the diagram below.
We need to set up basic load balancing services between 4 Telnet servers (I know, the only easy way to show it works is with Telnet). The routers are configured with basic connectivity to the ISP. We need to define the inside/outside NAT interfaces on the ISP in the old-school, non-NVI way.
Configuration
ISP(config)#int fastethernet0/0
ISP(config-if)#ip nat outside
ISP(config-if)#int fastethernet0/1
ISP(config-if)#ip nat inside
ISP(config-if)#end
Beautiful! Now let’s define what I am calling my VIP (which so happens to sit on the same subnet as the interfaces connected)
ISP(config)#ip access-list extended LOAD_BALANCE_VIP
ISP(config-ext-nacl)#permit tcp any host 56.44.24.110 eq 23
OK, now the fun starts; we will define a NAT pool but add a unique keyword at the end and add the hosts we want to load-distribute over in this list.
ISP(config)#ip nat pool LOAD_BALANCE prefix-length 24 type rotary
ISP(config-ipnat-pool)#address 172.20.224.10 172.20.224.10
ISP(config-ipnat-pool)#address 172.20.224.11 172.20.224.11
ISP(config-ipnat-pool)#address 172.20.224.12 172.20.224.12
ISP(config-ipnat-pool)#address 172.20.224.13 172.20.224.13
Just a side note: you have to configure it like this if you were to do the configuration below, it would not work properly
ISP(config)#ip nat pool LOAD_BALANCE prefix-length 24 type rotary
ISP(config-ipnat-pool)#address 172.20.224.10 172.20.224.13
Now, let us create the NAT rule
ISP(config)#ip nat inside destination list LOAD_BALANCE_VIP pool LOAD_BALANCE
Testing
Now, let’s test!
Host#telnet 56.44.24.110
Trying 56.44.24.110 ...
% Connection timed out; remote host not responding
Host#telnet 56.44.24.110
Trying 56.44.24.110 ...
% Connection timed out; remote host not responding
ost#telnet 56.44.24.110
Trying 56.44.24.110 ...
% Connection timed out; remote host not responding
It doesn’t seem to be working, and let’s look at some debugs
ISP#sh debug
Generic IP:
IP packet debugging is on (detailed)
IP NAT debugging is on
TCP:
TCP Packet debugging is on
Host#
Host#
Host#
Host#
So, the debugs returned nothing… So what gives? Being that the IP address 56.44.24.110 does not live anywhere on the router. We need to configure an IP alias on the ISP router to facilitate that “virtual” IP Address
ISP(config)#ip alias 56.44.24.110 23
Now, when we re-test, we see no issues
Host#telnet 56.44.24.110
Trying 56.44.24.110 ... Open
Server_1#exit
[Connection to 56.44.24.110 closed by foreign host]
Host#telnet 56.44.24.110
Trying 56.44.24.110 ... Open
Server_2#exit
[Connection to 56.44.24.110 closed by foreign host]
Host#
Now, what changes if that “Virtual IP” was on a different subnet? Let’s say the VIP is on 44.44.44.44; what happens? Well, this is where we fall into a trap. For IP Alias to work, an IP from that subnet must be assigned to an interface as a primary or secondary address. If not, this is the error you get when adding it.
ISP(config)#ip alias 44.44.44.44 23
Invalid IP address
To get around that, you can configure an IP address from that subnet as a secondary interface and then add the alias command.
ISP(config)#int f0/0
ISP(config-if)#ip address 44.44.44.1 255.255.255.0 secondary
ISP(config-if)#exit
ISP(config)#ip alias 44.44.44.44 23
Now let us try our telnet.
Host#telnet 44.44.44.44
Trying 44.44.44.44 ... Open
Server_4#exit
[Connection to 44.44.44.44 closed by foreign host]
Host#telnet 44.44.44.44
Trying 44.44.44.44 ... Open
Server_1#exit
[Connection to 44.44.44.44 closed by foreign host]
Host#telnet 44.44.44.44
Trying 44.44.44.44 ... Open
Server_2#
There you have it: basic load distribution on a Cisco IOS-based router using NAT.