Question Routage par trajets multiples dans les noyaux postérieurs à 3.6


Comme vous le savez probablement tous, le cache de route ipv4 a été supprimé de la série de noyaux Linux 3.6, ce qui a eu un impact considérable sur le routage par trajets multiples. Le code de routage IPv4 (contrairement à IPv6) sélectionne le saut suivant tour à tour, de sorte que les paquets d'une adresse IP source donnée à une adresse IP de destination donnée ne passent pas toujours par le même saut suivant. Avant la version 3.6, le cache de routage corrigeait cette situation, car le saut suivant, une fois sélectionné, restait dans le cache et tous les paquets supplémentaires provenant de la même source vers la même destination passaient par ce saut suivant. Maintenant, le saut suivant est re-sélectionné pour chaque paquet, ce qui conduit à des choses étranges: avec 2 routes par défaut à coût égal dans la table de routage, chacune pointant vers un fournisseur d'accès, je ne peux même pas établir de connexion TCP, car SYN initial et ACK final passer par différents itinéraires et, en raison de la NAT sur chaque chemin, ils arrivent à destination sous forme de paquets provenant de sources différentes.

Existe-t-il un moyen relativement simple de rétablir le comportement normal du routage par trajets multiples, afin que le saut suivant soit sélectionné par flux plutôt que par paquet? Existe-t-il des correctifs permettant de rendre le choix du saut suivant IPv4 basé sur un hachage, comme pour IPv6? Ou comment faites-vous tous face à cela?


15
2018-06-04 15:59


origine


Avez-vous une configuration "accès fractionné" semblable à celle-ci ici: lartc.org/howto/lartc.rpdb.multiple-links.html ? Si tel est le cas, à quoi ressemblent votre jeu de règles et vos routes? - the-wabbit
essayez d'utiliser "ip route get 173.194.112.247" plusieurs fois et envoyez le résultat - c4f4t0r
Merci pour la bonne question. :) tout d'abord, vous ne nous avez pas donné d'exemple. Donc je suppose que vous avez quelque chose comme ip ro add 8.8.8.8/32 nexthop via 1.2.3.4 nexthop via 1.2.3.5 Cette hypothèse est-elle correcte? - poige
Oui, c’est correct, mais c’est généralement ip route ajouter 0.0.0.0/0 avec plusieurs prochains sauts. - Eugene
le-wabbit, oui, exactement comme ça. "fournisseur 1" et "fournisseur2" dans mon cas sont des routeurs frontaliers connectés à mon réseau interne et au réseau du fournisseur et ils effectuent le NAT source. Sur mon routeur interne, j'ai juste la passerelle par défaut avec 2 sauts pointant vers provider1 et provider2, pas d'autres routes. Les règles de pare-feu autorisent seulement certains services (comme HTTP) pour les ordinateurs clients et bloquent tout le reste. - Eugene


Réponses:


"Relativement facile" est un terme difficile, mais vous pourriez

  1. configurer des tables de routage pour chacun de vos liens - une table par lien, avec une seule passerelle par défaut
  2. utilisez netfilter pour marquer des marques identiques sur tous les paquets d'un seul flux
  3. utilisez la table de règles ip pour acheminer les paquets via différentes tables de routage en fonction de la marque
  4. utilisez une route pondérée multi-nexthop pour équilibrer les premiers paquets d'une session sur vos passerelles / liens.

Il y a eu un discussion sur la liste de diffusion netfilter sur ce sujet où je vole les annonces de:

1. Règles de routage (RPDB et 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. Règles de pare-feu (utilisation d'ipset pour forcer le mode "flux" 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

Vous voudrez peut-être suivre la discussion sur la liste de diffusion netfilter pour connaître certaines variantes de ce qui précède.


6
2018-06-08 13:12



Pas sûr, mais pourrait être plus simple à u32 pour obtenir des paramètres importants hachés puis "label" attribué pour ip rulede - poige
Merci, mais cela ressemble à une solution assez complexe. Ce que je ne comprends pas très bien, c'est quelle pièce est responsable de "marquer des marques identiques sur tous les paquets d'un même flux"? Comment fonctionne cette magie ipset? Je pensais qu'ipset n'était qu'un ensemble d'adresses IP particulières qui sont hachées et qui peuvent être comparées dans des règles. - Eugene
Vous avez raison à propos de ipset - il s’agit juste de créer des ensembles remplis avec --add-set et apparié contre l'utilisation --match-set - mais c'est surtout pour les connexions à l'état NEW. Pour les connexions à l’état ESTABLISHED, la marque est apposée sur les paquets à l’aide du --restore-mark paramètre de la CONNMARK cible - cette directive copie la marque de la connexion dans le paquet. La marque de la connexion est précédemment définie à l'aide de --save-mark dans le POSTROUTING chaîne (où les paquets appartenant à de nouvelles connexions passeraient). Le scénario me semble trop compliqué, mais il traduit l'idée. - the-wabbit
Oui, maintenant j'ai eu l'idée, je pense. Dernière question: comprenez-vous pourquoi les développeurs du noyau n'introduisent pas de sélection de saut suivant pour ipv4 basée sur le hachage? Y a-t-il une raison pour ne pas l'implémenter avec la suppression du cache de routage? Une solution similaire pour ipv6 fonctionne assez bien. Toute cette magie connue n’est-elle pas exagérée pour une tâche aussi simple? - Eugene
@Eugene malheureusement, je suis loin d'être assez proche du développement de la pile IP (ou du développement du noyau Linux en général) pour répondre avec autorité à toutes vos questions, mais je supposerais que le multipathing utilisant différents fournisseurs avec IPv4 était considéré comme trop important un cas de coin pour mettre plus de travail dedans. L'utilisation de netfilter CONNMARKs ressemble évidemment à un vilain kludge, mais pourrait même avoir été considérée comme une "solution de contournement utilisable" dans la décision de supprimer le code du cache de la route. - the-wabbit


Si possible, effectuez une mise à niveau vers le noyau Linux> = 4.4 ....

Routage par trajets multiples basé sur le hachage a été introduit, ce qui à bien des égards est meilleur que le comportement antérieur à 3.6. Il est basé sur le flux et utilise un hachage des adresses IP source et de destination (les ports sont ignorés) pour maintenir le chemin stable pour les connexions individuelles. Un inconvénient est que je pense qu'il y avait différents algorithmes / modes de configuration disponibles avant la version 3.6, mais maintenant vous obtenez ce que vous avez reçu!. Vous pouvez utiliser affecter le choix du chemin par weight bien que.

Si vous êtes dans ma situation alors vous voulez réellement le 3.6 >= behaviour < 4.4 mais ce n'est plus supporté.

Si vous effectuez une mise à niveau vers> = 4.4, cela devrait faire l'affaire, sans toutes les autres commandes:

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

Alternativement par appareil:

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

6
2017-12-12 21:56