Iptables/netfiler
Содержание
IPTABLES
Тонкая настройка
Настройка для PPPoE, решение проблемы MTU
Round Robin балансирование IP адресов исходящих соединений средствами iptables
Данное решение отличается изящностью, так как реализует все средствами iptables. Синтаксис: на машине, которая должна балансировать исходящие соединения, выполнить скрипт balancer.sh:
bash balancer.sh
Выключить балансер:
bash 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
Балансировка входящих соединений при достижении лимита скорости одного из сетевых интерфейсов
Возникла задача: если канал забит, перекидывать соединение на другой интерфейс и при уменьшении нагрузки перекидывать обратно.
Дано: два провайдера, клиенты локальной сети, шлюз с linux и три сетевых интерфейса.
WAN1_IFACE=eth1 WAN2_IFACE=eth2 WAN1_RATE=7000 WAN2_RATE=800 WAN1_MARK=1 WAN2_MARK=2 DEFAULT_MARK=1 $ipt -t mangle -A PREROUTING -i ${WAN1_IFACE} -j RATEEST --rateest-name wan1download --rateest-interval 250ms --rateest-ewma 0.5s $ipt -t mangle -A PREROUTING -i ${WAN2_IFACE} -j RATEEST --rateest-name wan2download --rateest-interval 250ms --rateest-ewma 0.5s $ipt -t mangle -A PREROUTING -j CONNMARK --restore-mark $ipt -t mangle -A PREROUTING -m mark ! --mark 0 -j ACCEPT $ipt -t mangle -A PREROUTING -m conntrack --ctstate NEW -m rateest --rateest-delta --rateest1 wan1download --rateest-bps1 ${WAN1_RATE}kbit --rateest-gt --rateest2 \ wan2download --rateest-bps2 ${WAN2_RATE}kbit -j CONNMARK --set-mark ${WAN1_MARK} $ipt -t mangle -A PREROUTING -m conntrack --ctstate NEW -m rateest --rateest-delta --rateest1 wan1download --rateest-bps1 ${WAN1_RATE}kbit --rateest-lt --rateest2 \ wan2download --rateest-bps2 ${WAN2_RATE}kbit -j CONNMARK --set-mark ${WAN2_MARK} $ipt -t mangle -A PREROUTING -m connmark --mark 0 -j CONNMARK --set-mark ${DEFAULT_MARK} $ipt -t mangle -A PREROUTING -j CONNMARK --restore-mark $ipt -t mangle -A PREROUTING -j ACCEPT
/sbin/ip rule add from 192.168.0.x fwmark 1 table wan1 /sbin/ip rule add from 192.168.0.x fwmark 2 table wan2
Итого: когда eth1 забит, клиент из локальной сети переводится на менее загруженный - eth2, а когда eth1 освобождается - клиент возвращается обратно.