Распределение нагрузки на PPTP/L2TP серверы MPD5

в 8:10, , рубрики: freebsd, shell, балансировка нагрузки, системное администрирование, Телекомы, метки: , ,

image

Многие провайдеры на постсоветском пространстве самых разных масштабов предоставляют услуги Интернет по VPN туннелю, будь то PPPoE или PPTP/L2TP. О плюсах и минусах такого доступа я не буду рассказывать, т. к. данная тема смело поместиться в отдельную статью. Как правило для такого туннелирования используются либо серьезные железки (Cisco, Juniper, etc), либо софт-роутеры на базе FreeBSD и MPD5. Так вот, в этой статье пойдет речь о балансировке нагрузки на MPD5 серверы. На хабре уже был подобный топик, но там рассматривалось PPPoE, сегодня же разберем ситуацию с PPTP/L2TP.

Теория

Самый простейший способ балансировки VPN серверов — это так называемый Round robin DNS. Выполнив команду nslookup vpn.iformula.ru, увидим следующее:

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

(можете попробовать nslookup yandex.ru — так же используется Round robin DNS)

Т.е. Клиент, посылая запрос к DNS серверу получает в ответ первый адресс из списка, запрос второго — следующий адресс и так далее по кругу. В принципе такой балансировки было бы достаточно, если бы не несколько обстоятельств:

  • Не все серверы обладают одинаковой конфигурацией и производительностью
  • При кратковременно падении одного из серверов, все его клиенты подключаться на оставшиеся сервера

Создается дисбаланс, который естественным путем может сглаживаться достаточно долго.
Выход из этих ситуаций прост: нужно мониторить количество одновременных сессий пользователей и при достижении максимальной нагрузки на сервер или его аварийном отключении, перестать анонсировать в DNS его ip-адресс. Разумеется, мы автоматизируем это с помощью shell скрипта.

Практика

1. Нам нужно получить информацию о количестве текущих сессий и максимально-допустимом количестве сессий. В MPD5 есть управление через telnet и webcmd. Я выбрал webcmd, так как в этом случае мне нужно просто получить html страницу и распарсить ее, нежели писать обработчик для telnet CLI на Expect. Включить web управление:

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

После перезапуска mpd по адресу 0.0.0.0:5006 будет доступна различная информация. Получить информацию о сессиях можно так: http://$login:$password@0.0.0.0:5006/cmd?show%20ippool


[] show ippool
Available IP pools:
        pool1:  used 1293 of 2047

2. Настроим DNS сервер. Я использую BIND9, который является стандартным в FreeBSD. Я предполагаю, что у вас уже есть настроенный DNS сервер с обслуживаемой зоной. Все что нам нужно, это добавить в эту зону $INCLUDE на автоматически генерируемый файл с списком VPN серверов:


$INCLUDE /var/named/etc/namedb/vpn ;

;host names
iformula.ru.		IN	A	193.93.236.126

3. Добавляем скрипт автоматизации в планировщик cron на выполнение каждые 30 минут. Разумеется, запускать скрипт нужно на сервере, где работает DNS демон.


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

Разберем скрипт

Параметры:

login="foo"

# имя пользователя

password="bar"

# и пароль для доступа к Webcmd MPD5

prcload="90"

# максимально допустимое количество одновременных сессий на одном сервере в процентах

name="vpn.example.com."

# имя службы VPN, точка в конце обязательна

srvlist="/root/srv"

# Пукть к файлу со списком vpn серверов

conf="/var/named/etc/namedb/vpn"

# путь к генерируемому $INCLUDE со списком vpn серверов, доступных клиентам

workdir="/tmp"

# директория для временных файлов

Получим HTML страницу с информацией о сессиях:

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

Распарсим количество активных и максимальных сессий для сервера:


mpdsrv="`cat "$workdir/$ipsrv" | grep used | awk '{print ($3)}' `"        
maxloadsrv="`cat "$workdir/$ipsrv" | grep used | awk '{print ($5)}' | tr -d "1532" `" 

Используя консольный калькулятор bc, посчитаем текущую загрузку сервера в процентах (проценты округляются до целых):

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

Если загрузка не превышает заданный процент, добавляем адресс сервера в список доступных, нагруженные и недоступные сервера просто комментируем:

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

Так же, если просто запустить скрипт из консоли, получим вот такие данные:

#######################################################################
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
#######################################################################

На основании этих данных можно рисовать красивые графики:
image

В скрипте используются утилиты bc, fetch и rndc — все это есть в стандартной поставке FreeBSD. Скрипт протестирован на FreeBSD 8.3, для Linux придется заменить fetch на wget. Поддерживает любое количество mpd5 серверов.

Скрипт:

Ссылка#1
Ссылка#2

Документация по MPD5
Документация по BIND9
Справочник по sh
Блог автора

Комментарии, предложения, вопросы и замечания приветствуются. Спасибо за внимание.

Автор: Ne_Palimsa


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js