ipipou: rohkem kui lihtsalt krüptimata tunnel

Mida me ütleme IPv6 jumalale?

ipipou: rohkem kui lihtsalt krüptimata tunnel
See on õige, me ütleme täna sama krüpteerimisjumalale.

Siin räägime krüptimata IPv4 tunnelist, kuid mitte "soojast lambist", vaid kaasaegsest "LED" tunnelist. Ja siin vilguvad ka toored pesad ja töö käib kasutajaruumis olevate pakettidega.

Iga maitse ja värvi jaoks on N tunneldamisprotokolli:

  • stiilne, moodne, nooruslik WireGuard
  • multifunktsionaalne, nagu Šveitsi noad, OpenVPN ja SSH
  • vana ja mitte kuri GRE
  • kõige lihtsam, kiirem, täiesti krüptimata IPIP
  • aktiivselt arenema GENEVA
  • paljud teised.

Kuid ma olen programmeerija, seega suurendan N-i vaid murdosa võrra ja jätan pärisprotokollide arendamise Kommersanti arendajatele.

Ühes sündimata projektiSee, mida ma praegu teen, on jõuda väljastpoolt NAT-i taga olevate hostideni. Kasutades selleks täiskasvanute krüptograafiaga protokolle, ei saanud ma lahti tundest, et see on nagu varblaste kahurist tulistamine. Sest tunnelit kasutatakse enamjaolt ainult NAT-e-sse aukude torkamiseks, siseliiklus on enamasti ka krüpteeritud, aga need upuvad ikka HTTPS-i ära.

Erinevaid tunneliprotokolle uurides pälvis minu sisemise perfektsionisti tähelepanu IPIP selle minimaalse üldkulu tõttu ikka ja jälle. Kuid sellel on minu ülesannete jaoks poolteist olulist puudust:

  • see nõuab mõlemalt poolt avalikke IP-sid,
  • ja teie jaoks pole autentimist.

Seetõttu aeti perfektsionist tagasi kolju tumedasse nurka või kuhu iganes ta seal istub.

Ja siis ühel päeval, lugedes artikleid algselt toetatud tunnelid Linuxis puutusin kokku FOU-ga (Foo-over-UDP), st. mis iganes, pakitud UDP-sse. Seni on toetatud ainult IPIP ja GUE (Generic UDP Encapsulation).

„Siin on hõbekuul! Minu jaoks piisab lihtsast IPIP-st. - Ma mõtlesin.

Tegelikult osutus kuul mitte täiesti hõbedaseks. Kapseldamine UDP-sse lahendab esimese probleemi – NAT-i taga olevate klientidega saab ühenduse luua väljastpoolt, kasutades eelnevalt loodud ühendust, kuid siin puhkeb pool IPIP-i järgmisest puudusest uues valguses – igaüks privaatvõrgust saab peituda nähtava taha. avalik IP ja kliendiport (puhta IPIP puhul seda probleemi ei esine).

Selle pooleteise probleemi lahendamiseks sündis utiliit ipipou. See rakendab kodus valmistatud mehhanismi kaughosti autentimiseks, häirimata tuuma FOU tööd, mis töötleb kiiresti ja tõhusalt pakette kerneli ruumis.

Me ei vaja teie skripti!

Ok, kui teate kliendi avalikku porti ja IP-d (näiteks kõik selle taga olevad inimesed ei lähe kuhugi, NAT proovib kaardistada porte 1-in-1), saate luua IPIP-over-FOU tunneli järgmised käsud, ilma 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

kliendi kohta:

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

kus

  • ipipou* — kohaliku tunneli võrguliidese nimi
  • 203.0.113.1 — avalik IP-server
  • 198.51.100.2 — kliendi avalik IP
  • 192.168.0.2 — liidesele eth0 määratud kliendi IP
  • 10001 — FOU kohalik kliendiport
  • 20001 — FOU avalik kliendiport
  • 10000 — avalik serveriport FOU jaoks
  • encap-csum — võimalus lisada kapseldatud UDP-pakettidele UDP kontrollsumma; saab asendada noencap-csum, rääkimata sellest, terviklikkust kontrollib juba välimine kapselduskiht (kui pakett on tunnelis)
  • eth0 — kohalik liides, millega ipip-tunnel seotakse
  • 172.28.0.1 — klienditunneli liidese IP (privaatne)
  • 172.28.0.0 — IP-tunneli serveri liides (privaatne)

