Ovdje ćemo govoriti o nešifriranom IPv4 tunelu, ali ne o “toploj lampi”, već o modernom “LED” tunelu. Ovdje također bljeskaju sirovi soketi, au tijeku je rad s paketima u korisničkom prostoru.
Postoji N protokola tuneliranja za svaki ukus i boju:
Ali ja sam programer, pa ću povećati N samo za djelić, a razvoj pravih protokola prepustiti programerima Kommersanta.
U jednom još nerođenom projektOno što sada radim jest doći do hostova iza NAT-a izvana. Koristeći za ovo protokole s kriptografijom za odrasle, nisam se mogao otresti osjećaja da je to kao pucanje vrabaca iz topa. Jer tunel se uglavnom koristi samo za bušenje rupa u NAT-e, interni promet je obično također šifriran, ali se i dalje utapaju u HTTPS.
Dok sam istraživao razne protokole za tuneliranje, pozornost mog unutarnjeg perfekcioniste uvijek je iznova privlačio IPIP zbog minimalnih troškova. Ali ima jedan i pol značajan nedostatak za moje zadatke:
zahtijeva javne IP adrese s obje strane,
i nema provjere autentičnosti za vas.
Stoga je perfekcionist stjeran natrag u mračni kut lubanje, ili gdje god on tamo sjedi.
A onda jednog dana, čitajući članke o nativno podržani tuneli u Linuxu sam naišao na FOU (Foo-over-UDP), tj. što god, umotano u UDP. Do sada su podržani samo IPIP i GUE (Generic UDP Encapsulation).
“Evo srebrnog metka! Dovoljan mi je jednostavan IPIP.” - Mislio sam.
Zapravo, pokazalo se da metak nije potpuno srebrn. Enkapsulacija u UDP rješava prvi problem - možete se spojiti na klijente iza NAT-a izvana koristeći unaprijed uspostavljenu vezu, ali ovdje polovica sljedećeg nedostatka IPIP-a procvjeta u novom svjetlu - bilo tko iz privatne mreže može se sakriti iza vidljive mreže. javni IP i port klijenta (u čistom IPIP-u ovaj problem ne postoji).
Za rješavanje ovog jednog i pol problema rođen je uslužni program ipipou. Implementira domaći mehanizam za autentifikaciju udaljenog računala, bez ometanja rada FOU kernela, koji će brzo i učinkovito obraditi pakete u kernel prostoru.
Ne treba nam tvoj scenarij!
U redu, ako znate javni port i IP klijenta (na primjer, svi iza njega ne idu nikamo, NAT pokušava mapirati portove 1-u-1), možete stvoriti IPIP-over-FOU tunel s slijedeći naredbe, bez ikakvih skripti.
na poslužitelju:
# Подгрузить модуль ядра 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
na klijentu:
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
gdje
ipipou* — naziv sučelja lokalne mreže tunela
203.0.113.1 — javni IP poslužitelj
198.51.100.2 — javni IP klijenta
192.168.0.2 — IP klijenta dodijeljen sučelju eth0
10001 — port lokalnog klijenta za FOU
20001 — javni klijentski port za FOU
10000 — port javnog poslužitelja za FOU
encap-csum — mogućnost dodavanja UDP kontrolne sume enkapsuliranim UDP paketima; može se zamijeniti sa noencap-csum, da ne spominjemo, integritet već kontrolira vanjski sloj enkapsulacije (dok je paket unutar tunela)
eth0 — lokalno sučelje na koje će ipip tunel biti vezan
172.28.0.1 — IP sučelja klijentskog tunela (privatno)
172.28.0.0 — IP tunel sučelje poslužitelja (privatno)
Sve dok je UDP veza živa, tunel će biti u ispravnom stanju, ali ako se pokvari, bit ćete sretni - ako klijentov IP: port ostane isti - živjet će, ako se promijene - pokvarit će se.
Najlakši način da sve vratite unazad je istovar modula kernela: modprobe -r fou ipip
Čak i ako provjera autentičnosti nije potrebna, klijentov javni IP i port nisu uvijek poznati i često su nepredvidivi ili promjenjivi (ovisno o vrsti NAT-a). Ako izostavite encap-dport na strani poslužitelja, tunel neće raditi, nije dovoljno pametan da preuzme priključak za udaljenu vezu. U ovom slučaju može pomoći i ipipou ili WireGuard i njemu slični.
Kako se to radi?
Klijent (koji je obično iza NAT-a) otvara tunel (kao u gornjem primjeru) i šalje paket provjere autentičnosti poslužitelju tako da on konfigurira tunel na svojoj strani. Ovisno o postavkama, to može biti prazan paket (samo da poslužitelj može vidjeti javni IP: port veze), ili s podacima po kojima poslužitelj može identificirati klijenta. Podaci mogu biti jednostavna šifra u jasnom tekstu (na pamet pada analogija s HTTP Basic Auth) ili posebno dizajnirani podaci potpisani privatnim ključem (slično HTTP Digest Authu samo jače, pogledajte funkciju client_auth u kodu).
Na poslužitelju (strana s javnom IP-om), kada se ipipou pokrene, stvara nfqueue rukovatelj redom čekanja i konfigurira netfilter tako da se potrebni paketi šalju tamo gdje bi trebali biti: paketi koji inicijaliziraju vezu s nfqueue redom čekanja i [skoro] sve ostalo ide ravno slušatelju FOU.
Za one koji nisu upućeni, nfqueue (ili NetfilterQueue) je posebna stvar za amatere koji ne znaju razvijati module kernela, koji pomoću netfiltera (nftables/iptables) omogućuje preusmjeravanje mrežnih paketa u korisnički prostor i njihovu obradu tamo pomoću primitivna sredstva pri ruci: modificirajte (opcionalno ) i vratite je jezgri ili je odbacite.
Za neke programske jezike postoje vezanja za rad s nfqueue, za bash ih nije bilo (heh, nije iznenađujuće), morao sam koristiti python: ipipou koristi NetfilterQueue.
Ako izvedba nije kritična, pomoću ove stvari možete relativno brzo i lako osmisliti vlastitu logiku za rad s paketima na prilično niskoj razini, na primjer, stvoriti eksperimentalne protokole za prijenos podataka ili kontrolirati lokalne i udaljene usluge s nestandardnim ponašanjem.
Neobrađeni soketi rade ruku pod ruku s nfqueueom, na primjer, kada je tunel već konfiguriran i FOU sluša željeni port, nećete moći poslati paket s istog porta na uobičajeni način - zauzet je, ali možete uzeti i poslati nasumično generirani paket izravno na mrežno sučelje koristeći sirovu utičnicu, iako će generiranje takvog paketa zahtijevati malo više petljanja. Ovako se kreiraju paketi s autentifikacijom u ipipou.
Budući da ipipou obrađuje samo prve pakete iz veze (i one koji su uspjeli procuriti u red prije nego što je veza uspostavljena), izvedba gotovo da ne trpi.
Čim ipipou poslužitelj primi autentificirani paket, stvara se tunel i sve sljedeće pakete u vezi već obrađuje kernel zaobilazeći nfqueue. Ako veza ne uspije, tada će prvi paket sljedećeg biti poslan u red čekanja nfqueue, ovisno o postavkama, ako to nije paket s autentifikacijom, već sa zadnje zapamćene IP adrese i porta klijenta, može se proslijediti ili na ili odbačeno. Ako autentificirani paket dolazi s novog IP-a i priključka, tunel se rekonfigurira da ih koristi.
Uobičajeni IPIP-over-FOU ima još jedan problem kada radi s NAT-om - nemoguće je stvoriti dva IPIP tunela enkapsulirana u UDP s istim IP-om, jer su FOU i IPIP moduli prilično izolirani jedan od drugog. Oni. par klijenata iza iste javne IP adrese neće se moći istovremeno spojiti na isti poslužitelj na ovaj način. U budućnosti, možda, to će se riješiti na razini kernela, ali to nije sigurno. U međuvremenu, probleme s NAT-om može riješiti NAT - ako se dogodi da je par IP adresa već zauzet drugim tunelom, ipipou će napraviti NAT s javnog na alternativni privatni IP, voila! - možete stvarati tunele dok ne ponestane portova.
Jer Nisu svi paketi u vezi potpisani, tada je ova jednostavna zaštita ranjiva na MITM, pa ako postoji zlikovac koji vreba na putu između klijenta i poslužitelja koji može slušati promet i njime manipulirati, on može preusmjeriti autentificirane pakete putem drugu adresu i stvorite tunel s nepouzdanog računala.
Ako netko ima ideje kako to popraviti, a da pritom većinu prometa ostavi u jezgri, ne ustručavajte se reći.
Usput, enkapsulacija u UDP-u se vrlo dobro pokazala. U usporedbi s enkapsulacijom preko IP-a, mnogo je stabilnija i često brža unatoč dodatnim troškovima UDP zaglavlja. To je zbog činjenice da većina hostova na Internetu dobro radi samo s tri najpopularnija protokola: TCP, UDP, ICMP. Opipljivi dio može u potpunosti odbaciti sve ostalo, ili ga obrađivati sporije, jer je optimiziran samo za ovo troje.
Na primjer, zbog toga je QUICK, na kojem se temelji HTTP/3, kreiran na vrhu UDP-a, a ne na vrhu IP-a.
Pa, dosta riječi, vrijeme je da vidimo kako to funkcionira u "stvarnom svijetu".
Bitka
Koristi se za oponašanje stvarnog svijeta iperf3. Što se tiče stupnja bliskosti stvarnosti, to je otprilike isto kao oponašanje stvarnog svijeta u Minecraftu, ali za sada će to učiniti.
Sudionici natječaja:
referentni glavni kanal
junak ovog članka je ipipou
OpenVPN s autentifikacijom, ali bez enkripcije
OpenVPN u sveobuhvatnom načinu rada
WireGuard bez PresharedKey, s MTU=1440 (samo od IPv4)
Tehnički podaci za geekove Mjerni podaci se uzimaju pomoću sljedećih naredbi:
na klijentu:
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", чтобы лишние пакеты не плодить и не портить производительность.