Instradamento multipath nei kernel post-3.6


16

Come probabilmente saprete, la route route ipv4 è stata rimossa in 3.6 kernel kernel series, il che ha avuto un forte impatto sul routing multipath. Il codice di routing IPv4 (a differenza di quello IPv6) seleziona l'hop successivo in modo round robin, quindi i pacchetti dall'IP di origine dato a quello di destinazione non passano sempre attraverso lo stesso hop successivo. Prima del 3.6 la cache di routing correggeva quella situazione, poiché l'hop successivo, una volta selezionato, rimaneva nella cache e tutti gli altri pacchetti dalla stessa sorgente alla stessa destinazione stavano attraversando quell'hop successivo. Ora il prossimo hop viene ri-selezionato per ogni pacchetto, il che porta a cose strane: con 2 route predefinite di uguale costo nella tabella di routing, ciascuna che punta a un provider Internet, non riesco nemmeno a stabilire una connessione TCP, perché SYN iniziale e ACK finale percorrere percorsi diversi,

Esiste un modo relativamente semplice per ripristinare il normale comportamento del routing multipath, in modo che l'hop successivo sia selezionato per flusso anziché per pacchetto? Ci sono patch in giro per rendere IPv4 basato sull'hash di selezione dell'hop successivo, come per IPv6? O come lo affrontate tutti?


Hai una configurazione "split access" simile a questa qui: lartc.org/howto/lartc.rpdb.multiple-links.html ? In tal caso, come sono il tuo set di regole e percorsi?
the-wabbit l'

prova a utilizzare "ip route get 173.194.112.247" più volte e pubblica l'output
c4f4t0r

Grazie per la gustosa domanda. :) prima di tutto, non ci hai dato un esempio. Quindi suppongo che tu abbia qualcosa del genere ip ro add 8.8.8.8/32 nexthop via 1.2.3.4 nexthop via 1.2.3.5è questa supposizione corretta?
poige

Sì, è corretto, ma di solito è ip route aggiungere 0.0.0.0/0 con più hop successivi.
Eugene,

the-wabbit, sì, esattamente così. "provider 1" e "provider2" nel mio caso sono router di frontiera collegati alla mia rete interna e alla rete del provider e generano NAT. Sul mio router interno ho solo un gateway predefinito con 2 hop che indicano provider1 e provider2, nessun altro percorso. Le regole del firewall consentono solo alcuni servizi (come HTTP) per i computer client e bloccano tutto il resto.
Eugene,

Risposte:


8

Se possibile, esegui l'upgrade a Linux Kernel> = 4.4 ....

È stato introdotto il routing multipath basato su hash , che per molti aspetti è migliore del comportamento precedente al 3.6. È basato sul flusso, prendendo un hash degli IP di origine e destinazione (le porte vengono ignorate) per mantenere il percorso costante per le singole connessioni. Un aspetto negativo è che credo che ci fossero vari algoritmi / modalità di configurazione disponibili prima del 3.6, ma ora ottieni quello che ti viene dato !. weightTuttavia, è possibile utilizzare influire sulla scelta del percorso .

Se ti trovi nella mia situazione , in realtà vuoi il 3.6 >= behaviour < 4.4ma non è più supportato.

Se esegui l'aggiornamento a> = 4.4, questo dovrebbe fare il trucco, senza tutti gli altri comandi:

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

In alternativa per dispositivo:

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

Per chiunque arrivi a questa soluzione, dai un'occhiata anche a: net.ipv4.fib_multipath_use_neigh per disabilitare automaticamente "drop" nexthop / gateway.
Rostislav Kandilarov,

6

"Relativamente facile" è un termine difficile, ma potresti

  1. imposta tabelle di instradamento per ciascuno dei tuoi collegamenti - una tabella per collegamento, con un singolo gateway predefinito
  2. usa netfilter per timbrare segni identici su tutti i pacchetti di un singolo flusso
  3. utilizzare la tabella delle regole ip per instradare i pacchetti tramite diverse tabelle di routing in base al segno
  4. utilizzare un percorso ponderato multi-nexthop per bilanciare i pacchetti della prima sessione su gateway / collegamenti.

C'è stata una discussione nella mailing list di netfilter su questo argomento in cui sto rubando gli elenchi da:

1. Regole di routing (RPDB e 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. Regole del firewall (usando ipset per forzare una modalità LB "flow")

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

Potresti voler seguire la discussione sulla mailing list di netfilter per alcune varianti di quanto sopra.


Non sono sicuro, ma potrebbe essere più semplice u32ottenere l'hash dei parametri importanti e quindi assegnare "label" per ip rule's
poige

Grazie, ma sembra una soluzione piuttosto complessa. Quello che non capisco bene è quale pezzo qui è responsabile di "timbrare segni identici su tutti i pacchetti di un singolo flusso"? Come funziona quella magia ipset? Pensavo che ipset fosse solo un insieme di IP particolari che sono stati sottoposti a hash e possono essere abbinati nelle regole.
Eugene,

Hai ragione ipset- si tratta solo di creare insiemi che vengono riempiti utilizzando --add-sete confrontati con l'utilizzo --match-set- ma questo è principalmente per le connessioni nel NUOVO stato. Per le connessioni di stato ESTABLISHED il segno è impresso sui pacchetti usando il --restore-markparametro della CONNMARKdestinazione - questa direttiva sta copiando il segno di connessione sul pacchetto. Il segno di connessione è stato precedentemente impostato usando --save-marknella POSTROUTINGcatena (dove passavano i pacchetti appartenenti a NUOVE connessioni). La sceneggiatura mi sembra eccessivamente contorta, ma trasmette l'idea.
the-wabbit l'

1
Sì, ora ho avuto l'idea, penso. L'ultima domanda: capisci perché gli sviluppatori del kernel non introducono la selezione hop successivo basata su hash per ipv4? C'è qualche motivo per non implementarlo insieme alla rimozione della cache di route? Una soluzione simile per ipv6 funziona abbastanza bene. Tutto ciò che connota la magia non è forse eccessivo per un compito così semplice?
Eugene,

1
@Eugene, sfortunatamente, sono ben lungi dall'essere abbastanza vicino allo sviluppo dello stack IP (o allo sviluppo del kernel Linux in generale) per rispondere in modo autorevole a qualsiasi tua domanda, ma speculerei sul fatto che il multipathing usando provider diversi con IPv4 era considerato troppo un caso d'angolo per aggiungere altro lavoro. L'uso di netfilter CONNMARKs ovviamente sembra un brutto kludge, ma potrebbe anche essere stato considerato un "rimedio utilizzabile" nella decisione di eliminare il codice cache del percorso.
the-wabbit,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.