ipipou: më shumë se thjesht një tunel i paenkriptuar

Çfarë i themi Zotit IPv6?

ipipou: më shumë se thjesht një tunel i paenkriptuar
E drejta, dhe Zotit të enkriptimit sot do t'i themi të njëjtën gjë.

Këtu do të flasim për tunelin IPv4 të pa enkriptuar, por jo për atë "të ngrohtë dhe të nostalgjik", por për atë modern "me LED". Gjithashtu, këtu shfaqen soketët e papërfunduar, dhe bëhet punë me paketat në hapësirën e përdoruesit.

Ka N protokolle tunelimi për çdo shije dhe ngjyrë:

  • stilistik, moderen, rinor WireGuard
  • multifunksionale, si thikat zvicerane, OpenVPN dhe SSH
  • i vjetër dhe jo i keq GRE
  • maksimalisht i thjeshtë, i shpejtë, krejtësisht i pa enkriptuar IPIP
  • duke u zhvilluar aktivisht GENEVE
  • një numër të madh të tjerëve.

Por unë jam programues, prandaj do të rrit N-në vetëm pak, dhe zhvillimin e protokolleve të vërtetë do ta lë për zhvilluesit e vërtetë.

Në një që nuk ka lindur ende projektin, për të cilin po punoj tani, duhet të arrij te hostet përtej NAT-it nga jashtë. Duke përdorur për këtë protokolle me kriptografi të rritur, nuk më ka lënë ndjenja se është si të gjuash me armë për merimanga. Duke qenë se tuneli përdoret kryesisht vetëm për të bërë një vrimë në NAT, trafiku i brendshëm gjithashtu zakonisht është i enkriptuar, prapëseprapë, pritet për HTTPS.

Duke eksploruar protokollet e ndryshme të tunelimit, vëmendjen e perfekcionistit tim të brendshëm e tërheq vazhdimisht IPIP për shkak të kostove të tij minimale.

  • Por ai ka një dhe një gjysmë mangësish thelbësore për detyrat e mia:
  • ai kërkon IP publike në të dy anët,

dhe asnjë autentifikim.

Prandaj, perfekcionisti u mbyll prapa në një qoshe të errët të kutisë së tij të kokës, ose ku ndodhet ai. Dhe kështu një herë, duke lexuar artikuj mbi tunelat e mbështetur natyrshëm

në Linux, u ndesha me FOU (Foo-over-UDP), dmth. diçka e rastësishme, e mbështjellë në UDP. Deri tani, nga çfarëdo e rastësishme mbështeten vetëm IPIP dhe GUE (Encapsulimi i përgjithshëm UDP).

"Ja, ajo është kula e argjendtë! Më mjafton edhe IPIP i thjeshtë." - mendoja unë.

Në realitet, kula doli të jetë jo krejtësisht e argjendtë. Inkasulimi në UDP zgjidh problemin e parë - mund të lidhemi me klientët pas NAT-it nga jashtë duke përdorur një lidhje të vendosur paraprakisht, por këtu gjysma e mangësisë tjetër të IPIP del në një dritë të re - pas IP-ve dhe portit publik të dukshëm të klientit mund të fshihet kushdo nga një rrjet privat (në IPIP të pastër, ky problem nuk ekziston). Për të zgjidhur këtë problem të pjesshëm lindi utilitaAty është implementuar një mekanizëm autentikimi për hostin e largët, pa penguar funksionimin e FOU-t bërthamor, i cili do të përpunojë paketat me shpejtësi dhe efikasitet në hapësirën e bërthamës.

Nuk e nevojmë skriptin tënd!

OK, nëse di publikun port dhe IP-në e klientit (për shembull, ata nuk shkojnë askund pa limit, NAT përpiqet të hartojë portet 1-ndaj-1), mund të krijosh një tunel IPIP-over-FOU me komandat e mëposhtme, pa asnjë skript.

në server:

# Подгрузить модуль ядра 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

