Enrutament ràpid i NAT a Linux

A mesura que les adreces IPv4 s'esgoten, molts operadors de telecomunicacions s'enfronten a la necessitat de proporcionar als seus clients accés a la xarxa mitjançant la traducció d'adreces. En aquest article us explicaré com podeu obtenir un rendiment NAT de grau de transportista als servidors de productes bàsics.

Una mica d'història

El tema de l'esgotament de l'espai d'adreces IPv4 ja no és nou. En algun moment, van aparèixer llistes d'espera a RIPE, després van sorgir intercanvis en els quals es negociaven blocs d'adreces i es van concloure acords per arrendar-los. A poc a poc, els operadors de telecomunicacions van començar a oferir serveis d'accés a Internet mitjançant la traducció d'adreces i ports. Alguns no van aconseguir les adreces suficients per emetre una adreça "blanca" a cada subscriptor, mentre que altres van començar a estalviar diners en negar-se a comprar adreces al mercat secundari. Els fabricants d'equips de xarxa van donar suport a aquesta idea, perquè aquesta funcionalitat sol requerir mòduls d'extensió o llicències addicionals. Per exemple, a la línia d'encaminadors MX de Juniper (excepte els últims MX104 i MX204), podeu realitzar NAPT en una targeta de servei MS-MIC independent, Cisco ASR1k requereix una llicència CGN, Cisco ASR9k requereix un mòdul A9K-ISM-100 independent. i una llicència A9K-CGN -LIC per a ell. En general, el plaer costa molts diners.

IPTables

La tasca de realitzar NAT no requereix recursos informàtics especialitzats; es pot resoldre mitjançant processadors de propòsit general, que s'instal·len, per exemple, a qualsevol encaminador domèstic. A escala d'un operador de telecomunicacions, aquest problema es pot resoldre mitjançant servidors de productes bàsics que executen FreeBSD (ipfw/pf) o GNU/Linux (iptables). No considerarem FreeBSD, perquè... Vaig deixar d'utilitzar aquest sistema operatiu fa força temps, així que ens quedarem amb GNU/Linux.

Habilitar la traducció d'adreces no és gens difícil. Primer heu de registrar una regla a iptables a la taula nat:

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

El sistema operatiu carregarà el mòdul nf_conntrack, que supervisarà totes les connexions actives i realitzarà les conversions necessàries. Aquí hi ha diverses subtileses. En primer lloc, com que estem parlant de NAT a l'escala d'un operador de telecomunicacions, cal ajustar els temps d'espera, ja que amb els valors predeterminats la mida de la taula de traducció augmentarà ràpidament fins a valors catastròfics. A continuació es mostra un exemple de la configuració que he utilitzat als meus servidors:

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

I en segon lloc, com que la mida predeterminada de la taula de traducció no està dissenyada per funcionar en les condicions d'un operador de telecomunicacions, cal augmentar-la:

net.netfilter.nf_conntrack_max = 3145728

També cal augmentar el nombre de cubs per a la taula hash que emmagatzema totes les emissions (aquesta és una opció al mòdul nf_conntrack):

options nf_conntrack hashsize=1572864

Després d'aquestes manipulacions senzilles, s'obté un disseny completament funcional que pot traduir un gran nombre d'adreces de client en un conjunt d'externes. Tanmateix, el rendiment d'aquesta solució deixa molt a desitjar. En els meus primers intents d'utilitzar GNU/Linux per a NAT (al voltant de 2013), vaig poder obtenir un rendiment d'uns 7 Gbit/s a 0.8 Mpps per servidor (Xeon E5-1650v2). Des d'aleshores, s'han fet moltes optimitzacions diferents a la pila de xarxa del nucli GNU/Linux, el rendiment d'un servidor del mateix maquinari ha augmentat fins a gairebé 18-19 Gbit/s a 1.8-1.9 Mpps (aquests eren els valors màxims) , però la demanda de volum de trànsit processat per un servidor va créixer molt més ràpidament. Com a resultat, es van desenvolupar esquemes per equilibrar la càrrega en diferents servidors, però tot això va augmentar la complexitat de la configuració, el manteniment i el manteniment de la qualitat dels serveis prestats.

NFTables

