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