Pull to refresh

Тайна незанятого xl0 или получаем контроль над своей сетью

Reading time 9 min
Views 5.7K
Как вы все помните, в конце предыдущего поста я обещал более подробно рассмотреть вкратце и максимально доступно следующие вопросы:

1. Настройка DHCP
2. Поднимаем свой DNS по минимуму
3. Съем статистики по интерфейсам при помощи snmp и отрисовывание красот в cacti
4. Лимитирование по трафику пользователей внутри сети
5. Ведение детальной статистики по тому, как куда и кем расходуется трафик
6. Настройка бекапа каналов в случае наличия еще одного провайдера (а о xl0 все и забыли)
7. Разруливание трафика между несколькими каналами средствами ipfw
image

В свете предыдущих обсуждений хотелось бы напомнить:
— статьи сии из серии “FreeBSD for dummies”
— нет, я не буду писать про pf и altq
— успокойтесь с хардовыми решениями и проксями на винде – не о них идет речь
— нет, про squid & sarg ни слова – не наш метод, хотя ж никто не запрещал?
— 10.10.10.0/24 и 172.16.0.0/24 потому что не 123.123.123.122 и не 222.222.222.222 мне глаз не режет
— так делать нельзя и не рекомендуется – это не руководство, это просто демонстрация концепции в общем. В идеале не должно быть всяких allow from any to any, доступа к mysql под рутом итд. Ну вы поняли :)

Итак поехали по порядку

Сверяемся для начала с нашей красивой сферической сетью в вакууме и решаем что было-бы хорошо раздавать всем сетевые настроечки (айпишку, маску, шлюз, днс-ы) автоматом

image

Установка isc-dhcpd не должна вызывать никаких сложностей:
#cd /usr/ports/net/isc-dhcp40-server/
#make install

После чего в /etc/rc.conf добавляем следующее:
dhcpd_enable="YES"
dhcpd_flags="-q"
dhcpd_conf="/usr/local/etc/dhcpd.conf"
dhcpd_ifaces="fxp0"


Далее правим наш /usr/local/etc/dhcpd.conf следующим удобным образом:
option domain-name-servers 192.168.0.1;
default-lease-time 3600;
max-lease-time 43200;
authoritative;
ddns-update-style none;
log-facility local7;
one-lease-per-client true;
deny duplicates;

subnet 192.168.0.0 netmask 255.255.255.0 {
default-lease-time 3600;
option domain-name "office";
option subnet-mask 255.255.255.0;
option routers 192.168.0.1;

include "/usr/local/etc/dhcp_subnets.conf";

}


Зачем так извратно? А чтобы проще было потом добавлять хосты в сабнет автоматом избегая возни с закзывающей «}»

Поехали теперь смотреть что-же будет наш сабнет представлять из себя:

/usr/local/etc/dhcp_subnets.conf

и для теста вбиваем следующее:
host hostmariya {
hardware ethernet 00:a1:b0:01:bc:77;
fixed-address 192.168.0.2;
}


Все вроде, пробуем это все дело стартовать
# /usr/local/etc/rc.d/isc-dhcpd start


Оппаньки – запустилось. Ок.
Как вы могли заметить по опциям option domain-name-servers 192.168.0.1 сейчас мы будем по ускоренной программе подымать свой DNS сервер. Будет он у нас только форвардящим, ибо мы полностью пока что полагаемся на безупречность нашего провайдера. Да и свои зоны пока что вести не будем. Будем просто раздавать Наталье Васильевне и Григорию Сергеичу интернеты. Даже на двух провайдеров мы будем полагаться.
Почему двух?
ВНЕЗАПНО появляется второй провайдер, более быстрый и дешевый. А от старого мы отказываться так не собираемся – зачем добру пропадать. Будем использовать его как резервный линк.

Смотрим /etc/namedb/named.conf

Раскаментиваем
forward only;


Начинаем слушать наш внутренний fxp0
listen-on { 127.0.0.1; 192.168.0.1; };


Раскоментиваем форвардеров которые у нас будут иметь вид допустим 10.10.10.2 и 172.16.0.2 (да да – второй провайдер у нас уже живет на сетевухе xl0 на которой висит айпишка допустим 172.16.0.1)
forwarders {
10.10.10.2;
172.16.0.1;
};


Сохраняемся и пробуем запускать:
#/usr/sbin/named -t /var/named -u bind


Тестим запустилось ли хотябы:
#ps aux | grep named
bind 10095 0.0 0.7 4280 3484 ?? Ss 7:58PM 0:00.11 /usr/sbin/named -t /var/named -u bind


Вроде запустилось

а работает ли?

