Snelle routering en NAT in Linux

Nu IPv4-adressen uitgeput raken, worden veel telecomoperatoren geconfronteerd met de noodzaak om hun klanten netwerktoegang te bieden met behulp van adresvertaling. In dit artikel vertel ik je hoe je Carrier Grade NAT-prestaties kunt krijgen op commodity-servers.

Een beetje geschiedenis

Het onderwerp uitputting van IPv4-adresruimte is niet langer nieuw. Op een gegeven moment verschenen er wachtlijsten in RIPE, daarna ontstonden er uitwisselingen waarop blokken adressen werden verhandeld en deals werden gesloten om deze te leasen. Geleidelijk aan begonnen telecomoperatoren internettoegangsdiensten aan te bieden met behulp van adres- en poortvertaling. Sommigen slaagden er niet in voldoende adressen te bemachtigen om elke abonnee een “wit” adres te geven, terwijl anderen geld begonnen te besparen door te weigeren adressen op de secundaire markt te kopen. Fabrikanten van netwerkapparatuur steunden dit idee omdat deze functionaliteit vereist meestal extra uitbreidingsmodules of licenties. In de MX-routers van Juniper (behalve de nieuwste MX104 en MX204) kunt u NAPT bijvoorbeeld uitvoeren op een afzonderlijke MS-MIC-servicekaart, vereist Cisco ASR1k een CGN-licentie, Cisco ASR9k vereist een afzonderlijke A9K-ISM-100-module en een A9K-CGN-licentie -LIC voor hem. Over het algemeen kost het plezier veel geld.

IPTables

De taak van het uitvoeren van NAT vereist geen gespecialiseerde computerbronnen; deze kan worden opgelost door processors voor algemeen gebruik, die bijvoorbeeld in elke thuisrouter worden geïnstalleerd. Op de schaal van een telecomoperator kan dit probleem worden opgelost met behulp van standaardservers waarop FreeBSD (ipfw/pf) of GNU/Linux (iptables) draaien. We zullen FreeBSD niet overwegen, omdat... Ik ben al een hele tijd geleden gestopt met het gebruik van dit besturingssysteem, dus we houden het bij GNU/Linux.

Het inschakelen van adresvertaling is helemaal niet moeilijk. Eerst moet je een regel registreren in iptables in de nat-tabel:

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

Het besturingssysteem laadt de nf_conntrack-module, die alle actieve verbindingen controleert en de nodige conversies uitvoert. Er zijn hier verschillende subtiliteiten. Ten eerste, omdat we het hebben over NAT op de schaal van een telecomoperator, is het noodzakelijk om de time-outs aan te passen, omdat met standaardwaarden de omvang van de vertaaltabel snel zal uitgroeien tot catastrofale waarden. Hieronder ziet u een voorbeeld van de instellingen die ik op mijn servers heb gebruikt:

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

En ten tweede, aangezien de standaardgrootte van de vertaaltabel niet is ontworpen om te werken onder de omstandigheden van een telecomoperator, moet deze worden vergroot:

net.netfilter.nf_conntrack_max = 3145728

Het is ook nodig om het aantal buckets te vergroten voor de hashtabel waarin alle uitzendingen worden opgeslagen (dit is een optie in de nf_conntrack-module):

options nf_conntrack hashsize=1572864

Na deze eenvoudige manipulaties wordt een volledig werkend ontwerp verkregen dat een groot aantal klantadressen kan vertalen naar een pool van externe adressen. De prestaties van deze oplossing laten echter veel te wensen over. Bij mijn eerste pogingen om GNU/Linux voor NAT te gebruiken (circa 2013), kon ik prestaties behalen van ongeveer 7 Gbit/s bij 0.8 Mpps per server (Xeon E5-1650v2). Sinds die tijd zijn er veel verschillende optimalisaties doorgevoerd in de GNU/Linux-kernelnetwerkstack, de prestaties van één server op dezelfde hardware zijn toegenomen tot bijna 18-19 Gbit/s bij 1.8-1.9 Mpps (dit waren de maximale waarden) , maar de vraag naar verkeersvolume, verwerkt door één server, groeide veel sneller. Als gevolg hiervan werden er schema's ontwikkeld om de belasting op verschillende servers te verdelen, maar dit alles verhoogde de complexiteit van het opzetten, onderhouden en onderhouden van de kwaliteit van de geleverde diensten.

NFT-tabellen

