Многолучевая маршрутизация в ядрах после 3.6


16

Как вы все, наверное, знаете, кэш маршрутов ipv4 был удален в ядре 3.6 Linux, что серьезно повлияло на многопутевую маршрутизацию. Код маршрутизации IPv4 (в отличие от IPv6) выбирает следующий переход циклически, поэтому пакеты от данного исходного IP-адреса к данному IP-адресу назначения не всегда проходят через тот же следующий переход. До версии 3.6 кэш маршрутизации исправлял эту ситуацию, поскольку следующий переход, после выбора, оставался в кэше, и все последующие пакеты из того же источника в то же место назначения проходили этот следующий переход. Теперь следующий переход повторно выбирается для каждого пакета, что приводит к странным вещам: с 2 одинаковыми по умолчанию маршрутами в таблице маршрутизации, каждый из которых указывает на одного интернет-провайдера, я даже не могу установить TCP-соединение, потому что начальный SYN и окончательный ACK идти по разным маршрутам,

Есть ли относительно простой способ восстановить нормальное поведение многолучевой маршрутизации, чтобы следующий переход выбирался для каждого потока, а не для каждого пакета? Существуют ли исправления, позволяющие сделать выбор следующего перехода IPv4 на основе хеша, как это делается для IPv6? Или как вы все с этим справляетесь?


Есть ли у вас настройка «разделенного доступа», подобная этой: lartc.org/howto/lartc.rpdb.multiple-links.html ? Если да, то как выглядит ваш набор правил и маршруты?
The Wabbit

попробуйте использовать "ip route get 173.194.112.247" несколько раз и
опубликуйте

Спасибо за вкусный вопрос. :) Во-первых, вы не дали нам пример. Итак, я полагаю, у вас есть что-то вроде ip ro add 8.8.8.8/32 nexthop via 1.2.3.4 nexthop via 1.2.3.5этого правильного предположения?
Пойдж

Да, это правильно, но обычно это ip route add 0.0.0.0/0 с несколькими последующими прыжками.
Евгений

the-wabbit, да, именно так. «провайдер 1» и «провайдер2» в моем случае являются пограничными маршрутизаторами, подключенными к моей внутренней сети и сети провайдера, и они делают исходный NAT. На моем внутреннем маршрутизаторе у меня просто есть шлюз по умолчанию с 2 прыжками, указывающими на provider1 и provider2, никаких других маршрутов. Правила брандмауэра просто разрешают некоторые службы (например, HTTP) для клиентских машин и блокируют все остальное.
Евгений

Ответы:


8

Если возможно, обновите ядро ​​до Linux> = 4.4 ....

Была введена многопутевая маршрутизация на основе хеша , которая во многих отношениях лучше, чем поведение до 3.6. Он основан на потоке и использует хэш IP-адресов источника и назначения (порты игнорируются), чтобы поддерживать постоянный путь для отдельных соединений. Недостатком является то, что я считаю, что до 3.6 были доступны различные алгоритмы / режимы конфигурации, но теперь вы получаете то, что вам дают !. Вы можете использовать повлиять на выбор пути, weightхотя.

Если вы находитесь в моей ситуации, то вы действительно хотите, 3.6 >= behaviour < 4.4но это больше не поддерживается.

Если вы обновляете до> = 4.4, это должно сработать без других команд:

ip route add default  proto static scope global \
nexthop  via <gw_1> weight 1 \
nexthop  via <gw_2> weight 1

Альтернативно по устройству:

ip route add default  proto static scope global \
 nexthop  dev <if_1> weight 1 \
 nexthop  dev <if_2> weight 1

Для любого, кто придет к этому решению - посмотрите также: net.ipv4.fib_multipath_use_neigh для автоматического отключения «отброшенного» nexthop / gateway.
Ростислав Кандиларов

6

«Относительно легко» - сложный термин, но вы можете

  1. настроить таблицы маршрутизации для каждой из ваших ссылок - по одной таблице на ссылку с одним шлюзом по умолчанию
  2. используйте netfilter для отметки одинаковых меток на всех пакетах одного потока
  3. используйте таблицу правил ip для маршрутизации пакетов через разные таблицы маршрутизации в зависимости от марки
  4. используйте взвешенный маршрут multi-nexthop, чтобы сбалансировать пакеты «первый в сеансе» по вашим шлюзам / каналам.

В списке рассылки netfilter была дискуссия на эту тему, где я краду списки из:

1. Правила маршрутизации (RPDB и FIB)

ip route add default via <gw_1> lable link1
ip route add <net_gw1> dev <dev_gw1> table link1
ip route add default via <gw_2> table link2
ip route add <net_gw2> dev <dev_gw2> table link2

