В качестве развития вот этой темы ( https://forum.smart-soft.ru/?PAGE_NAME=read&TID=20386&PN=2 ) публикую решение для связки Трафик Инспектора с FreeBSD в качестве шлюза для серых пользователей, дабы уйти от кучи проблем, если конечно у вас не 100 пользователей, а намного больше.
Итак, исходные данные: 1. ТИ стоит "в стороне" от всего транзита - обеспечивает лишь авторизацию абонента по ип-мак-логин-пароль ( выбрать на вкус и цвет ) - он подключен к ядру сети и все к нему имеют доступ. 2. Есть ядро сети - ну например коммутатор dlink 3610G или что-то по-проще, на котором валяются шлюзы пользователей и есть роут на 0.0.0.0 - на например 192.168.0.1 - это и есть FreeBSD машинка, на которой нам надо сделать вкл-выкл пользователям инет ну и порезать скорость в соответствии с тарифом.
Простая схема - юзеры - сети 192.168.2.0/24, 192.168.3.0/24 - на ядре есть интерфейсы 192.168.1.1, 192.168.2.1 - это default gw для этих сетей. Сервер ТИ стоит как 192.168.0.2, Шлюз FreeBSD как 192.168.0.1 - в агенте ТИ у пользователей сервер 0.2, шлюз 0.1 в настройках тцп-ип. ( соответственно роутинг между под-сетями и дефолт 0.0.0.0 - в 0.1 ).
Как реализована схема: - юзер авторизуется на ТИ - на сервере ТИ крутится апач ( или нжинкс, или .... - на выбор ) с поддержкой php. - скрипт на сервере ТИ в пассивном режиме ( по запросу ) отдаёт массив пользователей шлюзу FreeBSD - шлюз FreeBSD в цикле опрашивает сервер ТИ на изменение цепочек и корректирует правила файрвола
Время реагирования в моём случае от 2 до 4 секунд в зависимости от нагрузок ( у меня от 700 до 2200 юзеров ходят в инет). Предупреждаю сразу - все коды, публикуемые в теме - НЕ ГИБКОЕ РЕШЕНИЕ - оно заточено под меня - например определение адресов 172.28... - ограждение попадания в массив реальных IP итд. Это лишь руководство по рукоблудству!
Итак - поднимаем серверную часть ТИ: всё банально - простейший скрипт, который обращается к API ТИ:
где 0 - это лимитные тарифы - соответственно как считать траф - ваша головная боль, ибо у меня в таких нагрузках даже mirror с порта коммутатора клал ТИ сервер в полку, я на время перехода с ТИ на "другой биллинг" просто не считаю им сейчас трафик, а режу на 8 мегабит - это будет далее во втором скрипте.
Теперь FreeBSD.
Ставим "голую 7.3". Почему 7.3? А фиг его знает - восьмёрка как-то не прижилась. Сразу не забываем при установке ставить ветку dev и исходники ядра в /sys. Я решил использовать во FreeBSD не natd а FIREWALL_NAT - ядерный нат, который естественно быстрее и менее ресурсо-ёмкий. Засим открываем ман по сборке собственного ядра - https://www.freebsd.org/doc/ru/books/handbook/kernelconfig-bu ilding.html и просто добавляем в ядро следующее:
тут не всё нужно для работы моей схемы, но ибо избежать дальнейших вариаций на тему "решил юзать думинет, а у вас не работает ..." - добавил). после пересборки ядра и ребута, ставим на фрю php5-cli и обязательно php5-curl - эта библиотека позволит нам обращаться по http в серверу ТИ.
Итак, скрипт запуска всего этого безобразия под FreeBSD ( скрипт шельный - не забудте сделать его +x ):
Код
</br><br />#!/usr/local/bin/php -q</br><br /><?php</br><br /># Все вопросы шлите на dimka.smith(coбака)gmail.com</br><br /># URL скрипта на сервере ТИ</br><br />$ti_url="https://адрес_сервера_ТИ/хитрый_путь/ti.php";</br><br /># Сетевая карта, на которой шейпим скорость</br><br />$real_eth="em0";</br><br />$lim_max="8192"; // максимальная скорость для лимитных планов</br><br /># очищаем все цепочки, шейпер и nat</br><br />exec("ipfw -f flush");</br><br />exec("ipfw -f pipe flush");</br><br />exec("ipfw -f queue flush");</br><br />exec("ipfw -f table all flush");</br><br /># удаляем старые наты - не получилось пофлушить</br><br />exec("ipfw nat 100 delete");</br><br />exec("ipfw nat 101 delete");</br><br />exec("ipfw nat 102 delete");</br><br />exec("ipfw nat 103 delete");</br><br />exec("ipfw nat 104 delete");</br><br />exec("ipfw nat 105 delete");</br><br />exec("ipfw nat 106 delete");</br><br />exec("ipfw nat 107 delete");</br><br />exec("ipfw nat 108 delete");</br><br />exec("ipfw nat 109 delete");</br><br /># one_pass нафиг</br><br />exec("ipfw disable one_pass");</br><br /># включаем нат для пула внешних IP - у меня их столько, сколько тарифов</br><br /># дабы пользователям было комфортно качать с рапид итд. - чем дороже тариф, тем меньше юзеров на реальнике</br><br />exec("ipfw nat 100 config ip 109.197.112.2 log");</br><br />exec("ipfw nat 101 config ip 109.197.112.3 log");</br><br />exec("ipfw nat 102 config ip 109.197.112.4 log");</br><br />exec("ipfw nat 103 config ip 109.197.112.5 log");</br><br />exec("ipfw nat 104 config ip 109.197.112.6 log");</br><br />exec("ipfw nat 105 config ip 109.197.112.7 log");</br><br />exec("ipfw nat 106 config ip 109.197.112.8 log");</br><br />exec("ipfw nat 107 config ip 109.197.112.9 log");</br><br />exec("ipfw nat 108 config ip 109.197.112.10 log");</br><br />exec("ipfw nat 109 config ip 109.197.112.11 log");</br><br />exec("ipfw nat 65000 config ip 109.197.112.12 log");</br><br /># создаём трубы шейпера</br><br />exec("ipfw pipe 100 config bw 128Kbit/s mask dst-ip 0xffffffff");</br><br />exec("ipfw pipe 101 config bw 256Kbit/s mask dst-ip 0xffffffff");</br><br />exec("ipfw pipe 102 config bw 512Kbit/s mask dst-ip 0xffffffff");</br><br />exec("ipfw pipe 103 config bw 1024Kbit/s mask dst-ip 0xffffffff");</br><br />exec("ipfw pipe 104 config bw 2048Kbit/s mask dst-ip 0xffffffff");</br><br />exec("ipfw pipe 105 config bw 3072Kbit/s mask dst-ip 0xffffffff");</br><br />exec("ipfw pipe 106 config bw 4096Kbit/s mask dst-ip 0xffffffff");</br><br />exec("ipfw pipe 107 config bw 8192Kbit/s mask dst-ip 0xffffffff");</br><br />exec("ipfw pipe 108 config bw 12288Kbit/s mask dst-ip 0xffffffff");</br><br />exec("ipfw pipe 109 config bw 16384Kbit/s mask dst-ip 0xffffffff");</br><br /># создаём таблицы для тарифов</br><br />exec("ipfw add pipe 100 ip from table\(100\) to any out");</br><br />exec("ipfw add pipe 100 ip from any to table\(100\) in");</br><br />exec("ipfw add pipe 101 ip from table\(101\) to any out");</br><br />exec("ipfw add pipe 101 ip from any to table\(101\) in");</br><br />exec("ipfw add pipe 102 ip from table\(102\) to any out");</br><br />exec("ipfw add pipe 102 ip from any to table\(102\) in");</br><br />exec("ipfw add pipe 103 ip from table\(103\) to any out");</br><br />exec("ipfw add pipe 103 ip from any to table\(103\) in");</br><br />exec("ipfw add pipe 104 ip from table\(104\) to any out");</br><br />exec("ipfw add pipe 104 ip from any to table\(104\) in");</br><br />exec("ipfw add pipe 105 ip from table\(105\) to any out");</br><br />exec("ipfw add pipe 105 ip from any to table\(105\) in");</br><br />exec("ipfw add pipe 106 ip from table\(106\) to any out");</br><br />exec("ipfw add pipe 106 ip from any to table\(106\) in");</br><br />exec("ipfw add pipe 107 ip from table\(107\) to any out");</br><br />exec("ipfw add pipe 107 ip from any to table\(107\) in");</br><br />exec("ipfw add pipe 108 ip from table\(108\) to any out");</br><br />exec("ipfw add pipe 108 ip from any to table\(108\) in");</br><br />exec("ipfw add pipe 109 ip from table\(109\) to any out");</br><br />exec("ipfw add pipe 109 ip from any to table\(109\) in");</br><br /># нат загоняем в таблицы</br><br />exec("ipfw add nat 100 ip from table\(100\) to any");</br><br />exec("ipfw add nat 100 ip from any to 109.197.112.2");</br><br />exec("ipfw add nat 101 ip from table\(101\) to any");</br><br />exec("ipfw add nat 101 ip from any to 109.197.112.3");</br><br />exec("ipfw add nat 102 ip from table\(102\) to any");</br><br />exec("ipfw add nat 102 ip from any to 109.197.112.4");</br><br />exec("ipfw add nat 103 ip from table\(103\) to any");</br><br />exec("ipfw add nat 103 ip from any to 109.197.112.5");</br><br />exec("ipfw add nat 104 ip from table\(104\) to any");</br><br />exec("ipfw add nat 104 ip from any to 109.197.112.6");</br><br />exec("ipfw add nat 105 ip from table\(105\) to any");</br><br />exec("ipfw add nat 105 ip from any to 109.197.112.7");</br><br />exec("ipfw add nat 106 ip from table\(106\) to any");</br><br />exec("ipfw add nat 106 ip from any to 109.197.112.8");</br><br />exec("ipfw add nat 107 ip from table\(107\) to any");</br><br />exec("ipfw add nat 107 ip from any to 109.197.112.9");</br><br />exec("ipfw add nat 108 ip from table\(108\) to any");</br><br />exec("ipfw add nat 108 ip from any to 109.197.112.10");</br><br />exec("ipfw add nat 109 ip from table\(109\) to any");</br><br />exec("ipfw add nat 109 ip from any to 109.197.112.11");</br><br /># Юрики ( временно!) - у меня они бегают отдельной под-сеткой и пока не перешли на новый биллинг - раздаём халяву</br><br />exec("ipfw add nat 65000 ip from 172.28.9.0/24 to any");</br><br />exec("ipfw add nat 65000 ip from any to 109.197.112.12");</br><br /># ждём 1 сек</br><br /># sleep(1);</br><br /># функция обращения с серверу ТИ по http</br><br />function get($url) {</br><br /> $process = curl_init($url);</br><br /> curl_setopt($process, CURLOPT_TIMEOUT, 60);</br><br /> curl_setopt($process, CURLOPT_RETURNTRANSFER, 1);</br><br /> curl_setopt($process, CURLOPT_FOLLOWLOCATION, 1);</br><br /> $return = curl_exec($process);</br><br /> curl_close($process);</br><br /> return $return;</br><br />}</br><br /># бесконечный цикл - если остановить скрипт - все цепочки на момент остановки будут живы</br><br /># при повторном запуске скрипт очистит их и возьмёт из ТИ текущих активных юзеров</br><br />while(true) {</br><br /> # + получаем ВЕСЬ список с ТИ, с маркировкой Auth и Blocked</br><br /> $ti = get($ti_url);</br><br /> $ti = split("\n", $ti);</br><br /> # получаем список текущих цепочек ipfw, преобразуем в массив IP</br><br /> $fw_chk = shell_exec("ipfw table all list | awk '{print $1}'");</br><br /> $fw = array();</br><br /> $fw = split("\n", $fw_chk);</br><br /> # получаем список цепочек шейпера, преобразуем в массив</br><br /> # цикл обработки массива юзеров</br><br /> foreach($ti as $val) {</br><br /> if(ere gi("172\.28\.",$val)) {</br><br /> # загоняем список юзеров с ТИ в массив, выделяем переменные</br><br /> $user = split("\t", $val);</br><br /> $user _id = $user[0];</br><br /> $user _active = $user[1];</br><br /> $user _blocked = $user[2];</br><br /> $user _ip = $user[3];</br><br /> $user _speed = $user[4];</br><br /> if($user_speed==0) { $speed = $lim_max."Kbit/s"; } else { $speed = $user_speed."Kbit/s"; }</br><br /> # если юзер авторизирован по агенту и не заблокирован - тут мои тарифы!!!</br><br /> if($user_speed=='1 28') $table_id='100';</br><br /> if($user_speed=='2 56') $table_id='101';</br><br /> if($user_speed=='5 12') $table_id='102';</br><br /> if($user_speed=='1 024') $table_id='103';</br><br /> if($user_speed=='2 048') $table_id='104';</br><br /> if($user_speed=='3 072') $table_id='105';</br><br /> if($user_speed=='4 096') $table_id='106';</br><br /> if($user_speed=='8 192') $table_id='107';</br><br /> if($user_speed=='1 0800') $table_id='107';</br><br /> if($user_speed=='1 2228') $table_id='108';</br><br /> if($user_speed=='1 6348') $table_id='109';</br><br /> if($user_active==1 && $user_blocked==0) {</br><br />   ;   ; # если юзер активен</br><br /> if(in_array("$user_ip/32", $fw)) {</br><br /> # цепочка есть, юзер работает, можно проверить скорость при динашейпинге и поменять pipe</br><br /> # print "HAVE - ".$user_ip."\n";</br><br /> } else {</br><br /> # новый юзер - создаём цепочку, врубаем шейпер по скорости</br><br /> # пихаем в таблицу в соответствии с тарифом</br><br /> if($table_id!='') {</br><br /> exec("ipfw table $table_id add $user_ip/32");</br><br /> }</br><br /> print "NEW - ".$user_ip." - SPEED: $speed - IP: $real_ip - Table: $table_id\n";</br><br /> }</br><br /> } elseif($user_active==0) {</br><br />   ;   ; # если юзер неактивен, но цепочка есть, удаляем</br><br /> if(in_array("$user_ip/32", $fw)) {</br><br /> print "DELETE - ".$user_ip." - $speed - ipfw table $table_id delete $user_ip/32\n";</br><br /> # удаляем нат цепочки</br><br /> exec("ipfw table $table_id delete $user_ip/32");</br><br /> }</br><br /> }</br><br /> }</br><br /> }</br><br /> print "-------------- Now: ".date("H:i:s")." ---------------------------\n";</br><br />}</br><br />?></br><br />
Повторюсь - это не универсальный код - у вас он не будет работать, если вы бездумно скопируете.
Идеология следующая - таблица 1XX - это тариф, в ней каждый пользователь ограничен одинаковой скоростью, которая не делится на всех, а присуща только одному пользователю, добавленному в таблицу.
Ну и немного про тюнинг FreeBSD - постарайтесь не использовать 2х портовые карты (igb) - у них есть огромные проблемы - лучше уж материнка с 2мя em интерфейсами. Почитайте сразу про sysctl.conf - важная вещь при использовании фри, как ната и шейпера. я не тюнил сильно - вот мой sysctl.conf:
Код
</br><br />net.isr.direct=1</br><br />net.inet.ip.forwarding=1</br><br />net.inet.ip.fw.one_pass=0</br><br />net.inet.icmp.icmplim=1024 # чтобы пинги не дохли от юзеров</br><br />
и в /boot/loader.conf при использовании em интерфейсов не забудте добавить:
если делать такую связку, значит мб невазможно считат? а парвилно понял??
Возможно. В данной схеме можно на коммутаторе сделать mirror на порт, который идёт на FreeBSD и отдать поток во второй интерфейс ТИ сервера - в документации есть "Режим прослушки". Всё будет считаться. Но, повторюсь, у меня на 3500 абонентов ТИ сервер на 2х ксеонах умирал на потоке ( у меня в совокупности 900Мбит на 3 канала ).
А если коммутатор умный, то можно делать mirror по ACL и трафика будет сыпатсья не так много
зачем?) просто пофильтровать паразитный uTP трафик и поток упадёт минимум на 25-30%. Последнее время это проблема у всех провайдеров. Я фильтрую эту каку с помощью Layer7 на бордере, т.е. в сеть оно не попадает. PPSы упали на 25%.
В общем 2 суток - полёт нормальный. Можно юзать в продакшене) Для теста я выпустил сеть через один нат, а не через два в балансировке как раньше для стресс-нагрузки, вот некоторые скрины:
1. Нагрузка машины:
2. Экран отработки скрипта
3. Нагрузка сетевого интерфейса
Будет время, перепишу код под "универсальное" применение с выделенным конфигом.