Hurtig routing og NAT i Linux

Efterhånden som IPv4-adresser bliver udtømte, står mange teleoperatører over for behovet for at give deres kunder netværksadgang ved hjælp af adresseoversættelse. I denne artikel vil jeg fortælle dig, hvordan du kan få Carrier Grade NAT-ydelse på råvareservere.

Lidt historie

Emnet om udmattelse af IPv4-adresserum er ikke længere nyt. På et tidspunkt dukkede ventelister op i RIPE, så opstod der børser, hvor adresseblokke blev handlet, og der blev indgået aftaler om leasing af dem. Efterhånden begyndte teleoperatører at levere internetadgangstjenester ved hjælp af adresse- og portoversættelse. Nogle formåede ikke at få nok adresser til at udstede en "hvid" adresse til hver abonnent, mens andre begyndte at spare penge ved at nægte at købe adresser på det sekundære marked. Producenter af netværksudstyr støttede denne idé, fordi denne funktionalitet kræver normalt yderligere udvidelsesmoduler eller licenser. For eksempel kan du i Junipers serie af MX-routere (undtagen de nyeste MX104 og MX204) udføre NAPT på et separat MS-MIC servicekort, Cisco ASR1k kræver en CGN-licens, Cisco ASR9k kræver et separat A9K-ISM-100 modul og en A9K-CGN licens -LIC til ham. Generelt koster fornøjelsen mange penge.

IPTables

Opgaven med at udføre NAT kræver ikke specialiserede computerressourcer; den kan løses af processorer til generelle formål, som for eksempel er installeret i enhver hjemmerouter. På størrelse med en teleoperatør kan dette problem løses ved hjælp af vareservere, der kører FreeBSD (ipfw/pf) eller GNU/Linux (iptables). Vi vil ikke overveje FreeBSD, fordi... Jeg holdt op med at bruge dette OS for ganske lang tid siden, så vi holder os til GNU/Linux.

Det er slet ikke svært at aktivere adresseoversættelse. Først skal du registrere en regel i iptables i nat-tabellen:

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

Operativsystemet indlæser nf_conntrack-modulet, som overvåger alle aktive forbindelser og udfører de nødvendige konverteringer. Der er flere finesser her. For det første, da vi taler om NAT på skalaen af ​​en teleoperatør, er det nødvendigt at justere timeouts, for med standardværdier vil størrelsen af ​​oversættelsestabellen hurtigt vokse til katastrofale værdier. Nedenfor er et eksempel på de indstillinger, jeg brugte på mine servere:

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

Og for det andet, da standardstørrelsen af ​​oversættelsestabellen ikke er designet til at fungere under en teleoperatørs betingelser, skal den øges:

net.netfilter.nf_conntrack_max = 3145728

Det er også nødvendigt at øge antallet af buckets til hash-tabellen, der gemmer alle udsendelser (dette er en mulighed i nf_conntrack-modulet):

options nf_conntrack hashsize=1572864

Efter disse simple manipulationer opnås et fuldstændigt fungerende design, der kan oversætte et stort antal klientadresser til en pulje af eksterne. Denne løsnings ydeevne lader dog meget tilbage at ønske. I mine første forsøg på at bruge GNU/Linux til NAT (cirka 2013), var jeg i stand til at få en ydeevne på omkring 7Gbit/s ved 0.8Mpps pr. server (Xeon E5-1650v2). Siden dengang er der foretaget mange forskellige optimeringer i GNU/Linux-kernenetværksstakken, ydelsen af ​​en server på den samme hardware er steget til næsten 18-19 Gbit/s ved 1.8-1.9 Mpps (dette var de maksimale værdier) , men efterspørgslen efter trafikmængde, behandlet af én server, voksede meget hurtigere. Som et resultat blev der udviklet ordninger til at afbalancere belastningen på forskellige servere, men alt dette øgede kompleksiteten i at opsætte, vedligeholde og vedligeholde kvaliteten af ​​de leverede tjenester.

NFT-tabeller