# nslookup
> server 127.0.0.1
Default server: 127.0.0.1
Address: 127.0.0.1#53
> google.com
Server: 127.0.0.1
Address: 127.0.0.1#53

Non-authoritative answer:
Name: google.com
Address: 74.125.127.100
Name: google.com
Address: 74.125.45.100
Name: google.com
Address: 74.125.67.100


Работает! Отличненько.

Пишем в /etc/rc.conf строчечку
named_enable="YES"


исправляемся в /etc/resolv.conf
на
nameserver 127.0.0.1


Как уже говорилось у нас появился еще один провайдер которого мы хотели бы использовать как основного?
Открываем наш страдальческий /etc/firewall.conf и в том месте где у нас все натиться делам допустим так:
#internet natting and preserving
${FwCMD} add 1799 divert 8671 ip from table\(2\) to not table\(9\)
${FwCMD} add 1800 divert 8672 ip from table\(2\) to not table\(9\) out via xl0
${FwCMD} add 1847 fwd 172.16.0.2 ip from me to 213.180.204.8
${FwCMD} add 1849 fwd 10.10.10.2 ip from 10.10.10.1 to not table\(9\)
${FwCMD} add 1850 fwd 172.16.0.2 ip from 172.16.0.1 to not table\(9\)
${FwCMD} add 2099 divert 8671 ip from any to 10.10.10.1 in via rl0
${FwCMD} add 2100 divert 8672 ip from any to 172.16.0.1 in via xl0


Ну и подымаем второй natd для нового провайдера:
/sbin/natd -u -p 8672 -a 172.16.0.1


Давайте в кратце разберем как это работает чтобы в будущем мы не путались:
• Правило 1799 это прямой заворот трафика от нашей сети из таблички 2 в natd
• Правило 1800 аналогично предыдущему но уже для резервного канала и естественно туда ничего не попадет пока существует 1799
• Правила 1847 предназначено только для прокидывания нужного нам хоста по которому мы будем контролировать живость канала сквозь нового провайдера (172.16.0.2)
• Правила 1849 и 1850 жестко рассказывают куда девать трафик появившийся на соответствующих сетевухах
• Ну и 2099 и 2100 соответственно обратные диверты в natd

Логика работы проста – если живы правила 1799, 1849, 2099 интернет ходит новым провайдером который 172.16.0.2 если же они отсутствуют трафик «неожиданно» устремляется в 10.10.10.2 =)
Переключалку такую мы с вами напишем чуть позже.

Смотрим что шло следующим пунктом нашей программы на сегодня. Ой… snmp и установка apache+mysql+php+cacti… А можно на следующий раз отложим? Ну-у-у пожалуйста-а-а! Ну хотябы установку и настройку cacti. Давайте сейчас будем ставить биллинг, а мониторить и допиливать до красивости все это мы будем в финале?
Договорились? ;) Тогда поехали.

Для таких микрозадач использовать мы будем опенсорсный биллинг stargazer который является самым простым и предсказуемым решением из тех что я до сих пор видел.
Для его установки нам потребуется:
1. mysql в котором мы будем хранить данные биллинга
2. так как стройные костыли и подпорки мы будем писать на php поставим уж и php + apache
3. собственно последний стабильный stargazer

Для начала рекомендую ознайомиться хотя-бы с вот такой минимальной докой либо с другими посвященными установке связки apache+php+mysql. Опишу вкратце.

Поехали ставить mysql.
# cd /usr/ports/databases/mysql50-server/
# make install
# /usr/local/bin/mysqladmin -u root -p password ourpassword


Начинаем ставить php
# cd /usr/ports/lang/php5/
# make install


И собираем расширения поддержки mysql, gd, iconv ну и еще что нам может понадобиться в будущем

# cd /usr/ports/lang/php5-extensions
# make install


Пробуем все ли установилось так как нам хотелось бы:
# apachectl start
# echo "<?php phpinfo(); ?>" > /usr/local/www/data/test.php


Ну и собственно проверяем все ли получилось так как хотелось зайдя браузером по адресочку 192.168.0.1/test.php

Отлично. Теперь начинаем ставить то для чего все это затеивалось:
# fetch www.stg.dp.ua/download/server/2.406/stg-2.406.src.tgz
# tar zxvf stg-2.406.src.tgz
# cd stg-2.406
# cd projects/stargazer/
# ./build
#gmake install
#cd ../convertor/
#./build


Теперь будем конвертировать дефолтную текстовую базу в mysql. Правим convertor.conf:

Комментируем store_postgresql:
#<DestStoreModule store_postgresql>
# server = localhost
# database = stargazer
# user = stg
# password = 123456
#



