Routage rapide et NAT sous Linux

À mesure que les adresses IPv4 s'épuisent, de nombreux opérateurs de télécommunications sont confrontés à la nécessité de fournir à leurs clients un accès au réseau grâce à la traduction d'adresses. Dans cet article, je vais vous expliquer comment obtenir des performances NAT de qualité opérateur sur des serveurs standard.

Un peu d'histoire

Le sujet de l’épuisement de l’espace d’adressage IPv4 n’est plus nouveau. À un moment donné, des listes d'attente sont apparues dans RIPE, puis des échanges ont émergé sur lesquels des blocs d'adresses ont été échangés et des accords ont été conclus pour les louer. Peu à peu, les opérateurs de télécommunications ont commencé à fournir des services d'accès à Internet utilisant la traduction d'adresses et de ports. Certains n'ont pas réussi à obtenir suffisamment d'adresses pour attribuer une adresse « blanche » à chaque abonné, tandis que d'autres ont commencé à économiser de l'argent en refusant d'acheter des adresses sur le marché secondaire. Les fabricants d'équipements de réseau ont soutenu cette idée, car cette fonctionnalité nécessite généralement des modules d'extension ou des licences supplémentaires. Par exemple, dans la gamme de routeurs MX de Juniper (à l'exception des derniers MX104 et MX204), vous pouvez effectuer NAPT sur une carte de service MS-MIC distincte, Cisco ASR1k nécessite une licence CGN, Cisco ASR9k nécessite un module A9K-ISM-100 distinct. et une licence A9K-CGN -LIC pour lui. En général, le plaisir coûte très cher.

iptables

La tâche d'exécution du NAT ne nécessite pas de ressources informatiques spécialisées, elle peut être résolue par des processeurs à usage général, installés, par exemple, dans n'importe quel routeur domestique. A l'échelle d'un opérateur télécom, ce problème peut être résolu en utilisant des serveurs standards fonctionnant sous FreeBSD (ipfw/pf) ou GNU/Linux (iptables). Nous ne considérerons pas FreeBSD, car... J'ai arrêté d'utiliser ce système d'exploitation il y a longtemps, nous nous en tiendrons donc à GNU/Linux.

L'activation de la traduction d'adresses n'est pas du tout difficile. Vous devez d'abord enregistrer une règle dans iptables dans la table nat :

iptables -t nat -A POSTROUTING -s 100.64.0.0/10 -j SNAT --to <pool_start_addr>-<pool_end_addr> --persistent

Le système d'exploitation chargera le module nf_conntrack, qui surveillera toutes les connexions actives et effectuera les conversions nécessaires. Il y a ici plusieurs subtilités. Premièrement, puisqu'il s'agit de NAT à l'échelle d'un opérateur télécom, il est nécessaire d'ajuster les délais d'attente, car avec les valeurs par défaut la taille de la table de traduction atteindra rapidement des valeurs catastrophiques. Vous trouverez ci-dessous un exemple des paramètres que j'ai utilisés sur mes serveurs :

net.ipv4.ip_forward = 1
net.ipv4.ip_local_port_range = 8192 65535

net.netfilter.nf_conntrack_generic_timeout = 300
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 60
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 60
net.netfilter.nf_conntrack_tcp_timeout_established = 600
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 45
net.netfilter.nf_conntrack_tcp_timeout_last_ack = 30
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_close = 10
net.netfilter.nf_conntrack_tcp_timeout_max_retrans = 300
net.netfilter.nf_conntrack_tcp_timeout_unacknowledged = 300
net.netfilter.nf_conntrack_udp_timeout = 30
net.netfilter.nf_conntrack_udp_timeout_stream = 60
net.netfilter.nf_conntrack_icmpv6_timeout = 30
net.netfilter.nf_conntrack_icmp_timeout = 30
net.netfilter.nf_conntrack_events_retry_timeout = 15
net.netfilter.nf_conntrack_checksum=0

Et d'autre part, la taille par défaut de la table de traduction n'étant pas conçue pour fonctionner dans les conditions d'un opérateur télécom, il faut l'augmenter :

net.netfilter.nf_conntrack_max = 3145728

Il faut également augmenter le nombre de buckets pour la table de hachage stockant toutes les diffusions (c'est une option du module nf_conntrack) :

options nf_conntrack hashsize=1572864

Après ces manipulations simples, on obtient une conception entièrement fonctionnelle, capable de traduire un grand nombre d'adresses clients en un pool d'adresses externes. Toutefois, les performances de cette solution laissent beaucoup à désirer. Lors de mes premières tentatives d'utilisation de GNU/Linux pour NAT (vers 2013), j'ai pu obtenir des performances d'environ 7 Gbit/s à 0.8 Mpps par serveur (Xeon E5-1650v2). Depuis lors, de nombreuses optimisations différentes ont été réalisées dans la pile réseau du noyau GNU/Linux, les performances d'un serveur sur le même matériel ont augmenté jusqu'à près de 18-19 Gbit/s à 1.8-1.9 Mpps (il s'agissait des valeurs maximales). , mais la demande de volume de trafic traité par un seul serveur a augmenté beaucoup plus rapidement. En conséquence, des schémas ont été développés pour équilibrer la charge sur différents serveurs, mais tout cela a accru la complexité de la configuration, de la maintenance et du maintien de la qualité des services fournis.

