Данное решение отличается изящностью, так как реализует все средствами 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.214
root@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.221
Generating 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.220
root@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