Load-Balancing network traffic on Mikrotik router tutorial with example configuration

This is first part of a tutorial how to achieve load-balancing of a service on two servers. In this part we will focus on the network side and I will show how to use a Mikrotik home router as a load-balancer. Also I will show you the basic things Mikrotik can do for you like tracking the servers with pings and if one goes down reroute all the traffic to the remaining servers and/or send you email that one of the physical servers have failed.

This post is directly related to the previous announcement of networkgeekstuff.com running on two Raspberry PIs. So when you are reading this, you are going over the same system of load-balancing as shown here.

PS: If you like to read first a quick summary of load-balancing theory, I can point you to my older article about Basic Load-Balancer Scenarios. This example will create the most basic scenario of “Two-Arm Load-Balancer”.

The example topology of what we want to achieve is below:

NOTE on Stickiness concept:
The problematic part on load-balancing is something called “Stickiness” with applications that have multiple TCP sessions or independent requests. With these applications you have to make sure that a single users will always be load-balanced to the same server, otherwise there could be problems. For example if you login to one server, but all your next requests will be load-balanced to a different server that didn’t know you, then the user will have problem working correctly.

In my situation, I have dealt with Stickiness issue the most simple way imaginable, the load-balancing algorithm will make use of the client source IP, so one single source IP of a user (or more users) will be always forwarded/load-balanced to the same server.

Configuration

First, lets mark the incoming traffic.

/ip firewall mangle
 add chain=prerouting in-interface=ether1 per-connection-classifier=src-address:2/0 \
 action=mark-connection new-connection-mark=Pi132 passthrough=yes
 add chain=prerouting in-interface=ether1 per-connection-classifier=src-address:2/1 \
 action=mark-connection new-connection-mark=Pi134 passthrough=yes

This is basically where the Stickiness magic happens, before the packet is routed, it passes through prerouting table, usually nothing interesting happens there, but now we created these rules telling microtik the following with the most interesting per-connection-classifier:
1) first rule: get the source IP, and if you divide it with 2 and get 0 left, mark it with “Pi132” mark.
2) second rule: get the source IP, and if you divide it with 2 and get 1 left, mark it with “Pi134” mark.

You now have all the packets coming from ODD and EVEN source IPs marked. We will next use this mark to NAT and forward traffic. Do not forget the comments, they will be used later for script identification.

/ip firewall nat
 add chain=dstnat action=dst-nat to-addresses=192.168.10.132 protocol=tcp \
 in-interface=ether1 dst-port=80 connection-mark=Pi132 \
 comment="LoadBalancedHTTPto132PI"
 add chain=dstnat action=dst-nat to-addresses=192.168.10.134 protocol=tcp \
 in-interface=ether1 dst-port=80 connection-mark=Pi134 \
 comment="LoadBalancedHTTPto134PI"

And that’s it, technically if you do not have any need for failover detection and or failover mechanism, you are done. From this point onward we will focus on the point of managing the situation when one of the servers will fail and we need to redirect the traffic to the remaining one.

Failover mechanism and probing

First, lets create two more nat rules, these rules will be uses as last resort as they are rules that do not clasify by connection-mark, so any traffic will go through them.

/ip firewall nat
 add chain=dstnat action=dst-nat to-addresses=192.168.10.132 protocol=tcp \
 in-interface=ether1 dst-port=80 comment="DefaultHTTP to PI 192.168.10.132"
 add chain=dstnat action=dst-nat to-addresses=192.168.10.134 protocol=tcp \
 in-interface=ether1 dst-port=80 comment="DefaultHTTP to PI 192.168.10.134"

Now, lets create scripts, we will have four scripts for every event there can be. Every script will enable/disable a specific NAT rule by finding the rule searching for the correct rule comment.

One for the possibility of PI server on 192.168.10.132 going DOWN

/system script add name=Pi132_DOWN source={
 # Pi132 DOWN script
 /ip firewall nat disable [find comment="LoadBalancedHTTPto132PI"];
 /ip firewall nat disable [find comment="DefaultHTTPto132PI"];
 /tool e-mail send to=no-exist@gmail.com subject="NetworkGeekStuff: Pi132 down" \
 body="The NetworkGeekStuff.com server 192.168.10.132 is down" server=213.46.255.2 \
 from="admin@networkgeekstuff.com";
}

One for the possibility of PI server on 192.168.10.132 going UP

/system script add name=Pi132_UP source={
 # Pi132 UP script
 /ip firewall nat enable [find comment="LoadBalancedHTTPto132PI"];
 /ip firewall nat enable [find comment="DefaultHTTPto132PI"];
 /tool e-mail send to=no-exist@gmail.com subject="NetworkGeekStuff: Pi132 UP" \
 body="The NetworkGeekStuff.com server 192.168.10.132 is UP" server=213.46.255.2 \
 from="admin@networkgeekstuff.com";
}

One for the possibility of PI server on 192.168.10.134 going DOWN

/system script add name=Pi134_DOWN source={
 # Pi134 DOWN script
 /ip firewall nat disable [find comment="LoadBalancedHTTPto134PI"];
 /ip firewall nat disable [find comment="DefaultHTTPto134PI"];
 /tool e-mail send to=no-exist@gmail.com subject="NetworkGeekStuff: Pi134 down" \
 body="The NetworkGeekStuff.com server 192.168.10.134 is down" server=213.46.255.2 \
 from="admin@networkgeekstuff.com";
}

One for the possibility of PI server on 192.168.10.134 going UP

/system script add name=Pi134_UP source={
 # Pi134 UP script
 /ip firewall nat enable [find comment="LoadBalancedHTTPto134PI"];
 /ip firewall nat enable [find comment="DefaultHTTPto134PI"];
 /tool e-mail send to=no-exist@gmail.com subject="NetworkGeekStuff: Pi134 UP" \
 body="The NetworkGeekStuff.com server 192.168.10.134 is UP" server=213.46.255.2 \
 from="admin@networkgeekstuff.com";
}

And now the final piece, Mikrotik supports the ability to monitor IP addresses by ping and executing stcripts when the IP is considered UP and DOWN. In our case, it is very simple configuration:

/tool netwatch
add host=192.168.10.134 timeout=20 interval=5 down-script=Pi134_DOWN \
up-script=Pi134_UP
add host=192.168.10.132 timeout=20 interval=5 down-script=Pi132_DOWN \
up-script=Pi132_UP

Verification

Now you can have a look on the current status.

[non-existent@networkgeekstuffRD450] /tool netwatch> print 
Flags: X - disabled 
 #   HOST                 TIMEOUT            INTERVAL  STATUS  SINCE               
 0   192.168.10.132       20s                2s        up      nov/27/2012 00:22:12
 1   192.168.10.134       20s                2s        up      nov/29/2012 16:16:18

Regarding the e-mail configuration, you should have a look inside the /tool e-mail, in the examples I used gmail, but to be honest I had to change it for my local provider email because gmail was a little weird. So experiment a little with emails you have available for you.

Also to verify that the NAT is working correctly, you can reset the NAT statistics with /ip firewall nat reset-counters-all and have a look at the nat-rule counters with /ip firewall nat print.

Summary

Well, I just love when my little piece of routing HW can surprise me with being able to do something more than originally intended when I was buying it 3 years ago for around 50 EUR. So in summary, I hope you liked this quick tutorial.

RB450 Mikrotik
RB450 Mikrotik
---
Peter Havrila , published on