në klient:

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

# Opsionet local, peer, peer_port, dev mund të mos mbështeten nga bërthamat e vjetra, mund t'i anashkalosh.
# peer dhe peer_port përdoren për të krijuar lidhjen menjëherë gjatë krijimit të FOU-listener-it.
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

ku

  • ipipou* — emri i ndërfaqes lokale të tunelit të rrjetit
  • 203.0.113.1 — IP publike e serverit
  • 198.51.100.2 — IP publike e klientit
  • 192.168.0.2 — IP e klientit, e caktuar për ndërfaqen eth0
  • 10001 — porti lokal i klientit për FOU
  • 20001 — porti publik i klientit për FOU
  • 10000 — porti publik i serverit për FOU
  • encap-csum — opsion për të shtuar një checksum UDP në paketat UDP të inkapsuluara; mund të zëvendësohet me noencap-csum, që të mos llogaritet, e integriteti kontrollohet nga shtresa e jashtme e inkapsulimit (ndërsa paketa ndodhet brenda tunelit)
  • eth0 — ndërfaqja lokale me të cilën do të lidhet tuneli ipip
  • 172.28.0.1 — IP e ndërfaqes tunel të klientit (privat)
  • 172.28.0.0 — IP e ndërfaqes tunel të serverit (privat)

Përsa kohë që lidhja UDP është aktive, tuneli do të jetë në gjendje funksionale, dhe sa herë që pritet, siç do të ndodhë — nëse IP: porti i klientit mbetet i njëjtë — do të jetojë, ndryshohet — do të pritet.

Kthimi mbrapsht është më i thjeshtë duke shkarkuar modulat e bërthamës: modprobe -r fou ipip

Edhe nëse autentikimi nuk është i nevojshëm, IP-të dhe porti publik i klientit nuk janë gjithnjë të njohura dhe shpesh janë të papërcaktuara ose të ndryshueshme (varësisht nga lloji i NAT). Nëse anashkalohet encap-dport në anën e serverit, tuneli nuk do të funksionojë, nuk është aq i zgjuar sa të marrë portin e largët të lidhjes. Në këtë rast, ipipou gjithashtu mund të ndihmojë, ose WireGuard dhe njësoj me të në ndihmën tënde.

Si funksionon kjo?

Klienti (çfarë zakonisht ndodh pas NAT-it) ngrit një tunel (si në shembullin më sipër) dhe dërgon një paketë me autentifikim në server, në mënyrë që ai të konfigurojë tunelin nga ana e tij. Në varësi të konfigurimeve, kjo mund të jetë një paketë bosh (thjesht për ta bërë serverin të shohë IP-të publike: portin e lidhjes), ose me të dhëna me të cilat serveri mund të identifikojë klientin. Të dhënat mund të jenë një frazë fjalëkalimi e thjeshtë në tekst të hapur (më vjen në mendje analogjia me HTTP Basic Auth) ose të dhëna të nënshkruara me çelësin privat (si HTTP Digest Auth, vetëm më e fortë, shih funksionin client_auth në kod).

Në server (ana me IP publike) kur ipipou nis, krijon një trajtues radhesh nfqueue dhe konfiguronte netfilter për të drejtuar paketat e nevojshme në vendin e duhur: paketat që inicializojnë lidhjen në radhën nfqueue, dhe [gati] të gjitha të tjerat drejtpërdrejt te dëgjuesi FOU.

Kush nuk e di, nfqueue (ose NetfilterQueue) është një gjë speciale për amatorët, që nuk dinë të zhvillojnë module bërthamore, e cila me ndihmën e netfilter (nftables/iptables) lejon të drejtohen paketat e rrjetit në hapësirën e përdoruesit dhe të përpunohen atje me mjete primitive: të modifikohen (opsionalisht) dhe t'i kthehen prapa bërthamës, ose të hidhen poshtë.

