I takt med att IPv4-adresserna tar slut har mÄnga teleoperatörer stött pÄ behovet av att organisera sina kunders Ätkomst till nÀtet genom adressöversÀttning. I den hÀr artikeln kommer jag att gÄ igenom hur man kan uppnÄ Carrier Grade NAT-prestanda pÄ commodity-servrar.
Lite historia
Ămnet kring uttömning av IPv4-adressutrymmet Ă€r inte nytt. Vid nĂ„gon tidpunkt uppstod det köer i RIPE, och sedan dök det upp börser dĂ€r man handlade med adressblock och ingick avtal om deras uthyrning. Gradvis började teleoperatörer erbjuda internetĂ„tkomst genom adress- och portöversĂ€ttning. Vissa hann inte fĂ„ tillrĂ€ckligt med adresser för att kunna ge varje abonnent en "vit" adress, medan andra började spara pengar genom att avstĂ„ frĂ„n att köpa adresser pĂ„ sekundĂ€rmarknaden. Tillverkare av nĂ€tverksutrustning stödde denna idĂ©, eftersom denna funktionalitet vanligtvis krĂ€ver ytterligare expansionsmoduler eller licenser. Till exempel, hos Juniper i MX-serien av routrar (förutom de senaste MX104 och MX204) kan NAPT utföras pĂ„ ett separat servicekort MS-MIC, pĂ„ Cisco ASR1k krĂ€vs en licens CGN, och pĂ„ Cisco ASR9k en separat modul A9K-ISM-100 samt licens A9K-CGN-LIC till denna. Sammanfattningsvis kostar det en hel del.
IPTables
Att utföra NAT krÀver inga specialiserade berÀkningsresurser; det kan hanteras av allmÀnna processorer som finns i exempelvis vilken hemrouter som helst. PÄ teleoperatörsnivÄ kan denna uppgift lösas med commodity-servrar som kör FreeBSD (ipfw/pf) eller GNU/Linux (iptables). Vi kommer inte att behandla FreeBSD hÀr, eftersom jag för lÀnge sedan slutade anvÀnda detta operativsystem, sÄ vi fokuserar pÄ GNU/Linux.
Att aktivera adressöversÀttning Àr inte svÄrt. Först mÄste du skriva in en regel i iptables i nat-tabellen:
iptables -t nat -A POSTROUTING -s 100.64.0.0/10 -j SNAT --to - --persistent
Operativsystemet kommer att ladda modulen nf_conntrack, som kommer att övervaka alla aktiva anslutningar och utföra nödvÀndiga omvandlingar. Det finns nÄgra subtiliteter hÀr. För det första, eftersom vi pratar om NAT pÄ operatörsnivÄ, mÄste timeout-vÀrden justeras, eftersom standardvÀrdena gör att storleken pÄ översÀttningstabellen snabbt kan vÀxa till katastrofala dimensioner. HÀr Àr ett exempel pÄ instÀllningar som jag anvÀnde pÄ mina servrar:
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
Och för det andra, eftersom standardstorleken pÄ översÀttningstabellen inte Àr avsedd för anvÀndning pÄ operatörsnivÄ, behöver den ökas:
net.netfilter.nf_conntrack_max = 3145728
Det Àr ocksÄ nödvÀndigt att öka antalet buckets för hash-tabellen som lagrar alla översÀttningar (detta Àr en alternativmodul för nf_conntrack):
options nf_conntrack hashsize=1572864
Efter dessa enkla manipuleringar fÄr man en helt fungerande konstruktion som kan översÀtta ett stort antal klientadresser till en pool av externa. Men prestandan hos den hÀr lösningen lÀmnar mycket att önska. Under mina första försök med att anvÀnda GNU/Linux för NAT (ungefÀr 2013) fick jag en prestanda pÄ cirka 7 Gbit/s vid 0,8 Mpps pÄ en server (Xeon E5-1650v2). Sedan dess har mÄnga olika optimeringar gjorts i nÀtverksstacken av kÀrnan GNU/Linux, och prestandan pÄ en server med samma hÄrdvara har vuxit nÀstan till 18-19 Gbit/s vid 1,8-1,9 Mpps (detta var grÀnsvÀrden), men behovet av trafikvolym som hanteras av en server har vÀxt mycket snabbare. SÄ smÄningom utvecklades scheman för lastbalansering pÄ olika servrar, men allt detta ökade komplexiteten i konfigurationen, underhÄllet och kvaliteten pÄ de tillhandahÄllna tjÀnsterna.
NFTables
Just nu Àr en modeinriktning inom programvaru "paketöverföring" anvÀndningen av DPDK och XDP. Det har skrivits mÄnga artiklar om detta Àmne, hÄllits olika presentationer, och kommersiella produkter har dykt upp (till exempel SKAT frÄn VasExperts). Men under förhÄllandena med begrÀnsade resurser hos programmerarna pÄ telekomoperatörerna Àr det ganska problematiskt att sjÀlva snickra ihop nÄgot "projekt" baserat pÄ dessa ramverk. Att driva en sÄdan lösning vidare kommer att bli mycket mer komplicerat, sÀrskilt eftersom det mÄste utvecklas diagnostikverktyg. Till exempel fungerar inte den vanliga tcpdump med DPDK sÄ bra, och paket som skickas tillbaka till kablarna med XDP kommer den inte "se". Bland alla diskussioner om nya teknologier för pakethantering i anvÀndarutrymme har man missat och Pablo Neira Ayuso, underhÄllare av iptables, om utvecklingen av flow offloading i nftables. LÄt oss granska denna mekanism nÀrmare.
HuvudidĂ©n Ă€r att om routern har slĂ€ppt igenom paket frĂ„n en session i bĂ„da riktningarna (TCP-sessionen har gĂ„tt över i tillstĂ„ndet ESTABLISHED), sĂ„ finns det ingen anledning att lĂ„ta de efterföljande paketen frĂ„n denna session passera genom alla brandvĂ€ggsregler, eftersom alla dessa kontroller Ă€ndĂ„ kommer att sluta med att paketet skickas vidare till routing. Och valet av rutt behöver egentligen inte göras â vi vet redan vilket grĂ€nssnitt och vilken vĂ€rd paketen inom denna session ska skickas till. Det Ă„terstĂ„r bara att spara denna information och anvĂ€nda den för routing i ett tidigt skede av paketbehandlingen. NĂ€r NAT genomförs mĂ„ste dessutom information om adress- och portförĂ€ndringar som omvandlats av nf_conntrack-modulen sparas. Ja, i detta fall slutar olika policys och andra informationsstatistiska regler i iptables att fungera, men inom ramen för uppgiften för en separat stĂ„ende NAT eller till exempel en border â Ă€r detta inte sĂ„ viktigt, eftersom tjĂ€nsterna Ă€r distribuerade över enheter.
Konfiguration
För att anvÀnda denna funktion behöver vi:
- AnvÀnda en ny kÀrna. Trots att funktionen först dök upp i kÀrnan 4.16, var den lÀnge ganska "omogen" och orsakade regelbundet kernel panic. Allt stabiliserades ungefÀr i december 2019, nÀr LTS-kÀrnorna 4.19.90 och 5.4.5 slÀpptes.
- Omarbetta iptables-regler till nftables-format, med en tillrÀckligt ny version av nftables. Fungerar exakt i version 0.9.0
Om det första punkten Ă€r relativt förstĂ„eligt, kom ihĂ„g att aktivera modulen i konfigurationen vid kompilering (CONFIG_NFT_FLOW_OFFLOAD=m), sĂ„ krĂ€ver den andra punkten förklaringar. nftables-regler beskrivs pĂ„ ett helt annat sĂ€tt Ă€n i iptables. tĂ€cker praktiskt taget alla aspekter, och det finns ocksĂ„ speciella av regler frĂ„n iptables till nftables. DĂ€rför kommer jag endast att ge ett exempel pĂ„ konfiguration av NAT och flow offload. En kort legend för exemplet: <i_if>, <o_if> â dessa Ă€r nĂ€tverksgrĂ€nssnitt genom vilka trafiken passerar, och det kan faktiskt finnas fler Ă€n tvĂ„. <pool_addr_start>, <pool_addr_end> â den första och sista adressen i intervallet av "vita" adresser.
NAT-konfigurationen Àr mycket 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
}
}
Flow offload Àr lite mer komplicerat, men helt förstÄ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;
}
}
Detta Àr faktiskt hela konfigurationen. Nu kommer all TCP/UDP-trafik att gÄ till tabellen fastnat och behandlas mycket snabbare.
Resultat
För att förstÄ hur mycket "mycket snabbare" det Àr, kommer jag att bifoga en skÀrmdump av belastningen pÄ tvÄ verkliga servrar, med samma hÄrdvara (Xeon E5-1650v2), lika konfigurerade, som anvÀnder samma Linux-kÀrna, men utför NAT i iptables (NAT4) respektive i nftables (NAT5).

I skÀrmdumpen finns ingen graf över paket per sekund, men i belastningsprofilen för dessa servrar Àr det genomsnittliga paketstorleken cirka 800 byte, sÄ vÀrdena nÄr upp till 1.5Mpps. Som synligt, finns det en stor prestandareserv för servern med nftables. För nÀrvarande hanterar denna server upp till 30Gbit/s vid 3Mpps och kan tydligt nÄ det fysiska nÀtverksbegrÀnsningen pÄ 40Gbps, samtidigt som CPU-resurserna fortfarande Àr lediga.
Jag hoppas att detta material kommer att vara anvÀndbart för nÀtverksingenjörer som försöker förbÀttra prestandan för sina servrar.
KĂ€lla: habr.com
