📜 ⬆️ ⬇️

Load balancing on PPTP / L2TP MPD5 servers

image

Many providers in the post-Soviet space of various scales provide Internet services over a VPN tunnel, be it PPPoE or PPTP / L2TP. I will not talk about the pros and cons of such access, since this topic can be safely placed in a separate article. As a rule, for such tunneling, either serious pieces of hardware (Cisco, Juniper, etc), or FreeBSD and MPD5-based software routers are used. So, in this article we will talk about load balancing on MPD5 servers. On Habré there was already a similar topic , but PPPoE was considered there, but today we’ll analyze the situation with PPTP / L2TP.

Theory


The simplest way to balance VPN servers is the so-called Round robin DNS . Having executed the nslookup vpn.iformula.ru command, we will see the following:

  nslookup vpn.iformula.ru 
 Server: 193.93.236.2 
 Address: 193.93.236.2 # 53

 Name: vpn.iformula.ru
 Address: 10.168.1.103
 Name: vpn.iformula.ru
 Address: 10.168.1.101
 Name: vpn.iformula.ru
 Address: 10.168.1.102 

( you can try nslookup yandex.ru - Round robin DNS is also used )
')
Those. The client, sending a request to the DNS server, receives in response the first address from the list, the second request — the next address, and so on in a circle. In principle, such a balancing would be enough if not for several circumstances:

An imbalance is created that can naturally be smoothed out for a long time.
The way out of these situations is simple: you need to monitor the number of simultaneous user sessions and when the maximum load on the server or its emergency shutdown is reached, stop announcing its ip-address in the DNS. Of course, we automate this using a shell script.

Practice


1. We need to get information about the number of current sessions and the maximum allowable number of sessions. MPD5 has control via telnet and webcmd. I chose webcmd, because in this case I just need to get the html page and parse it, rather than writing a handler for the telnet CLI on Expect . Enable web management:

set user $ROOT $PASSWORD admin set web self 0.0.0.0 5006 

After restarting mpd at 0.0.0.0 : 5006, various information will be available. You can get information about the sessions like this: http: // $ login: $password@0.0.0.0: 5006 / cmd? Show% 20ippool
 [] show ippool Available IP pools: pool1: used 1293 of 2047 

2. Configure the DNS server. I use BIND9, which is standard on FreeBSD. I assume that you already have a configured DNS server with a serviced zone. All we need is to add $ INCLUDE to this automatically generated file with the list of VPN servers:

 $INCLUDE /var/named/etc/namedb/vpn ; ;host names iformula.ru. IN A 193.93.236.126 

3. Add an automation script to the cron scheduler for execution every 30 minutes. Of course, you need to run the script on the server where the DNS daemon is running.

 echo "*/30 * * * root /usr/local/bin/mpd_balancer" >> /etc/crontab echo "" >> /etc/crontab 

We will analyze the script


Options:

 login="foo" 
# Username
 password="bar" 
# and password to access Webcmd MPD5
 prcload="90" 
# maximum permissible number of simultaneous sessions on a single server as a percentage
 name="vpn.example.com." 
# VPN service name, full stop is required
 srvlist="/root/srv" 
#Access to the file with the list of vpn servers
 conf="/var/named/etc/namedb/vpn" 
# path to generated $ INCLUDE with a list of vpn servers available to clients
 workdir="/tmp" 
# directory for temporary files

Get an HTML page with information about the sessions:

 fetch -o $workdir/$ipsrv -q "http://$login:$password@$ipsrv:5006/cmd?show%20ippool" > /dev/null 2>&1 

Parse the number of active and maximum sessions for the server:
 mpdsrv="`cat "$workdir/$ipsrv" | grep used | awk '{print ($3)}' `" maxloadsrv="`cat "$workdir/$ipsrv" | grep used | awk '{print ($5)}' | tr -d "\015\032" `" 

Using the console calculator bc , we calculate the current server load as a percentage (percentages are rounded to whole numbers):

 loadsrv="`echo "$mpdsrv/($maxloadsrv/100)" | bc`" 

If the load does not exceed the specified percentage, add the server address to the list of available, loaded and inaccessible servers, simply comment:

 if [ "$loadsrv" -lt "$prcload" ] then echo "$name IN A $ipsrv" >> $conf else echo ";$name IN A $ipsrv" >> $conf fi 

Also, if you just run the script from the console, we get the following data:

 ####################################################################### 10.168.1.100 hosts 739 sessions and this is 49% of maximum load 10.168.1.101 hosts 1192 sessions and this is 70% of maximum load 10.168.1.102 hosts 1304 sessions and this is 65% of maximum load 10.168.1.103 hosts 138 sessions and this is 27% of maximum load 10.168.1.104 hosts 24 sessions and this is 24% of maximum load ####################################################################### 

Based on this data, you can draw beautiful graphics:
image

The script uses the bc, fetch, and rndc utilities — all of this comes standard with FreeBSD. The script was tested on FreeBSD 8.3, for Linux, you have to replace fetch with wget. Supports any number of mpd5 servers.

Script:

Link # 1
Link # 2

MPD5 Documentation
BIND9 documentation
Sh reference
Author's blog

Comments, suggestions, questions and comments are welcome. Thanks for attention.

Source: https://habr.com/ru/post/148144/


All Articles