Различия
Здесь показаны различия между двумя версиями данной страницы.
Предыдущая версия справа и слева Предыдущая версия Следующая версия | Предыдущая версия | ||
wiki:ip_balancing [2009/11/20 05:56] |
wiki:ip_balancing [2011/10/05 21:15] |
||
---|---|---|---|
Строка 1: | Строка 1: | ||
- | ====== FIXME IP-Балансировка: объединяем несколько интернет каналов в один ====== | + | ====== IP-Балансировка: объединяем несколько интернет-каналов в один ====== |
- | ---- | ||
===== Цели и средства ===== | ===== Цели и средства ===== | ||
- | * Имеется два или более каналов интернет,работающие на разных интерфейсах | + | * Имеется два или более каналов интернет, работающие на разных интерфейсах |
- | * Необходимо объединить эти каналы,увеличив общую скорость интернет,что может быть полезно для программ,создающих множественные подключения (Transmission,aMule и т.д.) | + | * Необходимо объединить эти каналы, увеличив общую скорость интернет, что может быть полезно для программ, создающих множественные подключения (Transmission, aMule и т.д.) |
- | * В руководстве предлагается 3 способа это сделать.Два из них не требуют дополнительного программного обеспечения,третий предполагает использование пакета patch-o-matic-ng (последний способ не проверен автором данного руководства) | + | * В руководстве предлагается 3 способа это сделать. Два из них не требуют дополнительного программного обеспечения, третий предполагает использование пакета patch-o-matic-ng (последний способ не проверен автором данного руководства) |
---- | ---- | ||
+ | |||
===== Способ 1 ===== | ===== Способ 1 ===== | ||
- Настройка **iproute2** : Создать в **/etc/iproute2/rt_tables** две таблицы для каждого из провайдеров: <code bash>sudo nano /etc/iproute2/rt_tables</code><file># | - Настройка **iproute2** : Создать в **/etc/iproute2/rt_tables** две таблицы для каждого из провайдеров: <code bash>sudo nano /etc/iproute2/rt_tables</code><file># | ||
Строка 22: | Строка 22: | ||
#1 inr.ruhep | #1 inr.ruhep | ||
101 FreeNet | 101 FreeNet | ||
- | 102 Wireless</file> | + | 102 NLine</file> |
- Создать файл /etc/routing/FreeNet.list в него можно дописывать адреса путь к которым будет идти четко через основного провайдера. | - Создать файл /etc/routing/FreeNet.list в него можно дописывать адреса путь к которым будет идти четко через основного провайдера. | ||
- Создать и запустить данный скрипт,предварительно отредактировав переменные: <code bash>#!/bin/sh | - Создать и запустить данный скрипт,предварительно отредактировав переменные: <code bash>#!/bin/sh | ||
Строка 150: | Строка 150: | ||
W1="2" | W1="2" | ||
W2="1"</code> | W2="1"</code> | ||
- | - Добавим в файл /etc/iproute2/rt_tables две дополнительные таблицы маршрутизации:<code bash>echo "1 provider1" >> /etc/iproute2/rt_tables | + | - Добавим в файл /etc/iproute2/rt_tables две дополнительные таблицы маршрутизации:<code bash>sudo nano /etc/iproute2/rt_tables</code><file># |
- | echo "2 provider2" >> /etc/iproute2/rt_tables</code> | + | # reserved values |
- | <note warning>ведутся работы</note> | + | # |
+ | 255 local | ||
+ | 254 main | ||
+ | 253 default | ||
+ | 0 unspec | ||
+ | # | ||
+ | # local | ||
+ | # | ||
+ | #1 inr.ruhep | ||
+ | 1 provider1 | ||
+ | 2 provider2</file> | ||
+ | - Теперь напишем скрипт, который будет прописывать все необходимые маршруты и правила файрвола:<code bash>sudo nano /etc/balance/routing.sh</code><code bash>#!/bin/bash | ||
+ | |||
+ | . /etc/balance/vars | ||
+ | |||
+ | echo "1" > /proc/sys/net/ipv4/ip_forward | ||
+ | |||
+ | |||
+ | ip route add $P1_NET dev $IF1 src $IP1 table $TBL1 > /dev/null 2>&1 | ||
+ | ip route add default via $P1 table $TBL1 > /dev/null 2>&1 | ||
+ | ip route add $P2_NET dev $IF2 src $IP2 table $TBL2 > /dev/null 2>&1 | ||
+ | ip route add default via $P2 table $TBL2 > /dev/null 2>&1 | ||
+ | |||
+ | ip route add $P1_NET dev $IF1 src $IP1 > /dev/null 2>&1 | ||
+ | ip route add $P2_NET dev $IF2 src $IP2 | ||
+ | |||
+ | ip route add default via $P1 > /dev/null 2>&1 | ||
+ | |||
+ | ip rule add from $IP1 table $TBL1 > /dev/null 2>&1 | ||
+ | ip rule add from $IP2 table $TBL2 > /dev/null 2>&1 | ||
+ | |||
+ | |||
+ | ip route add $P0_NET dev $IF0 table $TBL1 > /dev/null 2>&1 | ||
+ | ip route add $P2_NET dev $IF2 table $TBL1 > /dev/null 2>&1 | ||
+ | ip route add 127.0.0.0/8 dev lo table $TBL1 > /dev/null 2>&1 | ||
+ | ip route add $P0_NET dev $IF0 table $TBL2 > /dev/null 2>&1 | ||
+ | ip route add $P1_NET dev $IF1 table $TBL2 > /dev/null 2>&1 | ||
+ | ip route add 127.0.0.0/8 dev lo table $TBL2 > /dev/null 2>&1 | ||
+ | |||
+ | iptables -t nat -F POSTROUTING | ||
+ | iptables -t nat -A POSTROUTING -s $P0_NET -o $IF1 -j MASQUERADE | ||
+ | iptables -t nat -A POSTROUTING -s $P0_NET -o $IF2 -j MASQUERADE</code>Этот набор команд обеспечивает маршрутизацию ответов через интерфейс, на котором был получен запрос, а так же маскарадинг на обоих интерфейсах. | ||
+ | - Теперь напишем скрипт, который будет определять, работатет ли тот или иной канал и соответственно менять записи шлюза по умолчанию.<code bash>sudo nano /etc/balance/check.sh</code><code bash>#!/bin/bash | ||
+ | |||
+ | . /etc/balance/vars | ||
+ | |||
+ | OLDIF1=0 | ||
+ | OLDIF2=0 | ||
+ | |||
+ | . /etc/balance/routing.sh | ||
+ | while true; do | ||
+ | |||
+ | |||
+ | ping -c 3 -s 100 $P1 -I $IF1 > /dev/null | ||
+ | if [ $? -ne 0 ]; then | ||
+ | echo "Failed IF1!" | ||
+ | NEWIF1=0 | ||
+ | else | ||
+ | NEWIF1=1 | ||
+ | fi | ||
+ | |||
+ | ping -c 3 -s 100 $P2 -I $IF2 > /dev/null | ||
+ | if [ $? -ne 0 ]; then | ||
+ | echo "Failed IF2!" | ||
+ | NEWIF2=0 | ||
+ | else | ||
+ | NEWIF2=1 | ||
+ | fi | ||
+ | |||
+ | if (( ($NEWIF1!=$OLDIF1) || ($NEWIF2!=$OLDIF2) )); then | ||
+ | echo "Changing routes" | ||
+ | |||
+ | if (( ($NEWIF1==1) && ($NEWIF2==1) )); then | ||
+ | echo "Both channels" | ||
+ | ip route delete default | ||
+ | ip route add default scope global nexthop via $P1 dev $IF1 weight $W1 \ | ||
+ | nexthop via $P2 dev $IF2 weight $W2 | ||
+ | elif (( ($NEWIF1==1) && ($NEWIF2==0) )); then | ||
+ | echo "First channel" | ||
+ | ip route delete default | ||
+ | ip route add default via $P1 dev $IF1 | ||
+ | elif (( ($NEWIF1==0) && ($NEWIF2==1) )); then | ||
+ | echo "Second channel" | ||
+ | ip route delete default | ||
+ | ip route add default via $P2 dev $IF2 | ||
+ | fi | ||
+ | |||
+ | else | ||
+ | echo "Not changed" | ||
+ | fi | ||
+ | |||
+ | OLDIF1=$NEWIF1 | ||
+ | OLDIF2=$NEWIF2 | ||
+ | sleep 3 | ||
+ | done</code>Работу канала проверяем пингуя шлюз, и если нет ответа на 3 пинга подряд — мы считаем, что канал упал, и соответственно исключаем его из таблицы маршрутизации.Таким образом, если работают оба канала:<code bash>ip route | ||
+ | 195.5.xx.xx dev ppp0 proto kernel scope link src 95.133.xx.xx | ||
+ | 194.9.xx.xx/xx dev eth0 proto kernel scope link src 194.9.xx.xx | ||
+ | 192.168.0.0/24 dev eth1 proto kernel scope link src 192.168.0.75 | ||
+ | default | ||
+ | nexthop via 194.9.xx.xx dev eth0 weight 2 | ||
+ | nexthop via 195.5.xx.xx dev ppp0 weight 1</code>Итого имеем два шлюза, первый с весом 2 и второй с весом 1. Тоесть через первый канал пойдет в два раза больше трафика, чем через второй.Для того, чтобы изменить эти скрипты под ваши нужды необходимо настроить значения в файле vars, остальные скрипты практически не требуют настройки. | ||
+ | |||
+ | ---- | ||
+ | ===== Способ 3 ===== | ||
+ | В следующем примере понадобится пропатченное ядро Linux с поддержкой **ROUTE** и модулей **nth** или **random**.Эти модули предоставляются пакетом patch-o-matic-ng,который нужно скачать с репозитория [[http://www.netfilter.org/downloads.html#svn|subversion]] .О том,как пропатчить ядро и установить требуемый пакет,смотрите прилагающуюся документацию к нему. | ||
+ | |||
+ | ==== Установка ==== | ||
+ | В следующем примере будем считать,что имеется три разных интефейса: | ||
+ | * eth0: Проводное соединение, 192.168.1.0/24, шлюз 192.168.1.1, канал по умолчанию. | ||
+ | * eth1: Беспроводное соединение 1, 172.16.0.0/16, шлюз 172.16.0.1 | ||
+ | * rausb0: Бесроводное соединение 2, 192.168.0.0/24, шлюз 192.168.0.1 | ||
+ | Мы будем использовать **connmark** для привязки соединений к конкретному интерфейсу,чтобы определённые пакеты были жёстко привязаны к интерфейсу и шли только через него.Балансировка может быть сделана с помощью модуля nth ,а также random.Мы рассмотрим оба случая,Вы выбирайте тот,который вам больше нравится. | ||
+ | * Сначала общие команды для обоих методов:<code bash># FIXME (тут нужен точный перевод) | ||
+ | # prevent incoming packets on masqueraded connections from being dropped | ||
+ | # as "martians" due to the destination address being translated before the | ||
+ | # rp_filter check is performed | ||
+ | echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter | ||
+ | echo 0 > /proc/sys/net/ipv4/conf/rausb0/rp_filter | ||
+ | |||
+ | # FIXME (тут нужен точный перевод) | ||
+ | # Load protocol-specific connection tracking modules so that new connections | ||
+ | # associated with existing connections have state "RELATED" and inherit the | ||
+ | # same connmark. | ||
+ | modprobe ip_conntrack_ftp | ||
+ | |||
+ | # Маскарадинг для исходящих соединений на второстепенных интерфейсах | ||
+ | iptables -t nat -A POSTROUTING -o eth1 -s ! 172.16.0.0/16 -m state --state NEW,RELATED -j MASQUERADE | ||
+ | iptables -t nat -A POSTROUTING -o rausb0 -s ! 192.168.0.0/24 -m state --state NEW,RELATED -j MASQUERADE | ||
+ | |||
+ | # Создаём цепочку,обрабатывающую новые исходящие соединения | ||
+ | iptables -t mangle -N NEW_OUT_CONN | ||
+ | |||
+ | # Пропустить соединения,которые мы хотим,чтобы шли всегда через проводное соединение | ||
+ | iptables -t mangle -A NEW_OUT_CONN -d 192.168.1.0/24 -j RETURN | ||
+ | iptables -t mangle -A NEW_OUT_CONN -p tcp -m multiport --destination-ports 21,22,80,443,6667 -j RETURN | ||
+ | iptables -t mangle -A NEW_OUT_CONN -p udp --dport 53 -j RETURN | ||
+ | |||
+ | # новые исходящие соединения проходят через вышеуказанную цепочку правил | ||
+ | iptables -t mangle -A OUTPUT -o eth0 -m state --state NEW -j NEW_OUT_CONN | ||
+ | |||
+ | # шлём пакеты через выбранный интерфейс | ||
+ | iptables -t mangle -A OUTPUT -m connmark --mark 2 -j ROUTE --gw 172.16.0.1 --continue | ||
+ | iptables -t mangle -A OUTPUT -m connmark --mark 3 -j ROUTE --gw 192.168.0.1 --continue</code> | ||
+ | * Метод с помощью **random**:<code bash># 34% от времени идём через канал по умолчанию | ||
+ | iptables -t mangle -A NEW_OUT_CONN -j CONNMARK --set-mark 0 | ||
+ | iptables -t mangle -A NEW_OUT_CONN -m random --average 34 -j RETURN | ||
+ | |||
+ | # примерно 33% от времени идём через eth1 (50% от оставшейся вероятности) | ||
+ | iptables -t mangle -A NEW_OUT_CONN -j CONNMARK --set-mark 2 | ||
+ | iptables -t mangle -A NEW_OUT_CONN -m random --average 50 -j RETURN | ||
+ | |||
+ | # иначе (примерно 33% от времени) идём через rausb0 | ||
+ | iptables -t mangle -A NEW_OUT_CONN -j CONNMARK --set-mark 3</code> | ||
+ | * Метод с помощью **nth**:<code bash># Каждое первое из трёх соединений идёт через канал по умолчанию | ||
+ | iptables -t mangle -A NEW_OUT_CONN -j CONNMARK --set-mark 0 | ||
+ | iptables -t mangle -A NEW_OUT_CONN -m nth --counter 1 --every 3 --packet 0 -j RETURN | ||
+ | |||
+ | # Каждое второе из трёх соединений идёт через eth1 | ||
+ | iptables -t mangle -A NEW_OUT_CONN -j CONNMARK --set-mark 2 | ||
+ | iptables -t mangle -A NEW_OUT_CONN -m nth --counter 1 --every 3 --packet 1 -j RETURN | ||
+ | |||
+ | # Каждое третье из трёх соединений идёт rausb0 | ||
+ | iptables -t mangle -A NEW_OUT_CONN -j CONNMARK --set-mark 3 | ||
+ | iptables -t mangle -A NEW_OUT_CONN -m nth --counter 1 --every 3 --packet 2 -j RETURN</code> | ||
+ | * Предусмотрим случай,когда один из интерфейсов перестаёт работать (на Debian-системах нужно положить этот скрипт в папку **/etc/network/if-down.d/** и сделать его исполняемым (**chmod +x**)):<code bash>#!/bin/sh | ||
+ | |||
+ | if [ "$IFACE" = "eth1" ]; then | ||
+ | iptables -t mangle -D OUTPUT -m connmark --mark 2 -j ROUTE --gw 172.16.0.1 --continue 2>/dev/null | ||
+ | fi | ||
+ | |||
+ | if [ "$IFACE" = "rausb0" ]; then | ||
+ | iptables -t mangle -D OUTPUT -m connmark --mark 3 -j ROUTE --gw 192.168.0.1 --continue 2>/dev/null | ||
+ | fi | ||
+ | |||
+ | exit 0</code> | ||
+ | * Теперь скрипт в случае,если интерфейс заработал снова (на Debian-системах нужно положить этот скрипт в папку **/etc/network/if-up.d/** и сделать его исполняемым (**chmod +x**)): <code bash>#!/bin/sh | ||
+ | |||
+ | if [ "$IFACE" = "eth1" ]; then | ||
+ | iptables -t mangle -A OUTPUT -m connmark --mark 2 -j ROUTE --gw 172.16.0.1 --continue 2>/dev/null | ||
+ | fi | ||
+ | |||
+ | if [ "$IFACE" = "rausb0" ]; then | ||
+ | iptables -t mangle -A OUTPUT -m connmark --mark 3 -j ROUTE --gw 192.168.0.1 --continue 2>/dev/null | ||
+ | fi | ||
+ | |||
+ | exit 0</code> | ||
+ | |||
+ | ---- | ||
+ | ===== Ссылки ===== | ||
+ | Оригиналы статей: | ||
+ | - http://forum.0day.kiev.ua/index.php?showtopic=129574 | ||
+ | - http://habrahabr.ru/blogs/linux/54748/ | ||
+ | - http://tetro.net/misc/multilink.html | ||
+ | ===== Обсуждение ===== | ||
+ | Для обсуждения проблем,связанных с данным руководством,предлагаем Вам создать тему на форуме http://forum.ubuntu.ru (не забудьте,пожалуйста,обновить данную статью и добавить тут ссылку на обсуждение) | ||
- | {{tag> howto}} | + | {{tag> howto ip-balancing балансировка маршрутизация patch-o-matic-ng Администрирование Server Linux_на_предприятии }} |