Балансировка нагрузки 2-х каналов на FreeBSD 10.2 средствами PF
Здравствуйте, уважаемые обитатели данного форума. Обращаюсь к Вам с просьбой о помощи. Начну с предисловия. Имеется небольшая компания, которая занимается трансляцией кабельного тв и раздачей интернета.
Значит больший приоритет отдавался кабельному тв. Потом директор решил так-же раздавать интернет. Приобрели L3 свич Foxgate C704, кучу управляемых свичей 2-го уровня и взяли в аренду билинговую систему ACP Ideco Carbon Soft.
На данный момент возникла острая необходимость перехода на другой билинг. Выбор пал на Nodeny+. Значит Carbon у нас стоял на одной машине, а сейчас хотелось бы разделить билинг на 2 сервера:
маршрутизатор с балансировкой отдельно, билинг с базой отдельно. Так вот, к чему я. Специалиста у нас нет. Лично я принял хазяйство, не зная практически ничего, но за год работы кое что усвоить удалось. Билинг Carbon
очень простой в ослуживании, и там "ковыряться" во внутренностях не приходилось, сдесь-же, как я понял основной упор идет на знания администратора. На данный момент мы имеем 1 гигабит трафика, т.е. 2 провайдера,
один 400 Мб второй 600 Мб, оба провайдера выдали статические ip адреса. Абонентов, касательно интернета около 2-х тысяч. Начал я стого, что бы попробовать собрать сам балансировщик. Установил FreBSD на тестовую машину,
пересобрал ядро с опцией PF, установил 2 сетевые карты, помимо интегрированой, получается 2 интерфейса смотрят на внешних провайдеров, 1 в локальную сеть. На просторах интернета нашел, можно сказать готовый pf.config.
lan_net = "192.168.5.0/24"
int_if = "rl0"
ext_if1 = "re0"
ext_if2 = "re1"
ext_gw1 = "193.106.x.x"
ext_gw2 = "195.58.x.x"
# правила nat для исходящих соединений на каждом внешнем интерфейсе
nat on $ext_if1 from $lan_net to any -> ($ext_if1)
nat on $ext_if2 from $lan_net to any -> ($ext_if2)
# default deny
block in from any to any
block out from any to any
# пропускаем все исходящие пакеты на внутреннем итерфейсе
pass out on $int_if from any to $lan_net
# пропускаем (quick) пакеты предназначенные самому шлюзу
pass in quick on $int_if from $lan_net to $int_if
# балансировка исходящего tcp трафика идущего из внутренней сети
pass in on $int_if route-to { ($ext_if1 $ext_gw1), ($ext_if2 $ext_gw2) } round-robin sticky-address proto tcp from $lan_net to any flags S/SA modulate state
# балансировка исходящего icmp и udp трафика идущего из внутренней сети
pass in on $int_if route-to { ($ext_if1 $ext_gw1), ($ext_if2 $ext_gw2) } round-robin proto { udp, icmp } from $lan_net to any keep state
# основные "выпускаюшие" правила на внешнем интерфейсе
pass out on $ext_if1 proto tcp from any to any flags S/SA modulate state
pass out on $ext_if1 proto { udp, icmp } from any to any keep state
pass out on $ext_if2 proto tcp from any to any flags S/SA modulate state
pass out on $ext_if2 proto { udp, icmp } from any to any keep state
# маршрутизация пакетов идущих с любого IP на $ext_if1 через $ext_gw1 и
# пакетов идущих на $ext_if2 через $ext_gw2
pass out on $ext_if1 route-to ($ext_if2 $ext_gw2) from $ext_if2 to any
pass out on $ext_if2 route-to ($ext_if1 $ext_gw1) from $ext_if1 to any
А так-же готовый скрипт для переключения каналов в случае падения одного из них. За скрипт отдельная благодарность RicoX.
#!/bin/sh
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin
#Ip адреса на интерфейсах разных каналов.
ext_if1="193.106.x.x"
ext_if2="195.58.x.x"
#Какой внешний адрес проверяем для определения жив ли канал.
testaddress="8.8.8.8"
#Шлюзы по умолчанию для каждого из каналов
ext_gw1="193.106.236.89"
ext_gw2="195.58.245.17"
#Куда складывать лог.
logfile=/var/log/canalchange.log
fl=`date "+%H:%M:%S %d-%m-%Y"`
tester=0;
itest1=`/sbin/ping -S $ext_if1 -c 3 $testaddress | grep "64 bytes" | wc -l`;
itest2=`/sbin/ping -S $ext_if2 -c 3 $testaddress | grep "64 bytes" | wc -l`;
if [ ! -f "/tmp/countGW.tmp" ]
then
echo 3 > /tmp/countGW.tmp
fi
oldtest=`cat /tmp/countGW.tmp`
if (test $itest1 -gt "0")
then
let tester=tester+1
fi
if (test $itest2 -gt "0")
then
let tester=tester+2
fi
#Если последняя проверка такая же как предыдущая, то ничего не делаем
if [ $oldtest = $tester ]; then
exit;
else
if [ $tester = 3 ]; then
cp /etc/pf.conf3 /etc/pf.conf
/sbin/route change default $ext_gw1
echo ${fl}" OK" >> $logfile
echo 3 > /tmp/countGW.tmp
fi
if [ $tester = 2 ]; then
cp /etc/pf.conf2 /etc/pf.conf
/sbin/route change default $ext_gw2
echo ${fl}" CHANAL 1 DOWN" >> $logfile
echo 2 > /tmp/countGW.tmp
fi
if [ $tester = 1 ]; then
cp /etc/pf.conf1 /etc/pf.conf
/sbin/route change default $ext_gw1
echo ${fl}" CHANAL 2 DOWN" >> $logfile
echo 1 > /tmp/countGW.tmp
fi
if [ $tester = 0 ]; then
echo ${fl}" CHANAL 1 DOWN and CHANAL 2 DOWN" >> $logfile
# Если лежат оба то при каждом запуске скрипта меняем дефолтный, ведь неизвестно какой подымется первым
if [ $(/usr/bin/netstat -rn | awk '/default/ {print $2}') == $ext_gw1 ]; then
/sbin/route change default $ext_gw2
else
/sbin/route change default $ext_gw1
fi
fi
/etc/rc.d/pf restart
fi
И на этом, как говорится, я застрял. Хотелось бы узнать у знающих людей. Будет ли эта коммутация работать, что еще нужно настроить или прописать? Правильно ли это вообще?