Ovdje ćemo govoriti o nešifrovanom IPv4 tunelu, ali ne o onom „topla lampa“, već o modernom „LED“. A tu su i neobrađeni soketi koji bljeskaju ovdje, a u toku je rad sa 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 Kommersant-a.
U jednom nerođenom projektOno što sada radim je da dođem do hostova iza NAT-a izvana. Koristeći za to protokole sa kriptografijom za odrasle, nisam se mogao otarasiti osjećaja da je to kao pucanje vrapca iz topa. Jer tunel se uglavnom koristi samo za bušenje rupa u NAT-e, interni saobraćaj je obično takođe šifrovan, ali se i dalje utapa u HTTPS.
Dok sam istraživao razne protokole tuneliranja, pažnja mog unutrašnjeg perfekcioniste je uvijek iznova privlačila IPIP zbog minimalnih troškova. Ali ima jedan i po značajnih nedostataka za moje zadatke:
zahtijeva javne IP adrese s obje strane,
i nema autentifikacije za vas.
Stoga je perfekcionista otjeran nazad u tamni ugao lobanje, ili gdje god tamo sjedi.
A onda jednog dana, dok čitam članke dalje izvorno podržani tuneli u Linuxu sam naišao na FOU (Foo-over-UDP), tj. bilo šta, umotano u UDP. Do sada su podržani samo IPIP i GUE (generička UDP enkapsulacija).
„Evo srebrnog metka! Dovoljan mi je jednostavan IPIP.” - Mislio sam.
U stvari, pokazalo se da metak nije bio potpuno srebrni. Enkapsulacija u UDP rješava prvi problem - možete se povezati s klijentima iza NAT-a izvana koristeći unaprijed uspostavljenu vezu, ali ovdje polovina sljedećeg nedostatka IPIP-a procvjeta u novom svjetlu - svako iz privatne mreže može se sakriti iza vidljivog javni IP i port klijenta (u čistom IPIP-u ovaj problem ne postoji).
Da bi riješio ovaj jedan i po problem, rođen je uslužni program ipipou. Implementira domaći mehanizam za autentifikaciju udaljenog hosta, bez ometanja rada kernela FOU, koji će brzo i efikasno obraditi pakete u prostoru kernela.
Ne treba nam tvoj scenario!
Ok, ako znate javni port i IP klijenta (na primjer, svi iza njega ne idu nikuda, NAT pokušava mapirati portove 1-u-1), možete kreirati IPIP-over-FOU tunel sa sljedeće komande, bez ikakvih skripti.
na serveru:
# Подгрузить модуль ядра 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 lokalnog tunelskog mrežnog interfejsa
203.0.113.1 — javni IP server
198.51.100.2 — javni IP klijenta
192.168.0.2 — IP klijenta dodijeljen interfejsu eth0
10001 — lokalni klijentski port za FOU
20001 — javni klijentski port za FOU
10000 — port javnog servera za FOU
encap-csum — opcija za dodavanje UDP kontrolne sume inkapsuliranim UDP paketima; može se zamijeniti sa noencap-csum, da ne spominjemo, integritet je već kontroliran od strane vanjskog sloja enkapsulacije (dok je paket unutar tunela)
eth0 — lokalni interfejs na koji će ipip tunel biti vezan
172.28.0.1 — IP interfejsa klijentskog tunela (privatno)
172.28.0.0 — IP tunel serverski interfejs (privatno)
Dokle god je UDP veza živa, tunel će biti u funkciji, ali ako se pokvari, imat ćete sreće - ako IP: port klijenta ostane isti - živjet će, ako se promijene - pokvariće se.
Najlakši način da sve vratite je da ispraznite module kernela: modprobe -r fou ipip
Čak i ako autentifikacija nije potrebna, klijentov javni IP i port nisu uvijek poznati i često su nepredvidivi ili varijabilni (ovisno o tipu NAT-a). Ako izostavite encap-dport na strani servera, tunel neće raditi, nije dovoljno pametan da preuzme port za udaljenu vezu. U ovom slučaju, ipipou također može pomoći, ili WireGuard i drugi slični mogu vam pomoći.
Как это работает?
Klijent (koji se obično nalazi iza NAT-a) otvara tunel (kao u gornjem primjeru) i šalje autentifikacijski paket serveru tako da on konfigurira tunel na svojoj strani. Ovisno o postavkama, to može biti prazan paket (samo da server vidi javni IP: port veze), ili sa podacima po kojima server može identificirati klijenta. Podaci mogu biti jednostavna pristupna fraza u čistom tekstu (na pamet mi pada analogija s HTTP Basic Auth) ili posebno dizajnirani podaci potpisani privatnim ključem (slično HTTP Digest Auth samo jači, pogledajte funkciju client_auth u kodu).
Na serveru (strana s javnom IP-om), kada se ipipou pokrene, kreira nfqueue queue handler i konfigurira netfilter tako da se potrebni paketi šalju tamo gdje bi trebali biti: paketi koji inicijaliziraju vezu s nfqueue redom i [skoro] sve ostalo ide direktno slušaocu FOU.
Za one koji ne znaju, nfqueue (ili NetfilterQueue) je posebna stvar za amatere koji ne znaju kako razviti module kernela, koji pomoću netfiltera (nftables/iptables) omogućavaju preusmjeravanje mrežnih paketa u korisnički prostor i obradu ih tamo koristeći primitivno sredstvo pri ruci: modificirati (opciono) i vratiti ga kernelu, ili ga odbaciti.
Za neke programske jezike postoje veze za rad sa nfqueue, za bash ih nije bilo (heh, nije iznenađujuće), morao sam koristiti python: ipipou koristi NetfilterQueue.
Ako performanse nisu kritične, pomoću ove stvari možete relativno brzo i lako smisliti vlastitu logiku za rad s paketima na prilično niskom nivou, na primjer, kreirati eksperimentalne protokole za prijenos podataka ili trolovati lokalne i udaljene usluge nestandardnim ponašanjem.
Raw utičnice rade ruku pod ruku sa nfqueue, na primjer, kada je tunel već konfiguriran i FOU sluša na željenom portu, nećete moći poslati paket sa istog porta na uobičajen način - zauzet je, ali možete uzeti i poslati nasumično generisani paket direktno na mrežni interfejs koristeći sirovu utičnicu, iako će za generisanje takvog paketa biti potrebno malo više popravljanja. Ovako se kreiraju paketi sa autentifikacijom u ipipou.
Budući da ipipou obrađuje samo prve pakete iz veze (i one koji su uspjeli procuriti u red prije uspostavljanja veze), performanse gotovo da ne trpe.
Čim ipipou server primi autentificirani paket, kreira se tunel i svi naredni paketi u vezi su već obrađeni od strane kernela zaobilazeći nfqueue. Ako veza ne uspije, tada će prvi paket sljedećeg biti poslan u nfqueue queue, ovisno o postavkama, ako nije paket s autentifikacijom, ali sa zadnjeg zapamćenog IP-a i klijentskog porta, može se ili proslijediti uključeno ili odbačeno. Ako autentificirani paket dolazi s novog IP-a i porta, tunel se rekonfigurira da ih koristi.
Uobičajeni IPIP-over-FOU ima još jedan problem pri radu sa NAT-om - nemoguće je kreirati dva IPIP tunela inkapsulirana u UDP sa istim IP-om, jer su FOU i IPIP moduli prilično izolovani jedan od drugog. One. par klijenata iza iste javne IP adrese neće moći istovremeno da se poveže na isti server na ovaj način. U budućnosti, moguće, to će biti riješeno na nivou kernela, ali to nije sigurno. U međuvremenu, NAT probleme može riješiti NAT - ako se dogodi da je par IP adresa već zauzet drugim tunelom, ipipou će učiniti NAT sa javnog na alternativni privatni IP, voila! - možete kreirati tunele dok ne ponestane portova.
Jer Nisu svi paketi u konekciji potpisani, onda je ova jednostavna zaštita ranjiva na MITM, pa ako na putu između klijenta i servera vreba negativac koji može slušati promet i manipulirati njime, on može preusmjeriti autentificirane pakete kroz drugu adresu i kreirajte tunel od nepouzdanog hosta.
Ako neko ima ideje kako to popraviti, a da najveći dio prometa ostane u jezgri, ne oklijevajte da progovorite.
Inače, inkapsulacija u UDP se jako dobro pokazala. U poređenju sa enkapsulacijom preko IP-a, ona je mnogo stabilnija i često brža uprkos dodatnim opterećenjima UDP zaglavlja. To je zbog činjenice da većina hostova na Internetu dobro radi samo sa tri najpopularnija protokola: TCP, UDP, ICMP. Opipljivi dio može potpuno odbaciti sve ostalo, ili to sporije obrađivati, jer je optimiziran samo za ovo troje.
Na primjer, ovo je razlog zašto 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 stepena bliskosti sa stvarnošću, ovo je otprilike isto kao oponašanje stvarnog svijeta u Minecraftu, ali za sada će to biti dovoljno.
Učesnici takmičenja:
referentni glavni kanal
junak ovog članka je ipipou
OpenVPN sa autentifikacijom, ali bez enkripcije
OpenVPN u sveobuhvatnom načinu rada
WireGuard bez PresharedKey, sa MTU=1440 (od samo IPv4)
Tehnički podaci za štreberke Metrike 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", чтобы лишние пакеты не плодить и не портить производительность.