ipipou : più cà un tunnellu micca criptatu

Chì dicemu à u Diu di l'IPv6?

ipipou : più cà un tunnellu micca criptatu
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:

  • eleganti, di moda, ghjuventù WireGuard
  • multifunzionale, cum'è i culteddi svizzeri, OpenVPN è SSH
  • vechju è micca male GRE
  • l'IPIP più simplice, veloce, cumpletamente micca criptatu
  • sviluppatu attivamente GENEVE
  • tanti altri.

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", чтобы лишние пакеты не плодить и не портить производительность.

TCP

CPULOG=NAME.tcp.cpu.log; sar 10 6 >"$CPULOG" & iperf3 -c SERVER_IP -4 -t 60 -f m -i 10 -B LOCAL_IP -P 2; tail -1 "$CPULOG"

Latenza ICMP

ping -c 10 SERVER_IP | tail -1

nantu à u servitore (corre simultaneamente cù u cliente):

UDP

CPULOG=NAME.udp.cpu.log; sar 10 6 >"$CPULOG" & iperf3 -s -i 10 -f m -1; tail -1 "$CPULOG"

TCP

CPULOG=NAME.tcp.cpu.log; sar 10 6 >"$CPULOG" & iperf3 -s -i 10 -f m -1; tail -1 "$CPULOG"

Cunfigurazione di u tunnel

ipipou
servitore
/etc/ipipou/server.conf:

server
number 0
fou-dev eth0
fou-local-port 10000
tunl-ip 172.28.0.0
auth-remote-pubkey-b64 eQYNhD/Xwl6Zaq+z3QXDzNI77x8CEKqY1n5kt9bKeEI=
auth-secret topsecret
auth-lifetime 3600
reply-on-auth-ok
verb 3

systemctl start ipipou@server

cliente
/etc/ipipou/client.conf:

client
number 0
fou-local @eth0
fou-remote SERVER_IP:10000
tunl-ip 172.28.0.1
# pubkey of auth-key-b64: eQYNhD/Xwl6Zaq+z3QXDzNI77x8CEKqY1n5kt9bKeEI=
auth-key-b64 RuBZkT23na2Q4QH1xfmZCfRgSgPt5s362UPAFbecTso=
auth-secret topsecret
keepalive 27
verb 3

systemctl start ipipou@client

openvpn (senza crittografia, cù autentificazione)
servitore

openvpn --genkey --secret ovpn.key  # Затем надо передать ovpn.key клиенту
openvpn --dev tun1 --local SERVER_IP --port 2000 --ifconfig 172.16.17.1 172.16.17.2 --cipher none --auth SHA1 --ncp-disable --secret ovpn.key

cliente

openvpn --dev tun1 --local LOCAL_IP --remote SERVER_IP --port 2000 --ifconfig 172.16.17.2 172.16.17.1 --cipher none --auth SHA1 --ncp-disable --secret ovpn.key

openvpn (cù crittografia, autentificazione, via UDP, tuttu cum'è previstu)
Configuratu usendu openvpn-manage

guardia di filu
servitore
/etc/wireguard/server.conf:

[Interface]
Address=172.31.192.1/18
ListenPort=51820
PrivateKey=aMAG31yjt85zsVC5hn5jMskuFdF8C/LFSRYnhRGSKUQ=
MTU=1440

[Peer]
PublicKey=LyhhEIjVQPVmr/sJNdSRqTjxibsfDZ15sDuhvAQ3hVM=
AllowedIPs=172.31.192.2/32

systemctl start wg-quick@server

cliente
/etc/wireguard/client.conf:

[Interface]
Address=172.31.192.2/18
PrivateKey=uCluH7q2Hip5lLRSsVHc38nGKUGpZIUwGO/7k+6Ye3I=
MTU=1440

[Peer]
PublicKey=DjJRmGvhl6DWuSf1fldxNRBvqa701c0Sc7OpRr4gPXk=
AllowedIPs=172.31.192.1/32
Endpoint=SERVER_IP:51820

systemctl start wg-quick@client

Risultati

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

ipipou : più cà un tunnellu micca criptatu

ipipou : più cà un tunnellu micca criptatu

canale per 1 Gbps ottimista

ipipou : più cà un tunnellu micca criptatu

ipipou : più cà un tunnellu micca criptatu

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.

Pò IPv6 è NetPrickle esse cun noi !

Source: www.habr.com

Add a comment