IP-Балансировка: объединяем несколько интернет-каналов в один Сравнение версий

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
wiki:ip_balancing [2009/11/20 05:54]
ubuntarubuntarQui quaerit, reperit
wiki:ip_balancing [2011/10/05 21:15] (текущий)
AndreiBAAndreiBAAndreiBAФигня случается...
Строка 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 ip-balancing балансировка маршрутизация patch-o-matic-ng Администрирование Server Linux_на_предприятии }}