Данное решение отличается изящностью, так как реализует все средствами iptables.
Синтаксис: на машине, которая должна балансировать исходящие соединения, выполнить скрипт balancer.sh:sh ./balancer.sh
Выключить балансер:
sh ./balancer.sh off
Замечание: При работе создается временный файл ~/balancer-rules.sav, используемый для уборки за собой при выключении балансера.
balancer.sh
#!/bin/bash
# Written by Stanislav S. Osipov, demofly@mail.ru
# Created 2010.08.08
# Script makes SNAT round robin balancing for connections between all real IPA of this host
#
# OpenVZ guest warning: you must allow the next options:
# IPTABLES="ip_tables iptable_filter iptable_mangle iptable_nat ip_conntrack ipt_conntrack ipt_state"myips=`/sbin/ifconfig | /bin/grep "inet a" | /usr/bin/awk "{print \\$2}" | /usr/bin/cut -d: -f2
| /bin/grep -v "^127\.\|^10\.\|^192\.168\.\|^172\.\([12][0-9]\|3[01]\)\."`myipscount=`/sbin/ifconfig | /bin/grep "inet a" | /usr/bin/awk "{print \\$2}" | /usr/bin/cut -d: -f2
| /bin/grep -v "^127\.\|^10\.\|^192\.168\.\|^172\.\([12][0-9]\|3[01]\)\." | /usr/bin/wc -l`if [ $myipscount -lt 2 ] && [ "$1" != "off" ]
then
/bin/echo "you have not enough IPAs for balancing"
/bin/echo "I have $myipscount IPAs:"
/bin/echo $myips
exit 0
fi#for connections, initiated from this host
chain="OUTPUT"
#for connections, initiated by other hosts, which go through this host
#chain="FORWARD"/bin/echo "Cleaning old balancer iptables rules..."
if [ -e ~/balancer-rules.sav ]
then
/bin/cat ~/balancer-rules.sav | /bin/bash
/bin/echo > ~/balancer-rules.sav
else
/bin/echo "No previously dumped rules was found."
fi
/bin/echo "Cleaning was done."
if [ "$1" == "off" ]
then
if [ -e ~/balancer-rules.sav ]
then
rm ~/balancer-rules.sav
fi
exit 0
fi
/bin/echo "I have $myipscount IPAs:
$myips
Generating and writing mangle table mark logic rules..."
i=1
while [ $i -le $myipscount ]
do
RULE1="/sbin/iptables -t mangle -A $chain -j CONNMARK --set-mark $i"
RULE2="/sbin/iptables -t mangle -A $chain -m statistic --mode nth --every $((myipscount-i+1)) -j RETURN"
/bin/echo $RULE1
$RULE1
/bin/echo $RULE2
$RULE2
/bin/echo $RULE1 | /bin/sed -e "s# -A # -D #" >> ~/balancer-rules.sav
/bin/echo $RULE2 | /bin/sed -e "s# -A # -D #" >> ~/balancer-rules.sav
((i++))
done
/bin/echo "...mangle table mark rules was done."/bin/echo "Writing SNAT mark based rules:"
i=1
for ip in $myips
do
RULE="/sbin/iptables -t nat -A POSTROUTING -m connmark --mark $i -j SNAT --to $ip"
/bin/echo $RULE
$RULE
/bin/echo $RULE | /bin/sed -e "s# -A # -D #" >> ~/balancer-rules.sav
((i++))
done
/bin/echo "...nat table SNAT rules was done.
Round robin balancer is turned on.
Thank you for using this script written by Stanislav S. Osipov!"
++ Как проверитьСоздать файл в DocumentRoot на какой-нить машине с апачом такого вида: `ip.php`:
<?
echo $_SERVER['REMOTE_ADDR']."\n";
?>И запустить такой тест с машины, которая работает с правилами балансера (для успешного теста на машине должна стоять библиотека libwww-perl):
i=1; count=20; url="http://my.www.ru/ip.php"; while [ $i -lt $count ]; do GET "$url"; ((i++)); done
++ Как выглядит в работе
root@h1:~# i=1; count=10; url="http://my.www.ru/ip.php"; while [ $i -lt $count ]; do GET "$url"; ((i++)); done
95.239.178.214
95.239.178.214
95.239.178.214
95.239.178.214
95.239.178.214
95.239.178.214
95.239.178.214
95.239.178.214
95.239.178.214root@h1:~# ./balancer.sh
Cleaning old balancer iptables rules...
No previously dumped rules was found.
Cleaning was done.
I have 3 IPAs:
95.239.178.214
95.239.178.220
95.239.178.221Generating and writing mangle table mark logic rules...
/sbin/iptables -t mangle -A OUTPUT -j CONNMARK --set-mark 1
/sbin/iptables -t mangle -A OUTPUT -m statistic --mode nth --every 3 -j RETURN
/sbin/iptables -t mangle -A OUTPUT -j CONNMARK --set-mark 2
/sbin/iptables -t mangle -A OUTPUT -m statistic --mode nth --every 2 -j RETURN
/sbin/iptables -t mangle -A OUTPUT -j CONNMARK --set-mark 3
/sbin/iptables -t mangle -A OUTPUT -m statistic --mode nth --every 1 -j RETURN
...mangle table mark rules was done.
Writing SNAT mark based rules:
/sbin/iptables -t nat -A POSTROUTING -m connmark --mark 1 -j SNAT --to 95.239.178.214
/sbin/iptables -t nat -A POSTROUTING -m connmark --mark 2 -j SNAT --to 95.239.178.220
/sbin/iptables -t nat -A POSTROUTING -m connmark --mark 3 -j SNAT --to 95.239.178.221
...nat table SNAT rules was done.
Round robin balancer is turned on.
Thank you for using this script written by Stanislav S. Osipov!root@h1:~# i=1; count=10; url="http://my.www.ru/ip.php"; while [ $i -lt $count ]; do GET "$url"; ((i++)); done
95.239.178.214
95.239.178.221
95.239.178.220
95.239.178.214
95.239.178.221
95.239.178.220
95.239.178.214
95.239.178.221
95.239.178.220root@h1:~# ./balancer.sh off
Cleaning old balancer iptables rules...
Cleaning was done.root@h1:~# i=1; count=10; url="http://my.www.ru/ip.php"; while [ $i -lt $count ]; do GET "$url"; ((i++)); done
95.239.178.214
95.239.178.214
95.239.178.214
95.239.178.214
95.239.178.214
95.239.178.214
95.239.178.214
95.239.178.214
95.239.178.214
URL: http://wiki.opennet.ru/Iptables/netfiler
Обсуждается: http://www.opennet.me/tips/info/2416.shtml
В результате регулярно начинают отваливаться некоторые сервисы, расчитанные на привязку к IP без keep-alive. Так что пользоваться осмотрительно.
а в чем приемущество данного решения против множественных таблиц маршрутизации и балансировки использую iproute2? Я так понимаю тут речь идет о round-robin NAT?
насколько я помню, через iptables2 если уже был пакет на какой-то ip, то он всегда будет идти через тот же интерфейс... то есть балансировка не совсем равномерная, если скажем на один и тот же сайт постоянно заходят из подсети...если не прав - поправьте...
в любом случае round-robin NAT это разброс соединений на этапе их инициализации, когда оно установлено соединение работает через тот интерфейс через который было установлено. Иначе никак. Сами подумайте как принимающая сторона поймет от кого пришел пакет если вы будет каждый следующий пакет слать через отдельный интерфейс. Пока у вас не будет автономной системы никакой балансировки реальной вы не получите.А вообще iptables использовть для этого это в рядовом случае как вырезать аппендицит бензопилой, iproute2 вам в помощь
Скрип "убивает" уже первыми строчками:
myips=…
myipscount=…
Сама идея погребена в тонне кода.
"Thank you for using this script written by" - да ну нафиг :)
Да, изящностью тут и не пахнет :)
Я бы еще exeption'ы для каждого IP бы сделал
типа smtp пускать только через этот ip, на этот ip обращаться только с этого интерфейса и так далее... а так - возьму на заметку
уже где то писал, но повторюсь : на что только не идут люди что бы не покупить циску :)
на что маркетологи циски только не идут чтобы люди покупали не только роутеры но и их мыльницы.
И на то у вас машина есть? (c)
>уже где то писал, но повторюсь : на что только не идут
>люди что бы не покупить циску :)Что только цисководы не купят, чтоб мозгами не работать.
там, это есть --random опция, что-бы раскидывать по дестинейшиенам через раун робин. И весь скрипт сводится к 1 правилу. Почитай рассылку, так они зыбыли это задокументировать.
таки верю, но циску не куплю - привык все делать линуксом :-bключевое слово "все"
Использовать ifconfig не очень корректно, он может не отображать некоторые IP адреса. ip - наше всё, например как-нибудь так
ip a | awk '/inet /&&!/ lo/{print $2}' | cut -d/ -f1
Вы абсолютно правы, спасибо!