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

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 "\015\032" `" 

Используя консольный калькулятор 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
Блог автора

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

Комментарии 31

    +1
    Ваш способ не сработает если IP пулами заведует RADIUS:
    [] show ippool Available IP pools: poolsat: used 0 of 510
    Но можно узнать количество сессий с помощью вот такого скрипта:
    #!/usr/local/bin/bash online=`ifconfig | grep ng | wc -l` echo $online" exit 0
      0
      Хм… почему-то тэг похерил форматирование
        0
        netstat работает значительно быстрее чем ifconfig
        /usr/bin/netstat -rn | grep -v grep | grep -c ng
          0
          Микросекунды решают
        +10
        Ссылка на блог автора повеселила)
          0
          Дело в том, что работа скрипта осуществляется на DNS сервере, который не является MPD5 сервером, поэтому вариант с ifconfig не подходит. Кол-во сессий можно еще узнать так:
          http://0.0.0.0:5006/bincmd?show%20mem
          Среди прочей информации будет значение BUND — количество фактически поднятных ng интерфейсов
            0
            Дело в том, что работа скрипта осуществляется на DNS сервере, который не является MPD5 сервером, поэтому вариант с ifconfig не подходит.

            Подходит. Если есть ssh доступ к серверу с MPD. У меня так графики загруженности в rrdtool рисуются.
            И чем http лучше ssh?
              0
              Согласен, в принципе, можно было и через ssh организовать. Мне показалось, что проще будет распарсить одну страницу http. Дело, как говориться, вкуса.
              +1
              Как правило для такого туннелирования используются либо серьезные железки (Cisco, Juniper, etc), либо софт-роутеры на базе FreeBSD и MPD5.

              Либо Linux и poptop/accel-pptp/rp-pppoe/accel-ppp
                +1
                Все это работает в usermode и нету аналога netgraph.
                  0
                  userspace т.е.
                    +1
                    Из всего этого только poptop работает в userspace.
                    +1
                    В Linux pppd сотоварищи шибко ущербное решение в сравнении с MPD. Мы это поняли, когда, устав от спорадических зависаний серверов доступа под Debian, преревели их на FreeBSD с MPD. И виснуть перестало и кучу «полезностей» получили.
                      +1
                      FreeBSD вообще на мой взгляд лучше в качестве шлюза, роутера, сервера доступа. Таже quagga для BGP чувствует себя на фряхе заметно лучше. Организация работы VLAN просто чудесна по сравнению с Linux. Зато в качестве сервера приложений мне больше нравится Linux, хотя и фря вполне себе со многими задачами справляется.
                        0
                        Угу, каждому овощу своё поле 8)
                        –2
                        Дело вкуса. У меня не было проблем с pptpd и pppoed на дебианах.
                          –2
                          У любителей фряхи в линуксах всегда что-то не работает.
                            0
                            Мне лично фря параллельна. Главное что работает без сбоев и можно в выходные спокойно отдохнуть от всего этого бедлама.
                      0
                      Подправьте использования grep. Он может напрямую парсить файл.

                      grep used "$workdir/$ipsrv" 
                      
                      0
                      у меня балансер находится на днс-сервере и лазит по vpn-ам через ssh с авторизированным ключем. В списке балансера у каждого сервера vpn стоит коэффициент его вычислительной мощности. при опросе серверов выбирается наименее запруженный, который и становится vpn.local
                      скрипт который выполняется на vpn:

                      #!/bin/sh
                      /bin/ps ax | grep -v grep | grep -c mpd5
                      /usr/bin/netstat -rn | grep -v grep | grep -c ng

                      отдаёт: жив ли mpd и сколько текущих сессий
                        0
                        картинка такая получается
                        image
                        0
                        Реализовывал аналогичную штуку, только dns сервер был самописный. Статистика снималась через fabric, а dns сервер был реализован на twisted.
                          0
                          А почему была необходимость в собственном dns сервере?
                            0
                            Документацию по bind не удосужился прочитать и NIH роль сыграл ) Ну и к тому же там еще была необходимость некоторых пользователей сажать на определенные сервера. Был вариант — powerdns + pipe backend, но решил сам имплементить это добро.
                              0
                              Мы такие задачи в bind разруливали с помощью view.
                          0
                          В свое время стояло 20 разных впн-серверов. Основные моменты в принципе как во всех выше приведенных примерах:
                          1. у каждого сервера был свой «вес», коэффициент в зависимости от его процессорной мощности (использовались несколько однотипных платформ, так что при установке нового сервера вес бы уже известен)
                          2. каждый впн-сервер раз в минуту собирал сам некое взвешенное число получаемое из кол-ва своего трафика в pps'ах и кол-ва сессий. Почему только не один из этих параметров, а совокупность? — потому что большое кол-во сессий не всегда прямо пропорционально трафику (допустим сломалась маршрутизация и т.п, и трафика нет, а балансер будет все кидать и кидать сессии на этот сервер). NAS отдавал эти числа по обычному snmp (exec в snmpd.conf на сервере и snmpwalk .1.3.6.1.4.1.2021.8.1.101 на балансере)
                          По snmp же строились графики онлайна, загрузки, pps
                          3. TTL для имени впн-сервера был крайне малым — 1-2 минуты, выдавались 4 самых ненагруженных nas'а роунд-робином

                          для выключения nas'а из балансировки для обслуживания можно было погасить снмп демон на нем.
                            0
                            А что же вы делаете с клиентами, у которых статический ип-адрес?
                              0
                              выход в интернет только через туннель. если без туннеля, то клиент варится в локальных ресурсах
                              0
                              Я про статический ип в инернет. Если раздавать реал, то пуллы закреплять за насами нужно, а они тут балансируют видите ли. Как на практике решаете вопрос статика за разными насами? BGP? proxy arp? Еще что-нибудь
                                0
                                дык ospf решает

                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                              Самое читаемое