Tegenwoordig is een modieuze trend in software “shifting bags” het gebruik van DPDK en XDP. Er zijn veel artikelen over dit onderwerp geschreven, er zijn veel verschillende toespraken gehouden en er verschijnen commerciële producten (bijvoorbeeld SKAT van VasExperts). Maar gezien de beperkte programmeermiddelen van telecomoperatoren is het behoorlijk problematisch om zelf een “product” te creëren dat op deze raamwerken is gebaseerd. Het zal in de toekomst veel moeilijker zijn om een ​​dergelijke oplossing te gebruiken; er zullen met name diagnostische hulpmiddelen moeten worden ontwikkeld. Standaard tcpdump met DPDK zal bijvoorbeeld niet zomaar werken, en het zal geen pakketten “zien” die met behulp van XDP naar de draden worden teruggestuurd. Te midden van al het gepraat over nieuwe technologieën voor het doorsturen van pakketten naar de gebruikersruimte, bleven ze onopgemerkt rapporten и Artikel Pablo Neira Ayuso, iptables-onderhouder, over de ontwikkeling van flow-offloading in nftables. Laten we dit mechanisme eens nader bekijken.

Het hoofdidee is dat als de router pakketten van één sessie in beide richtingen van de stroom doorgeeft (TCP-sessie ging naar de status ESTABLISHED), het niet nodig is om volgende pakketten van deze sessie door alle firewallregels te laten gaan, omdat al deze controles eindigen nog steeds als het pakket verder naar de routering wordt overgebracht. En we hoeven eigenlijk geen route te selecteren: we weten al naar welke interface en naar welke host we pakketten moeten sturen binnen deze sessie. Het enige dat overblijft is deze informatie op te slaan en te gebruiken voor routering in een vroeg stadium van de pakketverwerking. Bij het uitvoeren van NAT is het noodzakelijk om bovendien informatie op te slaan over wijzigingen in adressen en poorten, vertaald door de nf_conntrack-module. Ja natuurlijk werken in dit geval diverse politiemensen en andere informatie- en statistische regels in iptables niet meer, maar in het kader van de taak van een aparte staande NAT of bijvoorbeeld een grens is dit niet zo belangrijk, omdat de diensten zijn verdeeld over apparaten.

Configuratie

Om deze functie te gebruiken hebben we nodig:

  • Gebruik een nieuwe kernel. Ondanks het feit dat de functionaliteit zelf in kernel 4.16 verscheen, was deze lange tijd erg “ruw” en veroorzaakte regelmatig kernelpaniek. Alles stabiliseerde zich rond december 2019, toen LTS-kernels 4.19.90 en 5.4.5 werden uitgebracht.
  • Herschrijf iptables-regels in nftables-formaat met behulp van een vrij recente versie van nftables. Werkt precies in versie 0.9.0

Als alles in principe duidelijk is met het eerste punt, is het belangrijkste om niet te vergeten de module op te nemen in de configuratie tijdens de montage (CONFIG_NFT_FLOW_OFFLOAD=m), dan vereist het tweede punt uitleg. nftables-regels worden compleet anders beschreven dan in iptables. Документация onthult bijna alle punten, er zijn ook bijzondere converters regels van iptables tot nftables. Daarom zal ik alleen een voorbeeld geven van het instellen van NAT en flow-offload. Een kleine legende bijvoorbeeld: , - dit zijn de netwerkinterfaces waar het verkeer doorheen gaat; in werkelijkheid kunnen het er meer dan twee zijn. , — het begin- en eindadres van de reeks “witte” adressen.

NAT-configuratie is heel eenvoudig:

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

Bij flow offload is het iets ingewikkelder, maar heel begrijpelijk:

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

Dat is eigenlijk de hele opzet. Nu valt al het TCP/UDP-verkeer in de fastnat-tabel en wordt het veel sneller verwerkt.

Bevindingen

Om duidelijk te maken hoe “veel sneller” dit is, zal ik een screenshot bijvoegen van de belasting op twee echte servers, met dezelfde hardware (Xeon E5-1650v2), identiek geconfigureerd, met dezelfde Linux-kernel, maar met NAT in iptables (NAT4) en in nftables (NAT5).

Snelle routering en NAT in Linux

Er is geen grafiek met pakketten per seconde in de schermafbeelding, maar in het belastingsprofiel van deze servers ligt de gemiddelde pakketgrootte rond de 800 bytes, dus de waarden lopen op tot 1.5 Mpps. Zoals je kunt zien, heeft de server met nftables een enorme prestatiereserve. Momenteel verwerkt deze server tot 30Gbit/s bij 3Mpps en is duidelijk in staat om te voldoen aan de fysieke netwerkbeperking van 40Gbps, terwijl hij over vrije CPU-bronnen beschikt.

Ik hoop dat dit materiaal nuttig zal zijn voor netwerkingenieurs die de prestaties van hun servers proberen te verbeteren.

Bron: www.habr.com

Voeg een reactie