To je pravda, to isté povieme dnes bohu šifrovania.
Tu sa budeme baviť o nešifrovanom IPv4 tuneli, nie však o „teplej lampe“, ale o modernej „LED“. A blikajú tu aj raw sockety a pracuje sa s paketmi v užívateľskom priestore.
Existuje N tunelovacích protokolov pre každý vkus a farbu:
Som ale programátor, takže N zvýšim len o zlomok a vývoj skutočných protokolov nechám na vývojárov z Kommersantu.
V jednom nenarodenom projektTo, čo teraz robím, je osloviť hostiteľov za NAT zvonku. Pomocou protokolov s kryptografiou pre dospelých som sa nemohol zbaviť pocitu, že je to ako strieľať vrabce z dela. Pretože tunel sa pouziva z vacsej casti len na vysekanie dier v NAT-e, interna komunikacia je vacsinou tiez sifrovana, ale aj tak sa topia v HTTPS.
Počas skúmania rôznych tunelovacích protokolov sa pozornosť môjho vnútorného perfekcionistu znova a znova upútala na IPIP kvôli jeho minimálnej réžii. Má však jeden a pol významných nevýhod pre moje úlohy:
vyžaduje verejné IP adresy na oboch stranách,
a žiadne overenie pre vás.
Preto bol perfekcionista zahnaný späť do temného kúta lebky, alebo kamkoľvek si tam sadne.
A potom jedného dňa, pri čítaní článkov o natívne podporované tunely v Linuxe som narazil na FOU (Foo-over-UDP), t.j. čokoľvek, zabalené v UDP. Zatiaľ sú podporované iba IPIP a GUE (Generic UDP Encapsulation).
„Tu je strieborná guľka! Stačí mi jednoduchý IPIP.“ - Myslel som.
V skutočnosti sa ukázalo, že guľka nie je úplne strieborná. Zapuzdrenie v UDP rieši prvý problém – ku klientom za NAT sa môžete pripojiť zvonku pomocou vopred vytvoreného spojenia, ale tu sa polovica ďalšej nevýhody IPIP rozkvitá v novom svetle – ktokoľvek zo súkromnej siete sa môže schovať za viditeľné verejná IP a klientsky port (v čistom IPIP tento problém neexistuje).
Na vyriešenie tohto jeden a pol problému sa zrodil nástroj ipipou. Implementuje podomácky vytvorený mechanizmus na autentifikáciu vzdialeného hostiteľa, bez narušenia prevádzky FOU jadra, ktorý bude rýchlo a efektívne spracovávať pakety v priestore jadra.
Nepotrebujeme váš skript!
Ok, ak poznáte verejný port a IP klienta (napríklad všetci za ním nikam nechodia, NAT sa snaží mapovať porty 1 v 1), môžete vytvoriť tunel IPIP-over-FOU pomocou nasledujúce príkazy bez akýchkoľvek skriptov.
na serveri:
# Подгрузить модуль ядра FOU
modprobe fou
# Создать IPIP туннель с инкапсуляцией в FOU.
# Модуль ipip подгрузится автоматически.
ip link add name ipipou0 type ipip
remote 198.51.100.2 local 203.0.113.1
encap fou encap-sport 10000 encap-dport 20001
mode ipip dev eth0
# Добавить порт на котором будет слушать FOU для этого туннеля
ip fou add port 10000 ipproto 4 local 203.0.113.1 dev eth0
# Назначить IP адрес туннелю
ip address add 172.28.0.0 peer 172.28.0.1 dev ipipou0
# Поднять туннель
ip link set ipipou0 up
u klienta:
modprobe fou
ip link add name ipipou1 type ipip
remote 203.0.113.1 local 192.168.0.2
encap fou encap-sport 10001 encap-dport 10000 encap-csum
mode ipip dev eth0
# Опции local, peer, peer_port, dev могут не поддерживаться старыми ядрами, можно их опустить.
# peer и peer_port используются для создания соединения сразу при создании FOU-listener-а.
ip fou add port 10001 ipproto 4 local 192.168.0.2 peer 203.0.113.1 peer_port 10000 dev eth0
ip address add 172.28.0.1 peer 172.28.0.0 dev ipipou1
ip link set ipipou1 up
kde
ipipou* — názov sieťového rozhrania lokálneho tunela
203.0.113.1 — verejný IP server
198.51.100.2 — verejná IP klienta
192.168.0.2 — IP klienta priradená k rozhraniu eth0
10001 — miestny klientsky port pre FOU
20001 — verejný klientsky port pre FOU
10000 — verejný port servera pre FOU
encap-csum — možnosť pridať kontrolný súčet UDP k zapuzdreným paketom UDP; možno nahradiť noencap-csumNehovoriac o tom, že integrita je už riadená vonkajšou vrstvou zapuzdrenia (keď je paket vo vnútri tunela)
eth0 — lokálne rozhranie, ku ktorému bude pripojený tunel ipip
172.28.0.1 — IP rozhrania klientskeho tunela (súkromné)
172.28.0.0 — Rozhranie servera IP tunela (súkromné)
Kým bude pripojenie UDP živé, tunel bude fungovať, ale ak sa pokazí, budete mať šťastie - ak IP: port klienta zostane rovnaký - bude žiť, ak sa zmenia - preruší sa.
Najjednoduchší spôsob, ako vrátiť všetko späť, je uvoľniť moduly jadra: modprobe -r fou ipip
Aj keď sa autentifikácia nevyžaduje, verejná IP a port klienta nie sú vždy známe a často sú nepredvídateľné alebo premenlivé (v závislosti od typu NAT). Ak vynecháte encap-dport na strane servera tunel nebude fungovať, nie je dosť inteligentný na to, aby zabral port vzdialeného pripojenia. V tomto prípade môže pomôcť aj ipipou, prípadne vám môže pomôcť WireGuard a jemu podobné.
Ako to funguje?
Klient (ktorý je zvyčajne za NAT) otvorí tunel (ako vo vyššie uvedenom príklade) a odošle autentifikačný paket na server, aby nakonfiguroval tunel na svojej strane. V závislosti od nastavení to môže byť prázdny paket (len preto, aby server videl verejnú IP: port pripojenia), alebo s údajmi, podľa ktorých server dokáže identifikovať klienta. Dáta môžu byť jednoduchá prístupová fráza vo forme čistého textu (napadá ma analógia s HTTP Basic Auth) alebo špeciálne navrhnuté dáta podpísané súkromným kľúčom (podobne ako HTTP Digest Auth len silnejšie, pozri funkciu client_auth v kóde).
Na serveri (na strane s verejnou IP), keď sa ipipou spustí, vytvorí obsluhu fronty nfqueue a nakonfiguruje netfilter tak, aby sa potrebné pakety posielali tam, kde majú byť: pakety inicializujúce pripojenie k fronte nfqueue a [takmer] všetko ostatné ide priamo k poslucháčovi FOU.
Pre tých, ktorí nevedia, nfqueue (alebo NetfilterQueue) je špeciálna vec pre amatérov, ktorí nevedia, ako vyvíjať moduly jadra, ktoré vám pomocou netfilter (nftables/iptables) umožňujú presmerovať sieťové pakety do používateľského priestoru a spracovať ich tam pomocou primitívne prostriedky po ruke: upravte (voliteľné) a dajte ho späť do jadra alebo ho zahoďte.
Pre niektoré programovacie jazyky existujú väzby pre prácu s nfqueue, pre bash neboli žiadne (heh, nie je prekvapujúce), musel som použiť python: ipipou používa NetfilterQueue.
Ak výkon nie je kritický, pomocou tejto veci si môžete pomerne rýchlo a jednoducho vymyslieť vlastnú logiku pre prácu s paketmi na pomerne nízkej úrovni, napríklad vytvoriť experimentálne protokoly prenosu dát alebo trolovať lokálne a vzdialené služby s neštandardným správaním.
Raw sockety fungujú ruka v ruke s nfqueue, napríklad keď je tunel už nakonfigurovaný a FOU počúva na požadovanom porte, nebudete môcť poslať paket z rovnakého portu obvyklým spôsobom - je zaneprázdnený, ale môžete vziať a odoslať náhodne vygenerovaný paket priamo do sieťového rozhrania pomocou surového soketu, aj keď vygenerovanie takéhoto paketu bude vyžadovať trochu viac práce. Takto sa v ipipou vytvárajú pakety s autentifikáciou.
Keďže ipipou spracováva iba prvé pakety z pripojenia (a tie, ktoré stihli uniknúť do fronty pred vytvorením pripojenia), výkon takmer neutrpí.
Akonáhle server ipipou prijme overený paket, vytvorí sa tunel a všetky nasledujúce pakety v spojení už spracuje jadro obchádzajúce nfqueue. Ak spojenie zlyhá, do fronty nfqueue sa v závislosti od nastavení odošle prvý paket nasledujúceho, ak nejde o paket s autentifikáciou, ale z poslednej zapamätanej IP a klientskeho portu, môže sa buď odovzdať na alebo vyradené. Ak autentifikovaný paket pochádza z novej IP a portu, tunel sa prekonfiguruje tak, aby ich používal.
Bežný IPIP-over-FOU má pri práci s NAT ešte jeden problém - nie je možné vytvoriť dva IPIP tunely zapuzdrené v UDP s rovnakou IP, pretože moduly FOU a IPIP sú od seba dosť izolované. Tie. dvojica klientov za rovnakou verejnou IP sa nebude môcť týmto spôsobom súčasne pripojiť k rovnakému serveru. Nabudúce, možná, bude sa to riešiť na úrovni jadra, ale nie je to isté. Medzitým sa problémy s NATom dajú vyriešiť NATom - ak sa stane, že pár IP adries je už obsadených iným tunelom, ipipou urobí NAT z verejnej na alternatívnu súkromnú IP, voila! - môžete vytvárať tunely, kým sa neminú porty.
Pretože Nie všetky pakety v spojení sú podpísané, potom je táto jednoduchá ochrana zraniteľná voči MITM, takže ak na ceste medzi klientom a serverom číha zloduch, ktorý môže načúvať prevádzke a manipulovať s ňou, môže presmerovať overené pakety cez inú adresu a vytvorte tunel z nedôveryhodného hostiteľa.
Ak má niekto nápady, ako to napraviť a zároveň ponechať väčšinu návštevnosti v jadre, neváhajte sa ozvať.
Mimochodom, zapuzdrenie v UDP sa osvedčilo veľmi dobre. V porovnaní so zapuzdrením cez IP je oveľa stabilnejšia a často rýchlejšia napriek dodatočnej réžii hlavičky UDP. Je to spôsobené tým, že väčšina hostiteľov na internete funguje dobre iba s tromi najpopulárnejšími protokolmi: TCP, UDP, ICMP. Hmotná časť dokáže všetko ostatné úplne vyhodiť, prípadne spracovať pomalšie, pretože je optimalizovaná len pre tieto tri.
Napríklad to je dôvod, prečo bol QUICK, na ktorom je založený HTTP/3, vytvorený nad UDP, a nie nad IP.
No dosť slov, je čas vidieť, ako to funguje v „reálnom svete“.
Bitka
Používa sa na napodobňovanie skutočného sveta iperf3. Pokiaľ ide o mieru blízkosti k realite, je to približne rovnaké ako emulácia skutočného sveta v Minecrafte, ale zatiaľ to bude stačiť.
Účastníci súťaže:
referenčný hlavný kanál
hrdinom tohto článku je ipipou
OpenVPN s autentifikáciou, ale bez šifrovania
OpenVPN v režime all-inclusive
WireGuard bez predzdieľaného kľúča, s MTU=1440 (od iba IPv4)
Technické údaje pre geekov Metriky sa získavajú pomocou nasledujúcich príkazov:
u klienta:
UDP
CPULOG=NAME.udp.cpu.log; sar 10 6 >"$CPULOG" & iperf3 -c SERVER_IP -4 -t 60 -f m -i 10 -B LOCAL_IP -P 2 -u -b 12M; tail -1 "$CPULOG"
# Где "-b 12M" это пропускная способность основного канала, делённая на число потоков "-P", чтобы лишние пакеты не плодить и не портить производительность.