I dag er en fashionabel trend inden for software "shifting bags" brugen af ​​DPDK og XDP. Der er skrevet rigtig mange artikler om dette emne, der er holdt mange forskellige taler, og der kommer kommercielle produkter (f.eks. SKAT fra VasExperts). Men i betragtning af teleoperatørernes begrænsede programmeringsressourcer, er det ret problematisk at skabe ethvert "produkt" baseret på disse rammer på egen hånd. Det vil være meget vanskeligere at betjene en sådan løsning i fremtiden, især diagnostiske værktøjer skal udvikles. For eksempel vil standard tcpdump med DPDK ikke fungere bare sådan, og den vil ikke "se" pakker sendt tilbage til ledningerne ved hjælp af XDP. Midt i al snakken om nye teknologier til udsendelse af pakkevideresendelse til brugerområdet, gik de ubemærket hen rapporter и Artikel Pablo Neira Ayuso, iptables-vedligeholder, om udviklingen af ​​flow-offloading i nftables. Lad os se nærmere på denne mekanisme.

Hovedideen er, at hvis routeren sendte pakker fra en session i begge retninger af flowet (TCP-sessionen gik i ETABLISHED-tilstand), så er der ingen grund til at sende efterfølgende pakker af denne session gennem alle firewall-regler, fordi alle disse kontroller vil stadig ende med, at pakken overføres videre til routingen. Og vi behøver faktisk ikke at vælge en rute - vi ved allerede, til hvilken grænseflade og til hvilken vært, vi skal sende pakker i denne session. Det eneste, der er tilbage, er at gemme disse oplysninger og bruge dem til routing på et tidligt stadium af pakkebehandlingen. Når du udfører NAT, er det nødvendigt yderligere at gemme information om ændringer i adresser og porte oversat af nf_conntrack-modulet. Ja, selvfølgelig, i dette tilfælde holder forskellige politifolk og andre informations- og statistiske regler i iptables op med at virke, men inden for rammerne af opgaven med en separat stående NAT eller for eksempel en grænse, er dette ikke så vigtigt, fordi tjenesterne er fordelt på tværs af enheder.

Konfiguration

For at bruge denne funktion har vi brug for:

  • Brug en frisk kerne. På trods af at selve funktionaliteten dukkede op i kerne 4.16, var den i ret lang tid meget "rå" og forårsagede regelmæssigt kernepanik. Alt stabiliserede sig omkring december 2019, hvor LTS-kernerne 4.19.90 og 5.4.5 blev frigivet.
  • Omskriv iptables-regler i nftables-format ved hjælp af en ret nyere version af nftables. Virker nøjagtigt i version 0.9.0

Hvis alt i princippet er klart med det første punkt, er det vigtigste ikke at glemme at inkludere modulet i konfigurationen under montering (CONFIG_NFT_FLOW_OFFLOAD=m), så kræver det andet punkt forklaring. nftables regler er beskrevet helt anderledes end i iptables. Records afslører næsten alle punkter, der er også særlige konvertere regler fra iptables til nftables. Derfor vil jeg kun give et eksempel på opsætning af NAT og flow offload. En lille legende for eksempel: , - det er de netværksgrænseflader, som trafikken passerer igennem; i virkeligheden kan der være mere end to af dem. , — start- og slutadressen for rækken af ​​"hvide" adresser.

NAT-konfigurationen er meget enkel:

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

Med flow offload er det lidt mere kompliceret, men ret forståeligt:

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

Det er faktisk hele setuppet. Nu vil al TCP/UDP-trafik falde ind i fastnat-tabellen og blive behandlet meget hurtigere.

Fund

For at gøre det klart, hvor "meget hurtigere" dette er, vil jeg vedhæfte et skærmbillede af belastningen på to rigtige servere, med den samme hardware (Xeon E5-1650v2), identisk konfigureret, ved hjælp af den samme Linux-kerne, men udfører NAT i iptables (NAT4) og i nftables (NAT5).

Hurtig routing og NAT i Linux

Der er ingen graf over pakker per sekund i skærmbilledet, men i belastningsprofilen for disse servere er den gennemsnitlige pakkestørrelse omkring 800 bytes, så værdierne når op til 1.5Mpps. Som du kan se, har serveren med nftables en enorm ydeevnereserve. I øjeblikket behandler denne server op til 30Gbit/s ved 3Mpps og er klart i stand til at opfylde den fysiske netværksbegrænsning på 40Gbps, mens den har frie CPU-ressourcer.

Jeg håber, at dette materiale vil være nyttigt for netværksingeniører, der forsøger at forbedre ydeevnen på deres servere.

Kilde: www.habr.com

Tilføj en kommentar