Раскоменчиваем и приводим к нужному виду store_mysql:
<DestStoreModule store_mysql>
# Имя пользователя БД
dbuser = root

# Пароль пользователя БД
rootdbpass = ourpassword

# Имя БД на сервере
dbname = stg

# Адрес сервера БД
dbhost = localhost



Пробуем конвертиться:
# ./convertor


Пустая база конвертиться моментально. Начинаем конфигурить stargazer.
Прописываем классы трафика
# vim /etc/stargazer/rules
ALL 192.168.0.0/24 DIR1
ALL 0.0.0.0/0 DIR0


Подганяем под реалии жизни конфиг:
#vim /etc/stargazer/stargazer.conf


По минимуму правим названия направлений:
DirName0 = internet
DirName1 = local
DirName2 =
DirName3 =
DirName4 =
DirName5 =
DirName6 =
DirName7 =
DirName8 =
DirName9 =



Строим модуль захвата трафика cap_bpf так чтобы он считал его на интерфейсе смотрящем во внутреннюю сеть
<Module cap_bpf>
iface = fxp0



Коментируем все что относиться к <StoreModule store_files> и по аналогии с конвертером подключаем модуль <StoreModule store_mysql>:
<StoreModule store_mysql>
dbuser = root
rootdbpass = ourpassword
dbname = stg
dbhost = localhost



Пробуем запускать сам stargazer:
#stargazer


И проверяем как запустились
#tail /var/log/stargazer.log


Если мы видим что-то похожее на Stg started successfully. Значит есть шансы на жизнь ;)
Загружаем windows конфигуратор по адресу stg.dp.ua/download/sgconfig/1.91.9/sgconfig.1.91.9.win.exe и после установки в настройках ставим коннект на 192.168.0.1:5555
Логин/пароль по умолчанию admin/123456. После логина мы должны увидеть что-то типа

image

С умолчальным пользователем test которого тут, же смело удаляем.

image

Меняем пароль админа, либо добавляем новых. Добавляем исходя из старой схемы для теста нашу Марию Ивановну из бухгалтерии с айпишкой 192.168.0.2

image

Будет она у нас «всегда Online» потому, что незачем в условиях офиса использовать auth_ia требующий указывать логин/пароль для доступа к сети.
В поля UserData0 и UserData1 вбиваем скорость и MAC и вот зачем:
Логика работы stargazer очень проста и гибка. В моменты когда пользователь появляеться онлайн, отсоединяется, удаляется и добавляется исполняються следующие скрипты:
OnConnect
OnDisconnect
OnChange
OnUserAdd
OnUserDel


О назначении которых, несложно догадаться по их названиям. Все они находяться в /etc/stargazer/

Начинаем подганять их под наши реалии
Для начала создаем еще 2 скриптика на PHP (не даром же ставили его ;) при помощи которых мы будем получать скорость и МАС пользователя из базы.
Скрипт /etc/stargazer/GetSpeed с содержанием
#!/usr/local/bin/php
<?php
$login=$argv[1];
$link = mysql_connect("localhost", "root", "ourpassword");
mysql_select_db("stg");
$query = 'SELECT `Userdata0` FROM users where `login`= "'.$login.'"';
$result = mysql_query($query);
while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
foreach ($line as $col_value) {
print ($col_value);
}
}
?>


И /etc/stargazer/GetMac вида
#!/usr/local/bin/php
<?php
$login=$argv[1];
$link = mysql_connect("localhost", "root", "ourpassword");
mysql_select_db("stg");
$query = 'SELECT `Userdata1` FROM users where `login`= "'.$login.'"';
$result = mysql_query($query);
while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
foreach ($line as $col_value) {
print ($col_value);
}
}
?>


Назначаем им права для выполнения
#chmod a+x /etc/stargazer/GetMac /etc/stargazer/GetSpeed


Тестим их на тему работоспособности для ранее созданного пользователя:
# /etc/stargazer/GetSpeed mariya
512
/etc/stargazer/GetMac mariya
00:a1:b0:01:bc:77


Отлично!

Начинаем думать что же будет случаться когда пользователь появляется онлайн и выпадает в оффлайн.
Итак Что же будет случаться при появлении пользователя онлайн:
# OnConnect
IFACE="fxp0"
LOGIN=$1
IP=$2
CASH=$3
ID=$4
SPEED=`/etc/stargazer/GetSpeed $LOGIN`
MAC=`/etc/stargazer/GetMac $LOGIN`
SCOUNT="Kbit/s"
fwcmd="/sbin/ipfw -q"
arpcmd="/usr/sbin/arp"
cur_date=`date \+\%Y.\%m.\%d`
cur_time=`date \+\%H:\%M:\%S`

