Iptables/netfiler
Материал из OpenWiki
Содержание |
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 освобождается - клиент возвращается обратно.
