Mida me räägime IPv6 jumalale?

Tõsi, ja IPv6 jumalale ütleme täna sama.
Siin räägitakse mittešifreeritud IPv4 tunnelist, aga mitte "soe lamp", vaid moodne "LED". Ja siin vilguvad toored soketid ning toimub pakettide töö kasutajaruumi.
On olemas N tunneldusprotokolli igale maitsele ja värvile:
- stiilne, moekas, noortepärane
- mitmeotstarbelised, nagu Šveitsi noad, OpenVPN ja SSH
- vana ja mitte kuri GRE
- maksimaalselt lihtne, kiire, täiesti mittešifreeritud IPIP
- aktiivselt arenev
- palju teisi.
Aga kuna ma olen programmeerija, siis suurendan N vaid vähesel määral, ja tõeliste protokollide arendamise jätan Ъ-arendajatele.
Ühes veel sündimata , millega ma praegu tegelen, on vaja NAT-i taga asuvate hostidega väljastpoolt ühendust luua. Kasutades selleks täiskasvanute krüptoga protokolle, ei jätnud mind tunne, et see on nagu püssiga lindude peale tulistamine. Kuna tunnelit kasutatakse peamiselt ainult NAT-i august läbi pikendamiseks, on sisetrafik tavaliselt samuti šifreeritud, kõik toetavad HTTPS-i.
Uurides erinevaid tunneldusprotokolle, tõmbas minu sisemine perfectionist korduvalt tähelepanu IPIP-le selle minimaalsete koormuste tõttu. Kuid sellel on minu ülesannete jaoks kaks tõsist puudust:
- see nõuab avalikke IP-aadresse mõlemal pool,
- ja mingit autentimist ei ole.
Seetõttu pidi perfectionist tagasi tõmbuma oma aju tumedasse nurka, või kuhu iganes ta seal istub.
Ja nii lugedes ühe korra Linuxis sattusin FOU (Foo-over-UDP) peale, st miski, mida on UDP-sse mähitud. Seniks toetatakse midagi, mis tuleb, vaid IPIP ja GUE (Generic UDP Encapsulation).
"Siin ta on, hõbedane kuuli! Lihtsast IPIP-ist piisab mulle." — mõtlesin ma.
Tegelikult oli kuul mitte täiesti hõbedane. UDP-sse kapseldamine lahendab esimese probleemi - NAT-i taga asuvatele klientidele saab tulla väljastpoolt kasutades eelnevalt loodud ühendust, kuid siin särab IPIP järgmine puudus uues valguses - nähtavate avalike IP ja kliendi pordi taga võib varjuda keegi, kes on privaatvõrgus (puhta IPIP-i puhul ei ole seda probleemi).
Selle poolik probleemi lahendamiseks sündis utiliit Selles on rakendatud isetegemise mehanism kaughosti autentimiseks, rikkumata samal ajal kerneli FOU tööd, mis töötleb pakette kerge ja tõhusalt.
Sinu skripti ei ole vaja!
Kui sa tead kliendi avalikku porti ja IP-aadressi (näiteks sooritavad nad NAT-i, mis üritab kaardistada porte 1:1), saad luua IPIP-over-FOU tunnelid järgmiste käskudega, ilma igasuguste skriptideta.
serveris:
# Подгрузить модуль ядра 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
kliendis:
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
# Valikud local, peer, peer_port, dev võivad olla vanade kernelite puhul mitte toetatud, neid võib vahele jätta.
# peer ja peer_port kasutatakse ühenduse loomiseks kohe FOU-listeneri loomisel.
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
kus
ipipou*— kohaliku tunnelivõrgu liidese nimi203.0.113.1— serveri avalik IP198.51.100.2— kliendi avalik IP192.168.0.2— kliendi IP, mis on määratud liidesele eth010001— kliendi kohaliku portaadi jaoks FOU20001— kliendi avalik port FOU jaoks10000— serveri avalik port FOU jaoksencap-csum— valik UDP pakettides sisalduva kontrollsummaga lisamise jaoks; seda võib asendadanoencap-csum, et mitte arvutada, terviklikkust kontrollitakse välise sissetoomise kihi kaudu (kuni pakett on tunneli sees)eth0— kohaliku liidese nimi, millega IPIP tunnel on ühendatud172.28.0.1— kliendi tunneliliidese IP (privaatne)172.28.0.0— serveri tunneliliidese IP (privaatne)
Kuni UDP-ühendus on aktiivne, jääb tunnel töötavaks; kui see katke, siis sõltub see olukorrast — kui kliendi IP:port jäävad samaks, jääb see elama, kui need muutuvad — katke.
Kõike lihtsaim on tagasi pöörata, laadides välja kerneli moodulid: modprobe -r fou ipip
Isegi kui autentimine pole vajalik, ei ole kliendi avalikud IP ja port alati teada ning need võivad olla sageli ettearvamatud või muutuvad (sõltuvalt NAT-i tüübist). Kui jätta välja encap-dport serveri poolelt, tunnel ei tööta, sest see ei ole piisavalt intelligentne, et võtta kaugühenduse porti. Sel juhul võib ipipou ka abiks olla, või siis WireGuard ja muud sellega seotud tehnoloogiad aitavad sind.
Kuidas see töötab?
Kliendi (mis tavaliselt on NAT-i taga) tõstab tunnelit (nagu ülalkirjeldatud näites) ja saadab autentimispaketi serverisse, et see saaks tunnelit oma külje pealt seadistada. Olenevalt seadistustest võib see olla tühi pakett (ainult et server näeks avalikke IP-aadresse: ühenduse port), või andmed, mille alusel server suudab klienti tuvastada. Andmed võivad olla lihtne paroolifraas avatud tekstina (tuleb meelde analoogia HTTP Basic Auth'iga) või allkirjastatud eraprivaatselt koos vormindatud andmete (analooline HTTP Digest Auth'ile, vaid tugevam, vt funktsioon client_auth koodis).
Serveris (pool, kus asub avalik IP) ipipou käivitamisel loob järjekorra töötleja nfqueue ning seadistab netfilteri nii, et vajalikud paketid suunatakse õigesse kohta: ühenduse initsieerimise paketid nfqueue'i järjekorda ja [peaaegu] kõik teised otse FOU kuulajasse.
Kes ei tea, nfqueue (või NetfilterQueue) on eriline asi amatööridele, kes ei oska tuuma mooduleid arendada, mis netfilteri (nftables/iptables) abil võimaldab suunata võrgu pakette kasutajaruumi ja neid seal primitiivsete vahenditega töödelda: muudetud (valikuliselt) ja tagasi tuumale anda, või lihtsalt kõrvaldada.
Mõningate programmeerimiskeelte jaoks on olemas sidemed nfqueue kasutamiseks, bash'i jaoks neid ei leitud (heh, pole üllatav), pidime kasutama pythonit: ipipou kasutab .
Kui jõudlus ei ole kriitiline, siis võib selle asjaga suhteliselt kiiresti ja lihtsalt koostada oma loogikat pakettide töötlemiseks piisavalt madalal tasemel, näiteks katsetada andmeedastusprotokolle või trollida kohalikke ja kaugeid teenuseid ebatavalise käitumisega.
Koos nfqueue'iga töötavad toored soketid (raw sockets), näiteks kui tunnel on juba seadistatud ja FOU kuulab õigel pordil, ei saa tavalisel viisil paketti samalt pordilt saata — see on hõivatud, kuid võid võtta ja saata suvaliselt genereeritud paketi otse võrgu liidesesse, kasutades toorest soketti, kuigi sellise paketi genereerimisega tuleb veidi rohkem vaeva näha. Nii luuakse ipipou's autentimispaketid.
Kuna ipipou töötleb ainult ühenduse esimesi pakette (ja neid, mis on järjekorda jõudnud enne ühenduse loomist), ei mõjuta see jõudlust peaaegu üldse.
Niipea kui ipipou-server saab autentimise läbinud paketi, luuakse tunnel ja kõik järgnevad ühenduse pakettide töödeldakse südamikus, möödudes nfqueue'st. Kui ühendus aegub, suunatakse järgmise paketi esimene osa nfqueue'sse, olenevalt seadistustest, kui see ei ole autentimispakett, kuid tuleneb viimasest salvestatud kliendi IP-st ja pordist, võib see kas edasi lasta või tagasi lükata. Kui autentitud pakett tuleb uue IP ja pordiga, konfigureeritakse tunnel nende kasutamiseks ümber.
Tavalise IPIP-over-FOU teise probleemi NAT-i töö korral on see, et ei saa luua kahte IPIP tunnelit, mis on kapseldatud UDP-s sama IP-ga, kuna FOU ja IPIP moodulid on üksteisest piisavalt isoleeritud. See tähendab, et paari kliendi, kellel on sama avalik IP, ei saa samaaegselt ühendada ühe serveriga sellisel viisil. Tulevikus, , lahendatakse see tuumatasemel, kuid see ei ole kindel. Seni saab NAT probleeme lahendada NAT-iga — kui juhtub, et paar IP-aadressi on juba hõivatud teise tunneliga, teeb ipipou NAT-i avalikelt alternatiivsetele privaatsetele IP-dele, voilà! — tunnelite loomine on võimalik, kuni pordid ei saa otsa.
Kuna mitte kõik pakettides ühenduses ei ole allkirjastatud, on selline lihtne kaitse MITM-i suhtes haavatav, seega kui kliendi ja serveri vahel on kurikael, kes suudab kuulata liiklust ja sellega manipuleerida, võib ta suunata autentimispakette läbi teise aadressi ja luua usaldamatust hostist tunnel.
Kui kellelgi on mõtteid, kuidas seda parandada, jättes suurema osa liiklusest tuumasse, andke teada — jagage oma mõtteid.
Muide, UDP kapseldamine on end väga hästi tõestanud. Võrreldes kapseldamisega IP üle on see palju stabiilsem ja tihti kiirem, vaatamata UDP pealisehituse lisakuludele. See tuleneb sellest, et Internetis töötab suurem osa hoste harmoniseeritult ainult kolme kõige populaarsema protokolli: TCP, UDP, ICMP, osas. Märkimisväärne osa võib täielikult kõrvaldada kõik muu või töödelda aeglasemalt, kuna on optimeeritud ainult nende kolme jaoks.
Näiteks, seetõttu loodi QUICK, mille aluseks on HTTP/3, just UDP üle, mitte IP üle.
Noh, piisab sõnadest, on aeg vaadata, kuidas see „reaalses maailmas” toimib.
Lahing
Reaalmaailma simuleerimiseks kasutatakse iperf3. Tõelisuse astme osas on see umbes nagu reaalses maailmas simuletsioon Minecraftis, aga seni sobib.
Võistluses osalevad:
- standardne põhikanal
- selle artikli kangelane ipipou
- OpenVPN autentimisega, aga ilma krüpteerimiseta
- OpenVPN, kus kõik on sisse lülitatud
- WireGuard ilma PresharedKey'da, MTU=1440 (kuna IPv4 ainul)
Tehnilised andmed geeniustele
Mõõdud saadakse järgmiste käskudega
kliendis:
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"
# Kus "-b 12M" on põhikanali läbilaskevõime jagatud voogude arvuga "-P", et mitte genereerida liigseid pakette ja mitte rikutud tootlikkust.
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"
ICMP latentsus
ping -c 10 SERVER_IP | tail -1
serveris (käivitatakse koos kliendiga):
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"
Tunnelite konfiguratsioon
ipipou
server
/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
sattus tausta
/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 (ilma krüpteerimiseta, autentimisega)
server
openvpn --genkey --secret ovpn.key # Seejärel tuleb ovpn.key edastada kliendile
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
sattus tausta
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 (krüpteerimisega, autentimisega, UDP kaudu, kõike nagu peab)
Seatud kasutades
wireguard
server
/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
sattus tausta
/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
tulemused näitasid ainult nelja ebaolulise koodibloki kattuvust, mis olid tingitud POSIX ja ANSI C nõuetest.
Toores hirmus tabel
Serveri CPU koormus ei ole kuigi hea näitaja, kuna seal töötab palju teisi teenuseid, mis mõnikord vajavad ressursse:
proto bandwidth[Mbps] CPU_idle_client[%] CPU_idle_server[%]
# 20 Mbps kanal mikrokontrollerist (4 core) VPS ni (1 core) üle Atlandi
# puhas
UDP 20.4 99.80 93.34
TCP 19.2 99.67 96.68
ICMP viivitus 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 viivitus min/avg/max/mdev = 199.562/208.919/220.222/7.905 ms
# openvpn0 (ainult autentimine, krüpteerimist ei ole)
UDP 19.3 99.89 72.90
TCP 16.1 95.95 88.46
ICMP viivitus min/avg/max/mdev = 191.631/193.538/198.724/2.520 ms
# openvpn (täis krüpteerimine, autentimine jne)
UDP 19.6 99.75 72.35
TCP 17.0 94.47 87.99
ICMP viivitus 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 viivitus min/avg/max/mdev = 217.925/223.601/230.696/3.266 ms
## umbes 1Gbps kanal Euroopa ja USA VPSide vahel (1 core)
# puhas
UDP 729 73.40 39.93
TCP 363 96.95 90.40
ICMP viivitus 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 viivitus min/avg/max/mdev = 107.444/107.523/107.648/0.058 ms
# openvpn0 (ainult autentimine, krüpteerimist ei ole)
UDP 193 17.51 1.62
TCP 12 95.45 92.80
ICMP viivitus 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 viivitus min/avg/max/mdev = 107.616/107.788/108.038/0.128 ms
20 Mbps kanal


1 optimistlik Gbps kanal


Igas olukorras on ipipou tulemused üsna lähedased põhikanali näitajatele, ja see on suurepärane!
Krüpteerimata openvpn tunnel käitus kummaliselt mõlemas olukorras.
Kui keegi tahab testida, siis oleks huvitav kuulda tagasisidet.
Olgu IPv6 ja NetPrickle meiega!
Allikas: habr.com
