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