Dit is reg, ons sal vandag dieselfde vir die god van enkripsie sê.
Hier sal ons praat oor 'n ongeënkripteerde IPv4-tonnel, maar nie oor 'n "warm lamp" een nie, maar oor 'n moderne "LED" een. En hier flikker ook rou voetstukke, en werk is aan die gang met pakkies in gebruikersruimte.
Daar is N tonnelprotokolle vir elke smaak en kleur:
Maar ek is 'n programmeerder, so ek sal N slegs met 'n fraksie verhoog en die ontwikkeling van regte protokolle aan Kommersant-ontwikkelaars oorlaat.
In een ongebore die konsepWat ek nou doen, is om gashere agter NAT van buite af te bereik. Deur protokolle met volwasse kriptografie hiervoor te gebruik, kon ek nie die gevoel skud dat dit is soos om mossies uit 'n kanon te skiet nie. Omdat die tonnel word meestal net gebruik om gate in NAT-e te steek, interne verkeer word gewoonlik ook geïnkripteer, maar hulle verdrink steeds in HTTPS.
Terwyl ek verskeie tonnelprotokolle nagevors het, is my innerlike perfeksionis se aandag oor en oor op IPIP gevestig weens die minimale bokoste. Maar dit het een en 'n half beduidende nadele vir my take:
dit vereis openbare IP's aan beide kante,
en geen verifikasie vir jou nie.
Daarom is die perfeksionis teruggedryf in die donker hoek van die skedel, of waar hy ook al daar sit.
En dan eendag, terwyl jy artikels lees oor inheemse ondersteunde tonnels in Linux het ek op FOU (Foo-over-UDP) afgekom, m.a.w. wat ook al, toegedraai in UDP. Tot dusver word slegs IPIP en GUE (Generic UDP Encapsulation) ondersteun.
“Hier is die silwer koeël! ’n Eenvoudige IPIP is vir my genoeg.” - Ek dink.
Trouens, die koeël het geblyk nie heeltemal silwer te wees nie. Inkapseling in UDP los die eerste probleem op - jy kan van buite af met kliënte agter NAT koppel deur 'n voorafbepaalde verbinding, maar hier blom die helfte van die volgende nadeel van IPIP in 'n nuwe lig - enigiemand van 'n private netwerk kan agter die sigbare wegkruip publieke IP en kliëntpoort (in suiwer IPIP bestaan hierdie probleem nie).
Om hierdie een en 'n halwe probleem op te los, is die nut gebore ipipou. Dit implementeer 'n tuisgemaakte meganisme om 'n afgeleë gasheer te staaf, sonder om die werking van die kern-FOU te ontwrig, wat pakkies vinnig en doeltreffend in kernspasie sal verwerk.
Ons het nie jou skrif nodig nie!
Goed, as jy die publieke poort en IP van die kliënt ken (byvoorbeeld, almal daaragter gaan nêrens heen nie, NAT probeer poorte 1-in-1 karteer), kan jy 'n IPIP-oor-FOU-tonnel skep met die volgende opdragte, sonder enige skrifte.
op bediener:
# Подгрузить модуль ядра 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
op die kliënt:
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
waar
ipipou* — naam van die plaaslike tonnelnetwerkkoppelvlak
203.0.113.1 - openbare IP-bediener
198.51.100.2 - publieke IP van die kliënt
192.168.0.2 - kliënt IP toegewys aan koppelvlak eth0
10001 — plaaslike kliëntpoort vir FOU
20001 — publieke kliënt hawe vir FOU
10000 — publieke bedienerpoort vir FOU
encap-csum - opsie om 'n UDP-kontrolesom by ingekapselde UDP-pakkies by te voeg; vervang kan word deur noencap-csum, om nie te praat nie, integriteit word reeds beheer deur die buitenste inkapselingslaag (terwyl die pakkie binne die tonnel is)
eth0 - plaaslike koppelvlak waaraan die ipip-tonnel gebind sal word
172.28.0.1 - IP van die kliënt tonnel koppelvlak (privaat)
Solank die UDP-verbinding lewendig is, sal die tonnel in 'n werkende toestand wees, maar as dit breek, sal jy gelukkig wees - as die kliënt se IP:-poort dieselfde bly - dit sal lewe, as hulle verander - sal dit breek.
Die maklikste manier om alles terug te draai, is om die kernmodules af te laai: modprobe -r fou ipip
Selfs al word stawing nie vereis nie, is die kliënt se openbare IP en poort nie altyd bekend nie en is dit dikwels onvoorspelbaar of veranderlik (na gelang van die NAT-tipe). As jy weglaat encap-dport aan die bedienerkant sal die tonnel nie werk nie, dit is nie slim genoeg om die afstandverbindingpoort te neem nie. In hierdie geval kan ipipou ook help, of WireGuard en ander soos dit kan jou help.
Hoe werk dit?
Die kliënt (wat gewoonlik agter NAT is) maak 'n tonnel oop (soos in die voorbeeld hierbo), en stuur 'n verifikasiepakkie na die bediener sodat dit die tonnel aan sy kant konfigureer. Afhangende van die instellings, kan dit 'n leë pakkie wees (net sodat die bediener die publieke IP: konneksiepoort kan sien), of met data waarmee die bediener die kliënt kan identifiseer. Die data kan 'n eenvoudige wagwoordfrase in duidelike teks wees (die analogie met HTTP Basic Auth kom na vore) of spesiaal ontwerpte data wat met 'n private sleutel onderteken is (soortgelyk aan HTTP Digest Auth net sterker, sien funksie client_auth in die kode).
Op die bediener (die kant met die publieke IP), wanneer ipipou begin, skep dit 'n nfqueue queue hanteerder en stel netfilter op sodat die nodige pakkies gestuur word waar hulle moet wees: pakkies wat die verbinding met die nfqueue queue inisieer, en [amper] al die res gaan reguit na die luisteraar FOU.
Vir diegene wat nie weet nie, is nfqueue (of NetfilterQueue) 'n spesiale ding vir amateurs wat nie weet hoe om kernmodules te ontwikkel nie, wat met behulp van netfilter (nftables/iptables) jou toelaat om netwerkpakkies na gebruikersruimte te herlei en dit daar te verwerk met primitiewe middel byderhand: wysig (opsioneel) en gee dit terug aan die kern, of gooi dit weg.
Vir sommige programmeertale is daar bindings om met nfqueue te werk, vir bash was daar geen (heh, nie verbasend nie), ek moes python gebruik: ipipou gebruik NetfilterWou.
As prestasie nie krities is nie, kan jy met hierdie ding relatief vinnig en maklik jou eie logika saamstel om met pakkies op 'n redelike lae vlak te werk, byvoorbeeld eksperimentele data-oordragprotokolle te skep, of plaaslike en afgeleë dienste met nie-standaard gedrag te trol.
Rou sokke werk hand aan hand met nfqueue, byvoorbeeld, wanneer die tonnel reeds gekonfigureer is en FOU luister op die verlangde poort, sal jy nie 'n pakkie van dieselfde poort op die gewone manier kan stuur nie - dit is besig, maar jy kan 'n ewekansige gegenereerde pakkie direk na die netwerkkoppelvlak neem en stuur deur 'n rou sok te gebruik, alhoewel die generering van so 'n pakkie 'n bietjie meer gepeuter sal verg. Dit is hoe pakkies met verifikasie in ipipou geskep word.
Aangesien ipipou slegs die eerste pakkies van die verbinding verwerk (en dié wat daarin geslaag het om in die tou te lek voordat die verbinding tot stand gebring is), ly prestasie amper nie daaronder nie.
Sodra die ipipou-bediener 'n geverifieerde pakkie ontvang, word 'n tonnel geskep en alle daaropvolgende pakkies in die verbinding word reeds verwerk deur die kern wat nfqueue omseil. As die verbinding misluk, sal die eerste pakkie van die volgende een na die nfqueue-tou gestuur word, afhangende van die instellings, as dit nie 'n pakkie met verifikasie is nie, maar vanaf die laaste onthou IP en kliëntpoort, kan dit óf deurgegee word op of weggegooi. As 'n geverifieerde pakkie van 'n nuwe IP en poort af kom, word die tonnel herkonfigureer om dit te gebruik.
Die gewone IPIP-oor-FOU het nog een probleem wanneer jy met NAT werk - dit is onmoontlik om twee IPIP-tonnels te skep wat in UDP ingekapsuleer is met dieselfde IP, want die FOU- en IPIP-modules is redelik geïsoleer van mekaar. Dié. 'n paar kliënte agter dieselfde openbare IP sal nie gelyktydig op hierdie manier aan dieselfde bediener kan koppel nie. In die toekoms, miskien, sal dit op kernvlak opgelos word, maar dit is nie seker nie. Intussen kan NAT-probleme deur NAT opgelos word - as dit gebeur dat 'n paar IP-adresse reeds deur 'n ander tonnel beset word, sal ipipou NAT van publiek na 'n alternatiewe private IP doen, voila! - jy kan tonnels skep totdat die poorte opraak.
Omdat Nie alle pakkies in die verbinding is onderteken nie, dan is hierdie eenvoudige beskerming kwesbaar vir MITM, so as daar 'n skurk op die pad tussen die kliënt en die bediener skuil wat na die verkeer kan luister en dit kan manipuleer, kan hy gewaarmerkte pakkies herlei deur 'n ander adres en skep 'n tonnel van 'n onbetroubare gasheer.
As iemand idees het oor hoe om dit reg te stel terwyl jy die grootste deel van die verkeer in die kern laat, moet asseblief nie huiwer om te praat nie.
Terloops, inkapseling in UDP het homself baie goed bewys. In vergelyking met inkapseling oor IP, is dit baie meer stabiel en dikwels vinniger ten spyte van die bykomende bokoste van die UDP-opskrif. Dit is te wyte aan die feit dat die meeste gashere op die internet net goed werk met die drie gewildste protokolle: TCP, UDP, ICMP. Die tasbare deel kan alles anders heeltemal weggooi, of dit stadiger verwerk, want dit is net vir hierdie drie geoptimaliseer.
Dit is byvoorbeeld hoekom QUICK, waarop HTTP/3 gebaseer is, bo-op UDP geskep is, en nie bo-op IP nie.
Wel, genoeg woorde, dit is tyd om te sien hoe dit in die "regte wêreld" werk.
Slag
Word gebruik om die regte wêreld na te boots iperf3. Wat die mate van nabyheid aan die werklikheid betref, is dit ongeveer dieselfde as om die werklike wêreld in Minecraft na te boots, maar vir eers sal dit deug.
Deelnemers aan die kompetisie:
verwys hoofkanaal
die held van hierdie artikel is ipipou
OpenVPN met verifikasie, maar geen enkripsie nie
OpenVPN in alles-insluitende modus
WireGuard sonder PresharedKey, met MTU=1440 (slegs vanaf IPv4)
Tegniese data vir geeks Metrieke word geneem met die volgende opdragte:
op die kliënt:
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", чтобы лишние пакеты не плодить и не портить производительность.