Hè propiu, diceremu u stessu à u diu di a criptografia oghje.
Quì parlemu di un tunnel IPv4 non criptatu, ma micca di una "lampada calda", ma di una moderna "LED". È ci sò ancu sockets crudi lampendu quì, è u travagliu hè in corso cù pacchetti in u spaziu di l'utilizatori.
Ci sò N protokolli di tunneling per ogni gustu è culore:
Ma sò un programatore, cusì aghju aumentatu N solu da una frazzioni, è lasciate u sviluppu di protokolli veri à i sviluppatori di Kommersant.
In un nascitu prughjettuCiò chì facciu avà hè di ghjunghje à l'ospiti daretu à NAT da l'esternu. Utilizendu protokolli cù a criptografia adulta per questu, ùn pudia micca scuzzulate a sensazione chì era cum'è sparrow sparrows da un cannone. Perchè u tunelu hè utilizatu per a maiò parte solu per poke holes in NAT-e, u trafficu internu hè di solitu ancu criptatu, ma anu sempre affucatu in HTTPS.
Mentre cercava diversi protokolli di tunneling, l'attenzione di u mo perfeccionista internu hè stata attirata à l'IPIP una e più volte per via di u so minimu overhead. Ma hà un svantaghju è mezu significativu per i mo compiti:
esige IP publichi da i dui lati,
è senza autentificazione per voi.
Per quessa, u perfeccionista hè statu cacciatu torna in u cantonu scuru di u craniu, o induve si trova.
È dopu un ghjornu, mentre leghje articuli nantu tunnel supportati nativamente in Linux aghju trovu FOU (Foo-over-UDP), i.e. qualunque sia, avvoltu in UDP. Finu a ora, solu IPIP è GUE (Generic UDP Encapsulation) sò supportati.
"Eccu a pallottola d'argentu! Un IPIP simplice hè abbastanza per mè ". - Aghju pensatu.
In fatti, a balla ùn era micca cumpletamente d'argentu. L'encapsulazione in UDP risolve u primu prublema - pudete cunnette cù i clienti daretu à NAT da l'esternu utilizendu una cunnessione predeterminata, ma quì a mità di u prossimu inconveniente di IPIP fiorisce in una nova luce - qualchissia da una reta privata pò ammuccià daretu à u visibile. IP publicu è u portu di u cliente (in IPIP pura stu prublema ùn esiste micca).
Per risolviri stu prublema è mezu, hè natu l'utilità ipipou. Implementa un mecanismu di casa per l'autentificazione di un host remoto, senza disturbà l'operazione di u kernel FOU, chì processerà rapidamente è efficacemente i pacchetti in u spaziu di u kernel.
Ùn avemu micca bisognu di u vostru script !
Ok, se cunnosci u portu publicu è l'IP di u cliente (per esempiu, tutti quelli chì sò daretu ùn vanu in nudda parte, NAT prova à mape i porti 1-in-1), pudete creà un tunnel IPIP-over-FOU cù u seguenti cumandamenti, senza alcunu script.
nant'à u servitore:
# Подгрузить модуль ядра 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
nantu à u cliente:
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
induve
ipipou* - nome di l'interfaccia di rete di u tunnellu lucale
203.0.113.1 - servore IP publicu
198.51.100.2 - IP publicu di u cliente
192.168.0.2 - IP cliente assignata à l'interfaccia eth0
10001 - portu clientu lucale per FOU
20001 - portu publicu di u cliente per FOU
10000 - portu di u servitore publicu per FOU
encap-csum - opzione per aghjunghje un checksum UDP à i pacchetti UDP incapsulati; pò esse rimpiazzatu da noencap-csum, per ùn dì, l'integrità hè digià cuntrullata da a capa di incapsulazione esterna (mentre u pacchettu hè in u tunnel)
eth0 - interfaccia locale à quale u tunnel ipip serà ligatu
172.28.0.1 - IP di l'interfaccia di u tunnel di cliente (privata)
172.28.0.0 - Interfaccia di u servitore di tunnel IP (privatu)
Mentre a cunnessione UDP hè viva, u tunelu serà in modu di funziunamentu, ma s'ellu si rompe, sarete furtunatu - se l'IP di u cliente: u portu ferma u listessu - vivrà, se cambiassi - si romperà.
A manera più faciule di vultà tuttu hè di scaricate i moduli di u kernel: modprobe -r fou ipip
Ancu s'ellu ùn hè micca necessariu l'autentificazione, l'IP publicu è u portu di u cliente ùn sò micca sempre cunnisciuti è sò spessu imprevisible o variabili (secondu u tipu NAT). Se omette encap-dport da u latu di u servitore, u tunnel ùn hà micca travagliatu, ùn hè micca abbastanza intelligente per piglià u portu di cunnessione remota. In stu casu, ipipou pò dinù aiutà, o WireGuard è altri comu si pò aiutà vi.
Cumu viaghja?
U cliente (chì hè di solitu daretu à NAT) apre un tunnel (cum'è in l'esempiu sopra), è manda un pacchettu d'autentificazione à u servitore in modu chì cunfigurà u tunnel da u so latu. Sicondu i paràmetri, questu pò esse un pacchettu viotu (solu per chì u servitore pò vede l'IP publicu: portu di cunnessione), o cù dati per quale u servitore pò identificà u cliente. I dati ponu esse una passphrase simplice in testu chjaru (l'analogia cù HTTP Basic Auth vene in mente) o dati apposta firmati cù una chjave privata (simile à HTTP Digest Auth solu più forte, vede a funzione client_auth in u codice).
Nant'à u servitore (u latu cù l'IP publicu), quandu ipipou principia, crea un gestore di fila nfqueue è cunfigurà netfilter in modu chì i pacchetti necessarii sò mandati induve si deve esse: pacchetti chì inizializzanu a cunnessione à a fila nfqueue, è [quasi] tuttu u restu vai direttamente à l'ascoltatore FOU.
Per quelli chì ùn sanu micca, nfqueue (o NetfilterQueue) hè una cosa speciale per i dilettanti chì ùn sanu micca cumu sviluppà i moduli di u kernel, chì utilizendu netfilter (nftables/iptables) vi permette di reindirizzà i pacchetti di rete à u spaziu di l'utilizatori è di processà quì utilizendu. primitivu significa à a manu: mudificà (opcional) è rinvià à u kernel, o scartà.
Per certi linguaggi di prugrammazione ci sò ligami per travaglià cù nfqueue, per bash ùn ci era nimu (heh, micca surprisante), aghju avutu aduprà python: ipipou usa NetfilterQueue.
Se u rendimentu ùn hè micca criticu, utilizendu sta cosa pudete cuncettà relativamente rapidamente è facilmente a vostra propria logica per travaglià cù pacchetti à un livellu abbastanza bassu, per esempiu, creà protokolli di trasferimentu di dati sperimentali, o troll servizii lucali è remoti cù un cumpurtamentu micca standard.
I sockets crudi travaglianu in manu cù nfqueue, per esempiu, quandu u tunelu hè digià cunfiguratu è FOU hè à sente nantu à u portu desideratu, ùn puderete micca mandà un pacchettu da u stessu portu in u modu di solitu - hè occupatu, ma pudete piglià è mandà un pacchettu generatu aleatoriu direttamente à l'interfaccia di a rete utilizendu un socket crudu, ancu se generà un tali pacchettu richiederà un pocu più di tinkering. Hè cusì chì i pacchetti cù autentificazione sò creati in ipipou.
Siccomu ipipou prucessa solu i primi pacchetti da a cunnessione (è quelli chì anu sappiutu fughje in a fila prima chì a cunnessione hè stata stabilita), u rendiment quasi ùn soffre micca.
Appena u servitore ipipou riceve un pacchettu autentificatu, un tunnel hè creatu è tutti i pacchetti successivi in a cunnessione sò digià processati da u kernel bypassing nfqueue. Se a cunnessione falla, u primu pacchettu di u prossimu sarà mandatu à a fila nfqueue, secondu a paràmetra, s'ellu ùn hè micca un pacchettu cù autentificazione, ma da l'ultimu IP ricurdatu è u portu di u cliente, pò esse passatu. sopra o scartati. Se un pacchettu autentificatu vene da una nova IP è portu, u tunnel hè cunfiguratu per aduprà.
U solitu IPIP-over-FOU hà un prublema più quandu u travagliu cù NAT - hè impussibile di creà dui tunnel IPIP incapsulati in UDP cù a stessa IP, perchè i moduli FOU è IPIP sò abbastanza isolati l'una di l'altru. Quelli. un paru di clienti daretu à u listessu IP publicu ùn puderà micca cunnette simultaneamente à u stessu servitore in questu modu. In u futuru, hè possibile, serà risolta à u livellu di u kernel, ma questu ùn hè micca sicuru. Intantu, i prublemi NAT ponu esse risolti da NAT - s'ellu succede chì un paru di indirizzi IP hè digià occupatu da un altru tunnel, ipipou farà NAT da publicu à un IP privatu alternativu, voilà! - pudete creà tunnelli finu à chì i porti sguassate.
Perchè Ùn sò micca tutti i pacchetti in a cunnessione sò firmati, allora sta prutezzione simplice hè vulnerabile à MITM, perchè s'ellu ci hè un cattivu chì lurking in u percorsu trà u cliente è u servitore chì pò sente u trafficu è manipule, pò redirige i pacchetti autentificati attraversu. un altru indirizzu è creanu un tunnel da un host micca fiduciale.
Sì qualchissia hà idee nantu à cumu risolve questu mentre abbandunà a maiò parte di u trafficu in u core, ùn esitate micca à parlà.
Per via, l'incapsulazione in UDP hà pruvatu assai bè. Comparatu à l'incapsulazione nantu à IP, hè assai più stabile è spessu più veloce malgradu l'overhead supplementu di l'intestazione UDP. Questu hè duvuta à u fattu chì a maiò parte di l'ospiti in Internet funziona bè solu cù i trè protokolli più populari: TCP, UDP, ICMP. A parte tangibile pò scaccià cumplettamente tuttu u restu, o processà più lentamente, perchè hè ottimizatu solu per questi trè.
Per esempiu, hè per quessa QUICK, chì hè basatu HTTP/3, hè statu creatu nantu à UDP, è micca in cima à IP.
Ebbè, abbastanza parolle, hè ora di vede cumu si travaglia in u "mondu reale".
Battaglia
Adupratu per emulà u mondu reale iperf3. In quantu à u gradu di vicinanza à a realità, questu hè apprussimatamente u stessu cum'è emulà u mondu reale in Minecraft, ma per avà farà.
Participanti à u cuncorsu:
canale principale di riferimentu
l'eroi di stu articulu hè ipipou
OpenVPN cù autentificazione ma senza criptografia
OpenVPN in modu all-inclusive
WireGuard senza PresharedKey, cù MTU = 1440 (dapoi solu IPv4)
Dati tecnichi per i geeks A metrica hè presa cù i seguenti cumandamenti:
nantu à u cliente:
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", чтобы лишние пакеты не плодить и не портить производительность.
Segnu bruttu umitu
A carica di CPU di u server ùn hè micca assai indicativa, perchè ... Ci sò parechji altri servizii chì funzionanu quì, qualchì volta manghjanu risorse:
proto bandwidth[Mbps] CPU_idle_client[%] CPU_idle_server[%]
# 20 Mbps канал с микрокомпьютера (4 core) до VPS (1 core) через Атлантику
# pure
UDP 20.4 99.80 93.34
TCP 19.2 99.67 96.68
ICMP latency min/avg/max/mdev = 198.838/198.997/199.360/0.372 ms
# ipipou
UDP 19.8 98.45 99.47
TCP 18.8 99.56 96.75
ICMP latency min/avg/max/mdev = 199.562/208.919/220.222/7.905 ms
# openvpn0 (auth only, no encryption)
UDP 19.3 99.89 72.90
TCP 16.1 95.95 88.46
ICMP latency min/avg/max/mdev = 191.631/193.538/198.724/2.520 ms
# openvpn (full encryption, auth, etc)
UDP 19.6 99.75 72.35
TCP 17.0 94.47 87.99
ICMP latency min/avg/max/mdev = 202.168/202.377/202.900/0.451 ms
# wireguard
UDP 19.3 91.60 94.78
TCP 17.2 96.76 92.87
ICMP latency min/avg/max/mdev = 217.925/223.601/230.696/3.266 ms
## около-1Gbps канал между VPS Европы и США (1 core)
# pure
UDP 729 73.40 39.93
TCP 363 96.95 90.40
ICMP latency min/avg/max/mdev = 106.867/106.994/107.126/0.066 ms
# ipipou
UDP 714 63.10 23.53
TCP 431 95.65 64.56
ICMP latency min/avg/max/mdev = 107.444/107.523/107.648/0.058 ms
# openvpn0 (auth only, no encryption)
UDP 193 17.51 1.62
TCP 12 95.45 92.80
ICMP latency min/avg/max/mdev = 107.191/107.334/107.559/0.116 ms
# wireguard
UDP 629 22.26 2.62
TCP 198 77.40 55.98
ICMP latency min/avg/max/mdev = 107.616/107.788/108.038/0.128 ms
Canale 20 Mbps
canale per 1 Gbps ottimista
In tutti i casi, ipipou hè abbastanza vicinu à u funziunamentu di u canali di basa, chì hè grande!
U tunnel openvpn senza criptu si cumpurtava in modu abbastanza stranu in i dui casi.
Se qualchissia hà da pruvà, serà interessante per sente feedback.