Avui en dia, una tendència de moda en les "bosses de canvi" de programari és l'ús de DPDK i XDP. S'han escrit molts articles sobre aquest tema, s'han fet molts discursos diferents i estan apareixent productes comercials (per exemple, SKAT de VasExperts). Però tenint en compte els recursos limitats de programació dels operadors de telecomunicacions, és bastant problemàtic crear qualsevol "producte" basat en aquests marcs pel vostre compte. Serà molt més difícil operar aquesta solució en el futur; en particular, s'hauran de desenvolupar eines de diagnòstic. Per exemple, tcpdump estàndard amb DPDK no funcionarà així i no "veura" els paquets enviats als cables mitjançant XDP. Enmig de tota la xerrada sobre noves tecnologies per enviar el reenviament de paquets a l'espai d'usuari, van passar desapercebuts informes и Article Pablo Neira Ayuso, mantenidor d'iptables, sobre el desenvolupament de la descàrrega de flux a nftables. Vegem aquest mecanisme amb més detall.

La idea principal és que si l'encaminador va passar paquets d'una sessió en ambdues direccions del flux (la sessió TCP va passar a l'estat ESTABLISHED), llavors no cal passar els paquets posteriors d'aquesta sessió a través de totes les regles del tallafoc, perquè totes aquestes comprovacions encara acabaran amb la transferència del paquet a l'encaminament. I en realitat no necessitem seleccionar una ruta: ja sabem a quina interfície i a quin host hem d'enviar paquets dins d'aquesta sessió. Només queda emmagatzemar aquesta informació i utilitzar-la per a l'encaminament en una fase inicial del processament de paquets. Quan es realitza NAT, és necessari emmagatzemar informació addicional sobre els canvis d'adreces i ports traduïts pel mòdul nf_conntrack. Sí, per descomptat, en aquest cas diversos policies i altres regles d'informació i estadístiques a iptables deixen de funcionar, però en el marc de la tasca d'un NAT permanent independent o, per exemple, una frontera, això no és tan important, perquè els serveis es distribueixen entre dispositius.

Configuració

Per utilitzar aquesta funció necessitem:

  • Utilitzeu un nucli nou. Malgrat que la pròpia funcionalitat va aparèixer al nucli 4.16, durant força temps va ser molt "crua" i va provocar regularment el pànic del nucli. Tot es va estabilitzar al voltant de desembre de 2019, quan es van llançar els nuclis LTS 4.19.90 i 5.4.5.
  • Reescriu les regles d'iptables en format nftables utilitzant una versió força recent d'nftables. Funciona exactament a la versió 0.9.0

Si en principi tot està clar amb el primer punt, el més important és no oblidar d'incloure el mòdul a la configuració durant el muntatge (CONFIG_NFT_FLOW_OFFLOAD=m), llavors el segon punt requereix una explicació. Les regles de nftables es descriuen de manera completament diferent que a iptables. Registres revela gairebé tots els punts, també n'hi ha especials convertidors regles d'iptables a nftables. Per tant, només donaré un exemple de configuració de NAT i descàrrega de flux. Una petita llegenda per exemple: , - Són les interfícies de xarxa per les quals passa el trànsit; en realitat poden haver-ne més de dues. , — l'adreça inicial i final de l'interval d'adreces "blanques".

La configuració de NAT és molt senzilla:

#! /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
        }
}

Amb la descàrrega de flux és una mica més complicat, però força comprensible:

#! /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;
        }
}

Això, de fet, és tota la configuració. Ara tot el trànsit TCP/UDP caurà a la taula fastnat i es processarà molt més ràpid.

Troballes

Per deixar clar com de "molt més ràpid" això és, adjuntaré una captura de pantalla de la càrrega en dos servidors reals, amb el mateix maquinari (Xeon E5-1650v2), configurat de manera idèntica, utilitzant el mateix nucli Linux, però realitzant NAT en iptables (NAT4) i en nftables (NAT5).

Enrutament ràpid i NAT a Linux

No hi ha cap gràfic de paquets per segon a la captura de pantalla, però en el perfil de càrrega d'aquests servidors la mida mitjana dels paquets és d'uns 800 bytes, de manera que els valors arriben fins a 1.5 Mpps. Com podeu veure, el servidor amb nftables té una gran reserva de rendiment. Actualment, aquest servidor processa fins a 30 Gbit/s a 3 Mpps i és clarament capaç de complir la limitació física de la xarxa de 40 Gbps, alhora que té recursos de CPU gratuïts.

Espero que aquest material sigui útil als enginyers de xarxa que intenten millorar el rendiment dels seus servidors.

Font: www.habr.com

Afegeix comentari