Për disa gjuhë programimi ka lidhje për të punuar me nfqueue, për bash nuk u gjet asgjë (ha, nuk është befasi), kështu që duhej të përdorja python: ipipou përdor NetfilterQueue.

Nëse performanca nuk është kritike, me ndihmën e kësaj gjëje mund të krijosh relativisht shpejt dhe lehtë logjikën tënde për të punuar me paketat në një nivel mjaft të ulët, për shembull të krijosh protokolle eksperimentale të transferimit të të dhënave, ose të irritosh shërbimet lokale dhe të largëta me sjellje jostandarde.

Krah për krah me nfqueue punojnë soketët e papërpunuar (raw sockets), për shembull kur tuneli tashmë është konfiguruar, dhe FOU dëgjon në portin e nevojshëm, dërgimi i një pakete nga ky port nuk do të funksionojë - është i zënë, por mund të marrësh dhe të dërgosh një paketë të gjeneruar rastësisht drejtpërdrejt në ndërfaqen e rrjetit duke përdorur një soket të papërpunuar, edhe pse do të duhet pak më shumë punë për të gjeneruar një paketë të tillë. Kështu krijohen në ipipou paketat me autentifikim.

Pasi që ipipou përpunon vetëm paketat e para nga lidhja (dhe ato që kanë arritur të kalojnë në radhë para vendosjes së lidhjes), performanca nuk pëson pothuajse asnjë dëmtim.

Sa herë që serveri ipipou merr një paketë që kalon autentikimin, krijohet një tunel dhe të gjitha paketat e mëpasshme në lidhje përpunohen nga bërthama duke kaluar përmes nfqueue. Nëse lidhja ka skaduar, paketa e parë e ardhshme do të drejtohet në radhën nfqueue, në varësi të konfigurimeve; nëse kjo nuk është një paketë me autentikim, por nga adresa IP dhe porta e fundit e mbajtur të klientit, ajo mund të kalojë më tej ose të hidhet poshtë. Nëse një paketë e autentikuar vjen nga një IP dhe port i ri, tuneli ri-konfigurohet për t'i përdorur ato.

IPIP-over-FOU ka një problem tjetër kur punon me NAT — nuk është e mundur të krijosh dy tunelë IPIP të inkapsuluar në UDP me IP të njëjtë, sepse modulet FOU dhe IPIP janë mjaft të izoluara nga njëra-tjetra. Pra, një çift klientësh me një IP publik nuk mund të lidhesh në të njëjtin server në këtë mënyrë në të njëjtën kohë. Në të ardhmen, është i mundur, problemi do të zgjidhet në nivelin bërthamor, por kjo nuk është e sigurt. Ndërkohë, problemet me NAT mund të zgjidhen me NAT — nëse ndodh që një çift adresash IP të jetë tashmë i zënë nga një tunel tjetër, ipipou do të bëjë NAT nga IP publik në një IP privat alternativ, dhe ja! — mund të krijohen tunelë derisa portet të mos përfundojnë.

Duke marrë parasysh se jo të gjitha paketat në lidhje janë të nënshkruara, kjo mbrojtje e thjeshtë është e prekshme ndaj MITM, kështu që nëse një keqbërës është fshehur në rrugën midis klientit dhe serverit, ai mund të dëgjojë trafikun dhe ta menaxhojë, duke alokuar paketat me autentikim në një adresë tjetër dhe duke krijuar një tunel nga një host të paqartë.

Nëse dikush ka ide se si ta rregullojë këtë duke lënë pjesën kryesore të trafikut në bërthamë, mos ngurroni — shprehni mendimin tuaj.

Për ta thënë, inkapsulimi në UDP ka dhënë rezultate shumë të mira. Krahasuar me inkapsulimin mbi IP, është shumë më i qëndrueshëm dhe shpesh më i shpejtë pavarësisht shpenzimeve të shtesave për kokën UDP. Kjo ndodhur për shkak se në internet, shumica e hosteve operojnë më mirë me tre protokollet më të njohura: TCP, UDP, ICMP. Një pjesë e konsiderueshme mund edhe të hedhë poshtë çdo gjë tjetër, ose të përpunojë më ngadalë, sepse është optimizuar vetëm për këto tre.