Kuni UDP ühendus on elus, on tunnel töökorras, aga kui see katki läheb, siis veab - kui kliendi IP: port jääb samaks - elab, kui vahetuvad - läheb katki.

Lihtsaim viis kõike tagasi pöörata on kerneli moodulite mahalaadimine: modprobe -r fou ipip

Isegi kui autentimine pole vajalik, ei ole kliendi avalik IP ja port alati teada ning need on sageli ettearvamatud või muutuvad (olenevalt NAT-i tüübist). Kui jätate vahele encap-dport serveri poolel tunnel ei tööta, pole piisavalt tark kaugühenduse porti võtta. Sel juhul saab aidata ka ipipou või WireGuard ja teised sarnased.

Kuidas see toimib?

Klient (mis on tavaliselt NAT-i taga) avab tunneli (nagu ülaltoodud näites) ja saadab serverile autentimispaketi, nii et see konfigureerib tunneli enda küljel. Olenevalt seadistustest võib see olla tühi pakett (just selleks, et server näeks avalikku IP: ühendusporti) või andmetega, mille järgi server saab klienti tuvastada. Andmed võivad olla lihtsa tekstiga paroolifraas (tuleb meelde analoogia HTTP põhiautentiga) või spetsiaalselt loodud andmed, mis on allkirjastatud privaatvõtmega (sarnaselt HTTP Digest Authiga on ainult tugevam, vt funktsiooni client_auth koodis).

Serveris (avaliku IP-ga pool) loob ipipou käivitumisel nfqueue järjekorra töötleja ja seadistab netfiltri nii, et vajalikud paketid saadetakse sinna, kus need olema peaksid: paketid, mis initsialiseerivad ühenduse nfqueue järjekorraga ja [peaaegu] kõik ülejäänud lähevad otse kuulajale FOU.

Neile, kes ei tea, on nfqueue (või NetfilterQueue) eriline asi amatööridele, kes ei tea, kuidas kerneli mooduleid arendada, mis netfiltri (nftables/iptables) abil võimaldab võrgupakette kasutajaruumi ümber suunata ja neid seal kasutades töödelda. primitiivne tähendab käepärast: muutke (valikuline ) ja andke see kernelile tagasi või visake see ära.

Mõne programmeerimiskeele jaoks on nfqueue-ga töötamiseks sidemeid, bashi jaoks neid polnud (heh, pole üllatav), pidin kasutama pythonit: ipipou kasutab NetfilterQueue.

Kui jõudlus pole kriitilise tähtsusega, saab seda asja kasutades suhteliselt kiiresti ja lihtsalt oma loogikat üsna madalal tasemel pakettidega töötamiseks välja mõelda, näiteks luua eksperimentaalseid andmeedastusprotokolle või trollida ebastandardse käitumisega kohalikke ja kaugteenuseid.

Toorpesad töötavad käsikäes nfqueue-ga, näiteks kui tunnel on juba konfigureeritud ja FOU kuulab soovitud pordis, ei saa te samast pordist tavapärasel viisil paketti saata - see on hõivatud, kuid Juhuslikult genereeritud paketi saab võtta ja saata otse võrguliidesesse, kasutades töötlemata pesa, kuigi sellise paketi genereerimine nõuab veidi rohkem nokitsemist. Nii luuakse ipipous autentimisega pakette.

Kuna ipipou töötleb ühendusest ainult esimesi pakette (ja neid, millel õnnestus järjekorda lekkida enne ühenduse loomist), ei kannata jõudlus peaaegu üldse.

Niipea, kui ipipou server saab autentitud paketi, luuakse tunnel ja kõik järgnevad ühenduses olevad paketid on juba töödeldud kerneli poolt nfqueue'st mööda minnes. Kui ühenduse loomine ebaõnnestub, siis saadetakse järgmise paketi esimene pakett olenevalt seadistustest nfqueue järjekorda, kui tegemist pole autentimisega paketiga, vaid viimati meelde jäänud IP-st ja kliendipordist, saab selle kas edasi anda sisse või ära visatud. Kui autentitud pakett pärineb uuest IP-st ja pordist, konfigureeritakse tunnel nende kasutamiseks ümber.