/sbin/ip route add default  proto static scope global table lb \
 nexthop  via <gw_1> weight 1 \
 nexthop  via <gw_2> weight 1

ip rule add prio 10 table main
ip rule add prio 20 from <net_gw1> table link1
ip rule add prio 21 from <net_gw2> table link2
ip rule add prio 50 fwmark 0x301 table link1
ip rule add prio 51 fwmark 0x302 table link2
ip rule add prio 100 table lb

ip route del default

2. Правила брандмауэра (использование ipset для включения режима «потока» LB)

ipset create lb_link1 hash:ip,port,ip timeout 1200
ipset create lb_link2 hash:ip,port,ip timeout 1200

# Set firewall marks and ipset hash
iptables -t mangle -N SETMARK
iptables -t mangle -A SETMARK -o <if_gw1> -j MARK --set-mark 0x301
iptables -t mangle -A SETMARK -m mark --mark 0x301 -m set !
--match-set lb_link1 src,dstport,dst -j SET \
          --add-set lb_link1 src,dstport,dst
iptables -t mangle -A SETMARK -o <if_gw2> -j MARK --set-mark 0x302
iptables -t mangle -A SETMARK -m mark --mark 0x302 -m set !
--match-set lb_link2 src,dstport,dst -j SET \
          --add-set lb_link2 src,dstport,dst

# Reload marks by ipset hash
iptables -t mangle -N GETMARK
iptables -t mangle -A GETMARK -m mark --mark 0x0 -m set --match-set
lb_link1 src,dstport,dst -j MARK --set-mark 0x301
iptables -t mangle -A GETMARK -m mark --mark 0x0 -m set --match-set
lb_link2 src,dstport,dst -j MARK --set-mark 0x302

# Defining and save firewall marks
iptables -t mangle -N CNTRACK
iptables -t mangle -A CNTRACK -o <if_gw1> -m mark --mark 0x0 -j SETMARK
iptables -t mangle -A CNTRACK -o <if_gw2> -m mark --mark 0x0 -j SETMARK
iptables -t mangle -A CNTRACK -m mark ! --mark 0x0 -j CONNMARK --save-mark
iptables -t mangle -A POSTROUTING -j CNTRACK

# Reload all firewall marks
# Use OUTPUT chain for local access (Squid proxy, for example)
iptables -t mangle -A OUTPUT -m mark --mark 0x0 -j CONNMARK --restore-mark
iptables -t mangle -A OUTPUT -m mark --mark 0x0 -j GETMARK
iptables -t mangle -A PREROUTING -m mark --mark 0x0 -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING -m mark --mark 0x0 -j GETMARK

Возможно, вы захотите проследить за обсуждением списка рассылки netfilter для некоторых вариантов выше.


Не уверен, но может быть проще u32получить важные параметры хэшируются , а затем «ярлык» назначен на ip rule«S
poige

Спасибо, но это выглядит довольно сложным решением. То, что я не совсем понимаю, это то, что здесь отвечает за «печать одинаковых меток на всех пакетах одного потока»? Как работает эта магия ipset? Я думал, что ipset - это просто набор конкретных IP-адресов, которые хэшируются и могут быть сопоставлены в правилах.
Евгений

Вы правы ipset- это просто создание наборов, которые заполнены с использованием --add-setи сопоставлены с использованием --match-set- но это в основном для соединений в состоянии NEW. Для соединений с УСТАНОВЛЕННЫМ состоянием отметка помечается на пакетах с использованием --restore-markпараметра CONNMARKцели - эта директива копирует отметку соединения в пакет. Метки соединения предварительно устанавливаются с использованием --save-markв POSTROUTINGцепи (где пакеты , принадлежащие к новым соединениям будут проходить через). Сценарий кажется мне слишком запутанным, но он передает идею.
The Wabbit

1
Да, теперь у меня есть идея, я думаю. Последний вопрос: понимаете ли вы, почему разработчики ядра не вводят выбор следующего перехода на основе хеш-функции для ipv4? Есть ли какая-то причина не реализовывать это вместе с удалением кэша маршрутов? Подобное решение для ipv6 работает довольно хорошо. Разве все это волшебство не является излишним для такой простой задачи?
Юджин

1
@ Евгений, к сожалению, я далек от того, чтобы быть достаточно близким к разработке стека IP (или разработке ядра Linux в целом), чтобы авторитетно отвечать на любые ваши вопросы, но я бы предположил, что многолучевое использование различных провайдеров с IPv4 считалось слишком большим угловой случай, чтобы поместить больше работы в это. Использование netfilter CONNMARKs, очевидно, выглядит как неприятный ключ, но, возможно, даже рассматривалось как «полезный обходной путь» в решении отбросить код кэша маршрута.
the-wabbit
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.