Tables NF

De nos jours, une tendance à la mode en matière de « sacs de déplacement » de logiciels est l’utilisation de DPDK et XDP. De nombreux articles ont été écrits sur ce sujet, de nombreux discours différents ont été prononcés et des produits commerciaux apparaissent (par exemple, SKAT de VasExperts). Mais étant donné les ressources de programmation limitées des opérateurs télécoms, il est assez problématique de créer soi-même un « produit » basé sur ces frameworks. Il sera beaucoup plus difficile d'exploiter une telle solution à l'avenir ; il faudra notamment développer des outils de diagnostic. Par exemple, le tcpdump standard avec DPDK ne fonctionnera pas comme ça, et il ne « verra » pas les paquets renvoyés aux câbles utilisant XDP. Au milieu de toutes les discussions sur les nouvelles technologies permettant de transmettre le transfert de paquets vers l'espace utilisateur, elles sont passées inaperçues. rapports и articles Pablo Neira Ayuso, responsable d'iptables, à propos du développement du déchargement de flux dans nftables. Examinons ce mécanisme plus en détail.

L'idée principale est que si le routeur a transmis les paquets d'une session dans les deux sens du flux (la session TCP est passée à l'état ESTABLISHED), alors il n'est pas nécessaire de transmettre les paquets suivants de cette session à travers toutes les règles de pare-feu, car toutes ces vérifications se termineront toujours par le transfert du paquet vers le routage. Et nous n'avons pas réellement besoin de sélectionner une route - nous savons déjà à quelle interface et à quel hôte nous devons envoyer des paquets au cours de cette session. Il ne reste plus qu'à stocker ces informations et à les utiliser pour le routage à un stade précoce du traitement des paquets. Lors de l'exécution de NAT, il est nécessaire de stocker en plus des informations sur les modifications d'adresses et de ports traduites par le module nf_conntrack. Oui, bien sûr, dans ce cas, divers policiers et autres règles d'information et statistiques dans iptables cessent de fonctionner, mais dans le cadre de la tâche d'un NAT permanent distinct ou, par exemple, d'une frontière, cela n'est pas si important, car les services sont répartis sur tous les appareils.

Configuration

Pour utiliser cette fonction, nous avons besoin de :

  • Utilisez un noyau frais. Malgré le fait que la fonctionnalité elle-même soit apparue dans le noyau 4.16, elle est restée très « brute » pendant assez longtemps et a régulièrement provoqué la panique du noyau. Tout s'est stabilisé vers décembre 2019, lorsque les noyaux LTS 4.19.90 et 5.4.5 ont été publiés.
  • Réécrivez les règles iptables au format nftables en utilisant une version assez récente de nftables. Fonctionne exactement dans la version 0.9.0

Si tout est en principe clair avec le premier point, l'essentiel est de ne pas oublier d'inclure le module dans la configuration lors de l'assemblage (CONFIG_NFT_FLOW_OFFLOAD=m), alors le deuxième point demande des explications. Les règles nftables sont décrites complètement différemment de celles d'iptables. Documentation révèle presque tous les points, il y a aussi des spéciaux convertisseurs règles d'iptables à nftables. Par conséquent, je ne donnerai qu'un exemple de configuration de NAT et de déchargement de flux. Une petite légende par exemple : , - ce sont les interfaces réseau par lesquelles transite le trafic ; en réalité il peut y en avoir plus de deux. , — l'adresse de début et de fin de la plage d'adresses « blanches ».

La configuration NAT est très simple :

#! /usr/sbin/nft -f

table nat {
        chain postrouting {
                type nat hook postrouting priority 100;
                oif <o_if> snat to <pool_addr_start>-<pool_addr_end> persistent
        }
}

Avec le déchargement de flux, c'est un peu plus compliqué, mais tout à fait compréhensible :

#! /usr/sbin/nft -f

table inet filter {
        flowtable fastnat {
                hook ingress priority 0
                devices = { <i_if>, <o_if> }
        }

        chain forward {
                type filter hook forward priority 0; policy accept;
                ip protocol { tcp , udp } flow offload @fastnat;
        }
}

C’est en fait toute la configuration. Désormais, tout le trafic TCP/UDP tombera dans la table fastnat et sera traité beaucoup plus rapidement.

résultats

Pour bien comprendre à quel point cela est « beaucoup plus rapide », je joindrai une capture d'écran de la charge sur deux serveurs réels, avec le même matériel (Xeon E5-1650v2), configurés de manière identique, utilisant le même noyau Linux, mais effectuant du NAT dans iptables. (NAT4) et dans nftables (NAT5).

Routage rapide et NAT sous Linux

Il n'y a pas de graphique des paquets par seconde dans la capture d'écran, mais dans le profil de charge de ces serveurs, la taille moyenne des paquets est d'environ 800 octets, donc les valeurs atteignent jusqu'à 1.5 Mpps. Comme vous pouvez le constater, le serveur avec nftables dispose d'une énorme réserve de performances. Actuellement, ce serveur traite jusqu'à 30 Gbit/s à 3 Mpps et est clairement capable de respecter la limitation physique du réseau de 40 Gbps, tout en disposant de ressources CPU libres.

J'espère que ce matériel sera utile aux ingénieurs réseau qui tentent d'améliorer les performances de leurs serveurs.

Source: habr.com

Ajouter un commentaire