Балансирование IP адресов исходящих соединений средствами iptables

Данное решение отличается изящностью, так как реализует все средствами 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
  • 0
  • 02 декабря 2011, 17:51
  • admin

Комментарии (0)

RSS свернуть / развернуть
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.
Яндекс.Метрика