Ключевые слова:mpd, vpn, pptp, freebsd, shaper, limit, speed, bandwidth, radius, traffic, (найти похожие документы)
From: Vitaliy Yermistov <vantooatukrdotnet>
Newsgroups: email
Date: Mon, 07 Aug 2006 14:31:37 +0000 (UTC)
Subject: Ограничение пропускной способности каналов при реализации VPN сервера на базе MPD
Часто VPN сервер используется как часть биллинговой системы провайдера
для предоставления доступа в Интернет пользователям локальной сети.
При этом зачастую возникает необходимость ограничения пропускной способности
канала, причем скорость передачи данных должна отличатся индивидуально для каждого
пользователя. В данной статье я хочу предложить свой способ решения данной
задачи.
Самыми распространенными являются следующие ситуации:
1. Биллинговая система основана на протоколе AAA Radius.
2. Биллинговая система ведет учет трафика с помощью других программных средств,
либо вообще не нуждается в подсчете объема переданной и принятой информации.
В первом случае наиболее целесообразно, на мой взгляд, подключить к Radius
словарь MPD:
######################## dictionary.mpd ###############################
VENDOR mpd 12341
ATTRIBUTE mpd-rule 1 string mpd
ATTRIBUTE mpd-pipe 2 string mpd
ATTRIBUTE mpd-queue 3 string mpd
#######################################################################
Файл необходимо разместить в папке, в которой хранятся словари вашего Radius,
и внести имя файла dictionary.mpd в список используемых словарей. Далее необходимо
заставить Radius передавать необходимые параметры (ACL) MPD. В данной статье мы не
будем детально рассматривать этот способ, так как он подробно описан в документации MPD,
которую Вы можете найти в папке /usr/local/share/doc/mpd. Скажу только, что работает
он хорошо, его я и предпочитаю использовать.
Однако в случае, если биллинговая система не предусматривает использования сервера
Radius, а источником имени пользователя и пароля служит стандартный файл mpd.secret
(например, если провайдер небольшой), то в качестве альтернативы я хочу предложить
следующий выход (сразу оговорюсь, что ниже представленные скрипты Вы можете использовать
исключительно на свой страх и риск, и претензии в случае неправильной работы системы
автором статьи не принимаются).
Подразумевается, что у Вас уже имеется, сконфигурированный и работающий VPN сервер на MPD,
если нет, то воспользуйтесь статьями, по этой теме.
Добавьте в файл mpd.conf следующие строки:
set iface up-script /usr/local/etc/mpd/shaping/up.sh
set iface down-script /usr/local/etc/mpd/shaping/down.sh
Не забываем сделать отступы табуляциями в начале строк!
Если конфиги Вашего MPD лежат не в папке /usr/local/etc/mpd/, то измените эти строки,
и все последующие вхождения /usr/local/etc/mpd/ на свой путь к конфигам.
Создаем папку, в которой будут хранится наши файлы:
cd /usr/local/etc/mpd/
mkdir shaping
cd shaping
Здесь создаем следующие файлы:
######################## bandwidth.dat ################################
# user incoming outcoming
bill 32Kbit/s 64Kbit/s
eva 16KBytes/s 1MBytes/s
sam 128Kbit/s 1000Kbit/s
#######################################################################
Это собственно файл, в котором необходимо указать пропускную способность входящего и
исходящего каналов для каждого пользователя. Имена пользователей должны совпадать с именами
в файле mpd.secret. Направление потока (входящий, исходящий) принимаются относительно сервера.
Примеры указания значений скорости передачи: 32Kbit/s 6Mbit/s 24KBytes/s 4MBytes/s, будьте
внимательны, если неправильно указать значение, то пользователь получит неограниченный канал.
Все символы, следующие за символом "#" игнорируются, игнорируются также лишние пробелы,
табуляции и пустые строки.
########################### parse.awk ##################################
BEGIN { FS = "#" }
{ if ( $1 != "" ) print $1 }
########################################################################
Это вспомогательный скрипт на языке awk, его будет использовать следующий скрипт.
############################### up.sh ##################################
#!/bin/sh
# UP-SCRIPT
cd /usr/local/etc/mpd/shaping
intnum=$(awk "BEGIN { printf \"%03s\", substr(\"$1\", 3) }")
username=$5
incom=$(awk -f parse.awk bandwidth.dat | awk "NF > 0 && \$1 == \"$username\" { print \$2 }")
if [ "$incom" = "" ]; then
incom="32Kbit/s"
echo $(date '+%Y-%m-%d %H:%M:%S')" Incomming bandwidth for user [$username] are not determined, I set it to 32Kbit/s" >> shaper.log
fi
# Если значение ширины входящего канала для данного пользователя не указано,
# то используется значение 32Kbit/s, в этом случае создается запись в
# файле /usr/local/etc/mpd/shaping/shaper.log, проверяйте этот файл время от времени.
outcom=$(awk -f parse.awk bandwidth.dat | awk "NF > 0 && \$1 == \"$username\" { print \$3 }")
if [ "$outcom" = "" ]; then
outcom="32Kbit/s"
echo $(date '+%Y-%m-%d %H:%M:%S')" Outcomming bandwidth for user [$username] are not determined, I set it to 32Kbit/s" >> shaper.log
fi
# Та же проверка и для исходящего канала
ipfw pipe $(echo 30$intnum) config bw $incom
ipfw pipe $(echo 31$intnum) config bw $outcom
ipfw add $(echo 30$intnum) pipe $(echo 30$intnum) all from any to any in via $1
ipfw add $(echo 31$intnum) pipe $(echo 31$intnum) all from any to any out via $1
ipfw add $(echo 32$intnum) allow all from any to any via $1
################################################################################
Этот скрипт вызывается MPD при установлении соединения с хостом пользователя
и добавляет правила IPFW, ограничивающие пропускную способность каналов.
В Вашей системе должен работать IPFW, для этого скомпилируйте ядро с опциями:
options IPFIREWALL # ОБЯЗАТЕЛЬНО! Сам IPFW
options IPFIREWALL_VERBOSE # Поддержка логирования
options IPFIREWALL_FORWARD # Поддержка перенаправления пакетов
options IPFIREWALL_VERBOSE_LIMIT=100 # Ограничение кол-ва лог-записей
options IPFIREWALL_DEFAULT_TO_ACCEPT # Обязательно для начинающих!
options DUMMYNET # ОБЯЗАТЕЛЬНО! Формирователь трафика
options IPDIVERT # Скорее всего понадобится для NAT
И, наконец, последний скрипт
############################# down.sh ######################################
#!/bin/sh
# DOWN-SCRIPT
intnum=$(awk "BEGIN { printf \"%03s\", substr(\"$1\", 3) }")
ipfw pipe delete $(echo 30$intnum)
ipfw pipe delete $(echo 31$intnum)
ipfw delete $(echo 30$intnum)
ipfw delete $(echo 31$intnum)
ipfw delete $(echo 32$intnum)
############################################################################
Этот скрипт вызывается MPD при разрыве соединения с хостом пользователя,
здесь удаляются правила, созданные предыдущим скриптом (IPFW позволяет создавать
множество правил под одним номером, и если их не удалять, то вывод команд
ipfw show и ipfw pipe show засоряется старыми правилами).
При добавлении своих правил IPFW не используйте номера с 30000 по 32999,
они используются данной системой, думаю остальных 62535 номеров Вам должно хватить :-)
Не забываем сделать скрипты исполняемыми:
chmod 774 up.sh
chmod 744 down.sh
Вот, собственно, и все, перезапускаем MPD и проверяем работу системы. Удачи!
а как быть с паритетным трафиком проходящим через тотже тунель что и интернет?
нужно делать как минимум 2 пайпа. А если таких ресурсов/паритетов много, и скорости туда должны быть разные?
Понятно, что статья это лишь толчок - идея. Но перспектив роста так сказать нет.
Вопрос рассматривается с точки зрения провайдера,
а как там дальше клиент будет канал нарезать,
нас уже не интересует. Шейпинг в лок. сетях
учреждений - это уже другая история.
по опыту скажу так - проще юзерам назначать просто классы по скорости-трафику, и выдавать фиксированные ипы из сетей, принадлежащих определенным классам
блин, а у мну не шейпицца :(
если я один, то занимаю весь канал, а не выделенный пайпом.
если нас двое, то вроде как и делится, но не поровну...
в чем может быть трабла?