Tavalisel IPIP-over-FOU-l on NAT-iga töötamisel veel üks probleem - kaht UDP-sse kapseldatud IPIP tunnelit sama IP-ga ei saa luua, kuna FOU ja IPIP moodulid on üksteisest üsna isoleeritud. Need. sama avaliku IP-aadressi taga olevad kliendid ei saa sel viisil samaaegselt sama serveriga ühendust luua. Tulevikus, ehk, lahendatakse see kerneli tasemel, kuid see pole kindel. Seniks saab NAT-i probleeme lahendada NAT-iga – kui juhtub, et IP-aadresside paar on juba mõne teise tunneli poolt hõivatud, teeb ipipou NAT-i avalikust alternatiivsele privaatsele IP-le, voilaa! - saate luua tunneleid, kuni pordid saavad otsa.

Sest Kõik ühenduses olevad paketid pole allkirjastatud, siis on see lihtne kaitse MITM-i suhtes haavatav, nii et kui kliendi ja serveri vahelisel teel varitseb kaabakas, kes saab liiklust kuulata ja sellega manipuleerida, saab ta autentitud pakette ümber suunata. teise aadressi ja looge tunnel ebausaldusväärsest hostist.

Kui kellelgi on ideid, kuidas seda parandada, jättes suurema osa liiklusest tuumikusse, siis ärge kõhelge sellest rääkima.

Muide, UDP-sse kapseldamine on end väga hästi tõestanud. Võrreldes IP kapseldamisega, on see palju stabiilsem ja sageli ka kiirem, hoolimata UDP päise lisakulust. Selle põhjuseks on asjaolu, et enamik Interneti-hoste töötab hästi ainult kolme populaarseima protokolliga: TCP, UDP, ICMP. Käegakatsutav osa võib kõigest muust täielikult loobuda või seda aeglasemalt töödelda, kuna see on optimeeritud ainult nende kolme jaoks.

Näiteks seepärast loodi QUICK, millel HTTP/3 põhineb, UDP peale, mitte IP peale.

Noh, piisavalt sõnu, on aeg näha, kuidas see "pärismaailmas" töötab.

Lahing

Kasutatakse reaalse maailma jäljendamiseks iperf3. Reaalsuse läheduse osas on see ligikaudu sama, mis Minecraftis reaalse maailma jäljendamine, kuid praegu läheb see korda.

Konkursil osalejad:

  • viide põhikanalile
  • selle artikli kangelane on ipipou
  • OpenVPN autentimisega, kuid ilma krüptimiseta
  • OpenVPN kõikehõlmavas režiimis
  • WireGuard ilma eeljagatud võtmeta, MTU=1440 (alates ainult IPv4-st)

Tehnilised andmed nohikutele
Mõõdikud võetakse järgmiste käskudega:

kliendi kohta:

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"

ICMP latentsus

ping -c 10 SERVER_IP | tail -1

serveris (töötab samaaegselt 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"

Tunneli 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

klient
/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üptimiseta, autentimisega)
server

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

klient

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üptimise, autentimise, UDP kaudu, kõik ootuspäraselt)
Konfigureeritud kasutades openvpn-haldamine

traadikaitse
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

klient
/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

Järeldused

Niiske kole märk
Serveri protsessori koormus ei ole väga soovituslik, sest... Seal töötab palju muid teenuseid, mis mõnikord söövad ressursse:

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

20 Mbps kanal

ipipou: rohkem kui lihtsalt krüptimata tunnel

ipipou: rohkem kui lihtsalt krüptimata tunnel

kanal 1 optimistliku Gbps kohta

ipipou: rohkem kui lihtsalt krüptimata tunnel

ipipou: rohkem kui lihtsalt krüptimata tunnel

Kõigil juhtudel on ipipou jõudluses üsna lähedal põhikanalile, mis on suurepärane!

Krüptimata openvpn tunnel käitus mõlemal juhul üsna kummaliselt.

Kui keegi kavatseb seda testida, on huvitav kuulda tagasisidet.

Olgu IPv6 ja NetPrickle meiega!

Allikas: www.habr.com

Lisa kommentaar