S postupným vyčerpaním adries IPv4 sa mnohí operátori stretli s potrebou organizovať prístup svojich klientov na sieť prostredníctvom prekladov adries. V tomto článku vám ukážem, ako dosiahnuť výkon na úrovni Carrier Grade NAT na bežných serveroch.
Trochu histórie
Téma vyčerpania adresného priestoru IPv4 už nie je nová. V istom momente sa v RIPE objavili čakacie zoznamy, potom vznikli burzy, na ktorých sa obchodovalo s blokmi adries a uzatvárali sa zmluvy o ich prenájme. Postupne operátori začali poskytovať služby prístupu k internetu prostredníctvom prekladov adries a portov. Niektorí nestihli získať dostatok adries na to, aby mohli poskytnúť „bielu“ adresu každému predplatiteľovi, iní sa rozhodli šetriť peniaze a odstúpili od nákupu adries na sekundárnom trhu. Výrobcovia sieťového zariadenia podporili túto myšlienku, pretože táto funkcia zvyčajne vyžaduje dodatočné rozširujúce moduly alebo licencie. Napríklad spoločnosť Juniper v rade svojich smerovačov MX (okrem posledných MX104 a MX204) umožňuje vykonávať NAPT na samostatnej servisnej karte MS-MIC, na Cisco ASR1k je potrebná licencia CGN, na Cisco ASR9k – samostatný modul A9K-ISM-100 a licencia A9K-CGN-LIC k nemu. Všeobecne povedané, táto služba nie je lacná.
IPTables
Úloha vykonávania NAT si nevyžaduje špecializované výpočtové zdroje, dá sa uskutočniť na procesoroch všeobecného určenia, ktoré sú nainštalované, napríklad v akejkoľvek domácej smerovači. Na úrovni operátora túto úlohu možno riešiť pomocou bežných serverov na báze FreeBSD (ipfw/pf) alebo GNU/Linux (iptables). FreeBSD sa nebudeme zaoberať, pretože som sa už dávno vzdal jeho používania, tak sa zameriame na GNU/Linux.
Zapojiť preklad adries nie je vôbec zložité. Najprv je potrebné zapísať pravidlo do iptables v nat tabuľke:
iptables -t nat -A POSTROUTING -s 100.64.0.0/10 -j SNAT --to - --persistent
Operačný systém načíta modul nf_conntrack, ktorý bude sledovať všetky aktívne pripojenia a vykonávať potrebné transformácie. Tu je niekoľko nuáns. Po prvé, keďže ide o NAT na úrovni operátora, je potrebné upraviť timeouty, pretože s predvolenými hodnotami sa veľkosť prekladovej tabuľky rýchlo zvýši na katastrofálne hodnoty. Nižšie je uvedený príklad nastavení, ktoré som použil na svojich serveroch:
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
A po druhé, keďže predvolená veľkosť prekladovej tabuľky nie je určená na prácu v podmienkach operátora, je potrebné ju zvýšiť:
net.netfilter.nf_conntrack_max = 3145728
Rovnako je potrebné zvýšiť aj počet „buckets“ pre hashovaciu tabuľku, ktorá uchováva všetky preklady (toto je možnosť modulu nf_conntrack):
options nf_conntrack hashsize=1572864
Po týchto jednoduchých manipuláciách vznikne plne funkčná konštrukcia, ktorá dokáže prekladať veľké množstvo klientskych adries na vonkajší pool. Avšak výkonnosť tohto riešenia má svoje rezervy. V svojich prvých pokusoch o použitie GNU/Linux pre NAT (približne v roku 2013) som dokázal dosiahnuť výkon približne 7 Gbit/s pri 0.8 Mpps na jeden server (Xeon E5-1650v2). Od tej doby bolo v sieťovom stacku jadra GNU/Linux urobených množstvo rôznych optimalizácií, výkon jedného servera na tom istom hardvéri vzrástol prakticky na 18-19 Gbit/s pri 1.8-1.9 Mpps (to boli limitné hodnoty), ale potreba objemu prevádzky spracovanej jedným serverom rástla oveľa rýchlejšie. Nakoniec boli vyvinuté schémy vyvažovania zaťaženia medzi rôznymi servermi, ale to všetko zvýšilo zložitosti nastavenia, údržby a zachovania kvality poskytovaných služieb.
NFTables
Aktuálnym trendom v oblasti programovania „presúvania paketov“ je využitie DPDK a XDP. O tejto téme bolo napísaných množstvo článkov, uskutočnilo sa mnoho rôznych prezentácií a objavili sa komerčné produkty (napríklad SKAT od VasExperts). Ale pri obmedzených zdrojoch programátorov u poskytovateľov rádiovej komunikácie je ťažké vyvinúť si vlastný „výrobok“ na báze týchto frameworkov. V ďalšej prevádzke takého riešenia to bude oveľa zložitejšie, najmä vzhľadom na potrebu vyvinúť diagnostické nástroje. Napríklad, štandardný tcpdump s DPDK sa len tak nedokáže spustiť, a ani pakety odoslané späť na drôtoch pomocou XDP nevidí. Na pozadí všetkých diskusií o nových technológiách presmerovania paketov do užívateľského priestoru ostali bez povšimnutia a Pablo Neira Ayuso, správca iptables, hovorí o vývoji flow offloading v nftables. Poďme si tento mechanizmus podrobnejšie preštudovať.
Základná myšlienka spočíva v tom, že ak router prepušťa pakety jednej relácie oboma smermi toku (TCP relácia prešla do stavu ESTABLISHED), nie je potrebné premietať nasledujúce pakety tejto relácie cez všetky pravidlá firewallu, pretože všetky tieto kontroly a tak či tak skončia odoslaním paketu ďalej do routovania. A vlastne ani nie je potrebné vykonávať výber trasy – už vieme, do ktorého rozhrania a akému hostiteľovi je potrebné zasielať pakety v rámci tejto relácie. Ostáva iba uložiť túto informáciu a využiť ju na routovanie v raných fázach spracovania paketu. Pri vykonávaní NAT je potrebné navyše uložiť informácie o zmenách adries a portov, ktoré boli transformované modulom nf_conntrack. Áno, samozrejme, v takomto prípade prestávajú fungovať rôzne policery a iné informačno-štatistické pravidlá v iptables, ale v rámci úlohy samostatného NAT alebo napríklad brány – to nie je také dôležité, pretože služby sú distribuované medzi zariadeniami.
Konfigurácia
Aby sme mohli využiť túto funkciu, musíme:
- Použiť najnovšie jadro. Napriek tomu, že samotná funkcionalita sa objavila už v jadre 4.16, bola dosť dlhú dobu veľmi „nahrubo spracovaná“ a pravidelne spôsobovala kernel panic. Stabilizovalo sa to približne v decembri 2019, keď vyšli LTS jadrá 4.19.90 a 5.4.5.
- Prepísať pravidlá iptables do formátu nftables pomocou pomerne novej verzie nftables. Presne funguje vo verzii 0.9.0
Ak je prvý bod v podstate jasný, hlavným je nezabudnúť zahrnúť modul do konfigurácie pri kompilácii (CONFIG_NFT_FLOW_OFFLOAD=m), druhý bod si vyžaduje objasnenie. Pravidlá nftables sú popísané úplne inak ako v iptables. pokryje prakticky všetky aspekty, existujú aj špeciálne pravidiel z iptables do nftables. Preto uvádzam len príklad konfigurácie NAT a flow offload. Malá legenda pre príklad: <i_if>, <o_if> — to sú sieťové rozhrania, cez ktoré prechádza prevádzka, skutočne ich môže byť viac ako dve. <pool_addr_start>, <pool_addr_end> — počiatočná a konečná adresa rozsahu „bielych“ adries.
Konfigurácia NAT je veľmi jednoduchá:
#! /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
}
}
S flow offload je to trochu zložitejšie, ale celkom zrozumiteľné:
#! /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;
}
}
Tu je vlastne celá konfigurácia. Teraz bude celý TCP/UDP prenos prechádzať do tabuľky fastnat a spracovávať sa oveľa rýchlejšie.
Výsledky
Aby bolo jasné, ako veľmi je to „oveľa rýchlejšie“, priložím snímku záťaže dvoch reálnych serverov, s rovnakou konfiguráciou (Xeon E5-1650v2), rovnako nastavených, používajúcich ten istý Linux kernel, ale vykonávajúcich NAT v iptables (NAT4) a v nftables (NAT5).

Na snímke nie je graf paketov za sekundu, ale v profile zaťaženia týchto serverov je priemerná veľkosť paketu okolo 800 bajtov, preto hodnoty dosahujú až 1.5Mpps. Ako vidno, výkonový rezerv servera s nftables je obrovský. V súčasnosti tento server spracováva až 30Gbit/s pri 3Mpps a jasne môže naraziť na fyzické obmedzenie siete 40Gbps, pričom má voľné CPU zdroje.
Dúfam, že tento materiál bude užitočný sieťovým inžinierom, ktorí sa snažia zlepšiť výkon svojich serverov.
Zdroj: habr.com