Për shembull, prandaj QUICK, mbi të cilin është ndërtuar HTTP/3, u krijua saktësisht mbi UDP, dhe jo mbi IP.

Po, mjaft me fjalët, është koha të shikojmë se si funksionon në "botën reale".

Beteja

Për të imituar botën reale përdoret iperf3. Në shkallën e afërsisë me realitetin, kjo është përafërsisht si imtimi i botës reale në Minecraft, por për momentin është e pranueshme.

Në garë marrin pjesë:

  • kanali kryesor referencë
  • heroina e këtij artikulli ipipou
  • OpenVPN me autentifikim, por pa enkriptim
  • OpenVPN në modalitetin "gjithçka e përfshirë"
  • WireGuard pa PresharedKey, me MTU=1440 (pasi është vetëm IPv4)

Të dhënat teknike për geekët
Metritë merren me këto komandë

në klient:

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"
# Ku "-b 12M" është kapaciteti i kanalit kryesor, i ndarë me numrin e rrjedhave "-P", për të mos krijuar paketa të panevojshme dhe për të mos prishur performancën.

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"

Latenca ICMP

ping -c 10 SERVER_IP | tail -1

në server (në ekzekutim njëkohësisht me klientin):

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"

Konfigurationsi i tuneleve

Për të zgjidhur këtë problem të pjesshëm lindi utilita
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
# public key of auth-key-b64: eQYNhD/Xwl6Zaq+z3QXDzNI77x8CEKqY1n5kt9bKeEI=
auth-key-b64 RuBZkT23na2Q4QH1xfmZCfRgSgPt5s362UPAFbecTso=
auth-secret topsecret
keepalive 27
verb 3

systemctl start ipipou@client

openvpn (pa enkriptim, me autentifikim)
server

openvpn --genkey --secret ovpn.key  # Pas kësaj duhet ta dërgoni ovpn.key klientit
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 (me enkriptim, autentifikim, përmes UDP, ashtu si duhet)
I konfiguruar duke përdorur openvpn-manage

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

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

Rezultatet

Një tabelë e çuditshme dhe e çrregullt
Ngarkesa e CPU-së së serverit nuk është shumë treguese, pasi aty ekzekutohen shumë shërbime të tjera dhe ndonjëherë ato konsumojnë burime:

proto bandwidth[Mbps] CPU_idle_client[%] CPU_idle_server[%]
# 20 Mbps kanal nga mikrokompjuter (4 core) deri te VPS (1 core) përmes Atlantikut
# 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 (autentifikim vetëm, pa enkriptim)
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 (enkriptim i plotë, autentifikim, etj)
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

## kanal rreth 1Gbps mes VPS në Evropë dhe SHBA (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 (autentifikim vetëm, pa enkriptim)
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

kanal me 20 Mbps

ipipou: më shumë se thjesht një tunel i paenkriptuar

ipipou: më shumë se thjesht një tunel i paenkriptuar

kanal me 1 Gbps optimist

ipipou: më shumë se thjesht një tunel i paenkriptuar

ipipou: më shumë se thjesht një tunel i paenkriptuar

Në të gjitha rastet, ipipou është mjaft afër performancës së kanalit bazë, dhe kjo është e shkëlqyer!

Tuneli openvpn i pa enkriptuar u soll mjaft çuditshëm në të dy rastet.

Nëse dikush planifikon ta provojë, do të ishte interesante të dëgjoja mendimet.

Qofshin me ne IPv6 dhe NetPrickle!

Burimi: habr.com

Blini hosting të besueshëm për faqe interneti me mbrojtje nga DDoS, serverë VPS VDS 🔥 Blini hosting të besueshëm për faqe interneti me mbrojtje nga DDoS, serverë VPS VDS | ProHoster