# DELETE RULEZ
${fwcmd} delete `expr $ID '*' 10 + 10001`
${fwcmd} delete `expr $ID '*' 10 + 10002`
${fwcmd} delete `expr $ID '*' 10 + 10003`
${fwcmd} delete `expr $ID '*' 10 + 10004`
${fwcmd} delete `expr $ID '*' 10 + 10005`

# ADD RULEZ

# fix user mac to ip
${arpcmd} -S $IP $MAC

#SPEED CONTROL
${fwcmd} pipe `expr $ID + 101` config bw $SPEED$SCOUNT queue `expr $SPEED '/' 8`Kbytes
${fwcmd} pipe `expr $ID + 901` config bw $SPEED$SCOUNT queue `expr $SPEED '/' 8`Kbytes

# ALLOWS CONTROL
${fwcmd} add `expr $ID '*' 10 + 10001` allow icmp from $IP to me
${fwcmd} add `expr $ID '*' 10 + 10001` allow icmp from me to $IP
${fwcmd} add `expr $ID '*' 10 + 10002` pipe `expr $ID + 101` ip from $IP to any via $IFACE in
${fwcmd} add `expr $ID '*' 10 + 10003` pipe `expr $ID + 901` ip from any to $IP via $IFACE out
${fwcmd} add `expr $ID '*' 10 + 10004` allow ip from $IP to any
${fwcmd} add `expr $ID '*' 10 + 10005` allow ip from any to $IP

# ADD TO LOG
echo "<=;$cur_date;$cur_time;$ID;$LOGIN;$IP;$CASH;$SPEED;`expr $ID + 101`;$MAC" >> /var/stargazer/allconnect.log


и что будет случаться если он выпадает из онлайна:
# OnDisconnect
LOGIN=$1
IP=$2
CASH=$3
ID=$4

fwcmd="/sbin/ipfw -q"

# TIME FORMAT
cur_date=`date \+\%Y.\%m.\%d`
cur_time=`date \+\%H:\%M:\%S`

# DELETE RULEZ FRO IPFW
${fwcmd} delete `expr $ID '*' 10 + 10001`
${fwcmd} delete `expr $ID '*' 10 + 10002`
${fwcmd} delete `expr $ID '*' 10 + 10003`
${fwcmd} delete `expr $ID '*' 10 + 10004`
${fwcmd} delete `expr $ID '*' 10 + 10005`
${fwcmd} pipe `expr $ID + 101` delete
${fwcmd} pipe `expr $ID + 901` delete
echo "=>;$cur_date;$cur_time;$ID;$LOGIN;$IP;$CASH" >> /var/stargazer/allconnect.log


Думаю здесь все понятно – мы просто подымаем/удаляем соответствующие внтуренним ID пользователя правила шейпинга и делающие ему allow дальше чем наш локальный интерфейс fxp0.
Помниться у нас изначально они ничем не ограничивались ибо в самом конце стояло allow ip from any to any? Нет проблем.
Добавляем в /etc/firewall.conf что-то типа
${FwCMD} add 101 allow all from 192.168.0.1 to any
${FwCMD} add 101 allow all from any to 192.168.0.1
${FwCMD} add 65533 deny all from table\(2\) to any
${FwCMD} add 65534 deny all from any to table\(2\)


Теперь пробуем по включать/повыключать «всегда Online» для нашего подопытного пользователя и смотрим /var/stargazer/allconnect.log
Хозяйке на заметку: всегда полезно контролировать на глаз что и как ходит и по каким правилам при помощи
#ipfw show


Все – в минимальном варианте биллинг доставили. Вы спросите а зачем нам считать деньги? Да очень просто – мы же хотели нашей Марьивановне выдавать не более 500 мег интернетов в месяц либо просто выдавать ей в ручную по надобности определенную скорость с определенным количеством трафика? Нет проблем. Просто приравниваем 1мег к одной денюжке для простоты расчета. Допустим так

image

В общем простор для творчества есть.

По-моему статья получилась какой-то крайне затянутой и мрачной. Явно пора заокругляться.

В следующий раз если карма позволит обещаюсь таки рассказать как сделать переключалку на резервный канал, рисовать вот такие красивые графички при помощи cacti

image

и как удобно оформить отображение статистики по трафику собранной установленным нами сегодня stargazer.

ЗЫ и да – мой русский неученый в школе с предыдущего раза как не прискорбно не улучшился :(
Tags:
Hubs:
+47
Comments 25
Comments Comments 25

Articles