Multipath-Routing in Kerneln nach 3.6

15

Wie Sie wahrscheinlich alle wissen, wurde der IPv4-Routencache in der 3.6 Linux-Kernel-Serie entfernt, was schwerwiegende Auswirkungen auf das Multipath-Routing hatte. Der IPv4-Routingcode (im Gegensatz zu IPv6) wählt den nächsten Hop im Round-Robin-Verfahren aus, sodass Pakete von der angegebenen Quell-IP zur angegebenen Ziel-IP nicht immer über denselben nächsten Hop gesendet werden. Vor 3.6 korrigierte der Routing-Cache diese Situation, da der nächste Hop, sobald er ausgewählt war, im Cache blieb und alle weiteren Pakete von derselben Quelle zum selben Ziel diesen nächsten Hop durchliefen. Jetzt wird der nächste Hop für jedes Paket neu ausgewählt, was zu seltsamen Dingen führt: Mit zwei zu gleichen Kosten in der Routing-Tabelle enthaltenen Standardrouten, die jeweils auf einen Internet-Provider verweisen, kann ich nicht einmal eine TCP-Verbindung herstellen, da SYN und ACK anfänglich sind gehe über verschiedene Routen,

Gibt es eine relativ einfache Möglichkeit, das normale Verhalten des Multipath-Routings wiederherzustellen, sodass der nächste Hop pro Flow und nicht pro Paket ausgewählt wird? Gibt es Patches, mit denen die Auswahl von IPv4-Hashes für den nächsten Hop wie bei IPv6 durchgeführt werden kann? Oder wie geht ihr alle damit um?

Eugene
quelle
Haben Sie eine "Split-Access" -Einstellung ähnlich der hier: lartc.org/howto/lartc.rpdb.multiple-links.html ? Wenn ja, wie sehen Ihre Regeln und Routen aus?
the-wabbit
versuche mehrmals "ip route get 173.194.112.247" zu benutzen und poste die Ausgabe
c4f4t0r
Danke für die leckere Frage. :) Zunächst haben Sie uns kein Beispiel gegeben. Ich nehme an, Sie haben so etwas wie ip ro add 8.8.8.8/32 nexthop via 1.2.3.4 nexthop via 1.2.3.5die richtige Annahme?
Poige
Ja, das ist richtig, aber normalerweise ist es ip route add 0.0.0.0/0 mit mehreren nächsten Sprüngen.
Eugene
the-wabbit, ja genau so. "provider 1" und "provider2" sind in meinem Fall Grenzrouter, die mit meinem internen Netzwerk und dem Netzwerk des Anbieters verbunden sind und NAT als Quelle verwenden. Auf meinem internen Router habe ich nur ein Standard-Gateway mit 2 Hops, die auf provider1 und provider2 zeigen, keine anderen Routen. Firewall-Regeln erlauben nur einige Dienste (wie HTTP) für Client-Computer und blockieren alles andere.
Eugene

Antworten:

8

Wenn möglich, führen Sie ein Upgrade auf Linux Kernel> = 4.4 durch.

Hash-basiertes Multipath-Routing wurde eingeführt, das in vielerlei Hinsicht besser ist als das Verhalten vor 3.6. Es ist flussbasiert und verwendet einen Hash der Quell- und Ziel-IPs (Ports werden ignoriert), um den Pfad für einzelne Verbindungen stabil zu halten. Ein Nachteil ist, dass ich glaube, dass es vor 3.6 verschiedene Algorithmen / Konfigurationsmodi gab, aber jetzt bekommen Sie, was Sie bekommen !. Sie können die Wahl des Pfades jedoch durch beeinflussen weight.

Wenn du in meiner Situation bist dann willst du das eigentlich 3.6 >= behaviour < 4.4aber es wird nicht mehr unterstützt.

Wenn Sie ein Upgrade auf> = 4.4 durchführen, sollte dies ohne alle anderen Befehle funktionieren:

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

Alternativ nach Gerät:

