Routing wielościeżkowy w jądrach po wersji 3.6

16

Jak zapewne wszyscy wiecie, pamięć podręczna tras ipv4 została usunięta z serii jądra Linuxa 3.6, co miało poważny wpływ na routing wielościeżkowy. Kod routingu IPv4 (w przeciwieństwie do IPv6) wybiera następny przeskok w sposób okrągły, więc pakiety od danego źródłowego adresu IP do docelowego adresu IP nie zawsze przechodzą przez ten sam następny skok. Przed wersją 3.6 pamięć podręczna routingu korygowała tę sytuację, ponieważ następny skok, po wybraniu, pozostawał w pamięci podręcznej, a wszystkie kolejne pakiety z tego samego źródła do tego samego miejsca docelowego przechodziły przez ten następny skok. Teraz kolejny przeskok jest ponownie wybierany dla każdego pakietu, co prowadzi do dziwnych rzeczy: przy 2 domyślnych trasach o równych kosztach w tabeli routingu, z których każda wskazuje na jednego dostawcę Internetu, nie mogę nawet nawiązać połączenia TCP, ponieważ początkowa SYN i końcowe ACK iść różnymi drogami,

Czy jest jakiś stosunkowo łatwy sposób przywrócić normalne zachowanie routingu wielościeżkowego, aby następny skok był wybierany dla przepływu, a nie dla pakietu? Czy są jakieś łatki, które sprawiają, że IPv4 opiera się na haszu opartym na hash, tak jak w przypadku IPv6? A jak sobie z tym wszystkim radzicie?

Eugene
źródło
Czy masz konfigurację „podzielonego dostępu” podobną do tej tutaj: lartc.org/howto/lartc.rpdb.multiple-links.html ? Jeśli tak, to jak wygląda Twój zestaw reguł i trasy?
the-wabbit
spróbuj użyć „ip route get 173.194.112.247” wiele razy i opublikuj wynik
c4f4t0r
Dziękuję za smaczne pytanie. :) po pierwsze nie dałeś nam przykładu. Więc przypuszczam, że masz coś takiego, ip ro add 8.8.8.8/32 nexthop via 1.2.3.4 nexthop via 1.2.3.5czy to prawidłowe założenie?
poige
Tak, to prawda, ale zwykle jest to trasa ip, dodająca 0.0.0.0/0 z wieloma kolejnymi przeskokami.
Eugene
the-wabbit, tak, dokładnie tak. „dostawca 1” i „dostawca 2” w moim przypadku są routerami granicznymi podłączonymi do mojej sieci wewnętrznej i sieci dostawcy i zapewniają źródłowy NAT. Na moim wewnętrznym routerze mam tylko domyślną bramę z 2 przeskokami wskazującymi na dostawcę 1 i dostawcę 2, bez innych tras. Reguły zapory zezwalają tylko na niektóre usługi (takie jak HTTP) dla komputerów klienckich i blokują wszystko inne.
Eugene

Odpowiedzi:

8

Jeśli to możliwe, zaktualizuj do jądra Linux> = 4.4 ....

Wprowadzono wielościeżkowe routing oparty na skrócie , który pod wieloma względami jest lepszy niż zachowanie wcześniejsze niż 3.6. Jest oparty na przepływie, biorąc hash źródłowych i docelowych adresów IP (porty są ignorowane), aby utrzymać stałą ścieżkę dla poszczególnych połączeń. Jednym minusem jest to, że uważam, że były różne tryby algorytmów / konfiguracji dostępne przed wersją 3.6, ale teraz dostajesz to, co otrzymałeś! Możesz jednak wpłynąć na wybór ścieżki weight.

Jeśli jesteś w mojej sytuacji, to tak naprawdę chcesz, 3.6 >= behaviour < 4.4ale to nie jest już obsługiwane.

Jeśli wykonasz aktualizację do> = 4.4, to powinno załatwić sprawę, bez wszystkich innych poleceń:

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

Alternatywnie według urządzenia:

ip route add default  proto static scope global \
 nexthop  dev <if_1> weight 1 \
 nexthop  dev <if_2> weight 1
bao7uo
źródło
Dla każdego, kto przyjdzie do tego rozwiązania - spójrz również na: net.ipv4.fib_multipath_use_neigh, aby automatycznie wyłączyć „upuszczony” Nexthop / Gateway.
Rostislav Kandilarov
6

„Stosunkowo łatwy” to trudny termin, ale możesz

  1. skonfiguruj tabele routingu dla każdego z linków - jedna tabela na link, z jedną domyślną bramą
  2. użyj netfilter do wybicia identycznych znaków na wszystkich pakietach jednego strumienia
  3. użyj tabeli reguł ip do kierowania pakietów przez różne tabele routingu w zależności od znaku
  4. użyj trasy ważonej wieloma następnymi, aby zrównoważyć pakiety pierwsze w sesji przez twoje bramy / łącza.

Nastąpiło dyskusji na liście dyskusyjnej netfilter na ten temat, gdzie jestem kradzież ofert od:

1. Reguły routingu (RPDB i 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. Reguły zapory (użycie ipset do wymuszenia „przepływu” trybu 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

Możesz śledzić dyskusję o liście mailingowej netfilter dla niektórych wariantów powyższego.

the-wabbit
źródło
Nie jestem pewien, ale może być łatwiej u32uzyskać ip rule
skrót
Dziękuję, ale to wygląda na dość złożone rozwiązanie. Nie do końca rozumiem, który fragment jest odpowiedzialny za „stemplowanie identycznych znaków na wszystkich pakietach jednego strumienia”? Jak działa ta magia ipset? Myślałem, że ipset to tylko zestaw konkretnych adresów IP, które są zaszyfrowane i można je dopasować w regułach.
Eugene
Masz rację ipset- po prostu tworzy zestawy, które są wypełniane za pomocą --add-seti dopasowywane do za pomocą --match-set- ale dotyczy to głównie połączeń w stanie NOWY. W przypadku połączeń stanu USTANOWIONEGO znak jest wybijany na pakietach za pomocą --restore-markparametru CONNMARKcelu - ta dyrektywa kopiuje znak połączenia do pakietu. Znak połączenia jest ustawiony wcześniej używając --save-markw POSTROUTINGłańcuchu (gdzie pakiety należące do nowych połączeń będzie przechodzić przez). Scenariusz wydaje mi się zbyt skomplikowany, ale przekazuje ten pomysł.
the-wabbit
1
Tak, myślę, że teraz mam pomysł. Ostatnie pytanie: czy rozumiesz, dlaczego deweloperzy jądra nie wprowadzają opartego na haszowaniu wyboru następnego przeskoku dla ipv4? Czy istnieje jakiś powód, aby nie wdrażać go wraz z usuwaniem pamięci podręcznej tras? Podobne rozwiązanie dla ipv6 działa całkiem dobrze. Czy cała ta magia łącząca nie jest przesadą przy tak prostym zadaniu?
Eugene
1
@Eugene, niestety, jestem daleki od bycia wystarczająco blisko rozwoju stosu IP (lub ogólnie rozwoju jądra Linuksa), aby autorytatywnie odpowiedzieć na którekolwiek z twoich pytań, ale spekulowałbym, że wielościeżkowość przy użyciu różnych dostawców z IPv4 została uznana za zbyt narożny futerał, w którym można włożyć więcej pracy. Korzystanie z filtru sieciowego CONNMARKs wygląda oczywiście na nieprzyjemną kludge, ale może nawet zostać uznane za „użyteczne obejście” w decyzji o usunięciu kodu pamięci podręcznej trasy.
the-wabbit