ip route add default  proto static scope global \
 nexthop  dev <if_1> weight 1 \
 nexthop  dev <if_2> weight 1
bao7uo
quelle
Für alle, die zu dieser Lösung kommen - schauen Sie auch unter: net.ipv4.fib_multipath_use_neigh nach, um "dropped" nexthop / gateway automatisch zu deaktivieren.
Rostislav Kandilarov
6

"Relativ einfach" ist ein schwieriger Begriff, aber Sie könnten

  1. Richten Sie Routing-Tabellen für jeden Ihrer Links ein - eine Tabelle pro Link mit einem einzigen Standard-Gateway
  2. Verwenden Sie netfilter, um identische Markierungen auf alle Pakete eines einzelnen Streams zu stempeln
  3. Verwenden Sie die IP-Regeltabelle, um die Pakete je nach Markierung über verschiedene Routingtabellen zu routen
  4. Verwenden Sie eine mehrfach gewichtete Route, um die First-in-a-Session-Pakete über Ihre Gateways / Links auszugleichen.

Es gab eine Diskussion in der Netfilter-Mailingliste zu diesem Thema, in der ich die Einträge stehle aus:

1. Weiterleitungsregeln (RPDB und 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. Firewall-Regeln (mit ipset einen "Flow" -LB-Modus erzwingen)

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

Möglicherweise möchten Sie die Diskussion über die Netfilter-Mailingliste für einige Variationen der oben genannten verfolgen.

das-wabbit
quelle
Nicht sicher, aber möglicherweise einfacher zu u32bekommen wichtige Parameter gehasht und dann „label“ zugeordnet für ip rule‚s
poige
Danke, aber das sieht nach einer ziemlich komplexen Lösung aus. Was ich nicht ganz verstehe, ist, welches Stück hier dafür verantwortlich ist, "identische Markierungen auf alle Pakete eines einzelnen Streams zu stempeln"? Wie funktioniert die ipset-Magie? Ich dachte, ipset ist nur ein Satz von bestimmten IPs, die gehasht und in Regeln abgeglichen werden können.
Eugene
Sie haben Recht ipset- es werden nur Mengen erstellt, die mit gefüllt --add-setund mit denen mit verglichen werden --match-set-, aber dies gilt hauptsächlich für die Verbindungen im Status NEW. Bei ESTABLISHED-Statusverbindungen wird die Marke mit dem --restore-markParameter des CONNMARKZiels auf die Pakete gestempelt. Diese Anweisung kopiert die Marke der Verbindung in das Paket. Die Verbindungsmarke wird zuvor mit --save-markin der POSTROUTINGKette gesetzt (wobei Pakete, die zu NEUEN Verbindungen gehören, durchlaufen würden). Das Drehbuch scheint mir zu kompliziert, aber es vermittelt die Idee.
the-wabbit
1
Ja, jetzt habe ich die Idee, denke ich. Die letzte Frage: Verstehen Sie, warum Kernel-Entwickler keine Hash-basierte Next-Hop-Auswahl für ipv4 einführen? Gibt es einen Grund, es nicht zusammen mit dem Entfernen des Routen-Cache zu implementieren? Eine ähnliche Lösung für ipv6 funktioniert ganz gut. Ist all diese Kennzeichen-Magie nicht ein Übermaß für eine so einfache Aufgabe?
Eugene
1
@Eugene Ich bin leider weit davon entfernt, der IP-Stack-Entwicklung (oder der Linux-Kernel-Entwicklung im Allgemeinen) nahe genug zu sein, um alle Ihre Fragen maßgeblich zu beantworten, aber ich würde spekulieren, dass Multipathing mit verschiedenen Anbietern mit IPv4 als zu viel angesehen wurde ein eckkasten, um noch mehr arbeit hinein zu stecken. Die Verwendung von netfilter CONNMARKs sieht offensichtlich nach einem üblen Trick aus, könnte aber bei der Entscheidung, den Route-Cache-Code zu löschen, sogar als "brauchbare Problemumgehung" in Betracht gezogen worden sein.
the-wabbit