ipipou: rohkem kui lihtsalt krüpteerimata tunnel

Mida me ütleme IPv6 jumalale?

ipipou: rohkem kui lihtsalt krüpteerimata tunnel
Õige, ja ka krüptimise jumalale ütleme täna sama.

Siin räägitakse dekrüpteerimata IPv4 tunnelist, aga mitte "soe lamp" versioonist, vaid modernsest "LED" variandist. Siin vilguvad ka toored soketid ja käib töö pakettidega kasutaja ruumis.

On N tunneliprotokolli igale maitsele ja värvile:

  • stiilne, moes, noortepärane WireGuard
  • mitmeotstarbelised, nagu Šveitsi noad, OpenVPN ja SSH
  • vana ja mitte kuri GRE
  • maksimaalselt lihtne, kiire, täiesti dekrüpteerimata IPIP
  • aktiivselt arenev GENEVE
  • paljude teistega.

Aga olen arendaja, seega suurendan N vaid veidi ning jätan tõeliste protokollide arendamise Ъ-developers'ile.

Ühes veel sündimata projektis, millega praegu tööd teen, peab tungima NAT-i taga olevate hostide juurde. Kasutades selleks küpse krüptograafiaga protokolle, ei lahkunud mind tunne, et see on nagu relvaga linnukese pihta tulistamine. Kuna tunnelit kasutatakse peamiselt ainult NAT-is auku puurimiseks, on sisene liiklus tavaliselt samuti krüpteeritud, siiski on toetust HTTPS-ile.

Uurides erinevaid tunneldusprotokolle tõmbas mu sisemine perfektsionist korduvalt tähelepanu IPIP-le, kuna selle kulud on minimaalsed. Kuid sellel on minu ülesannete jaoks kaks olulist puudust:

  • see nõuab avalikke IP-aadresse mõlemal pool,
  • ja autentimist pole.

Seetõttu surus perfektsionist end tagasi kolju tumedasse nurka, või kus ta seal istub.

Ja ühel hetkel, lugedes artikleid natiivsetest tunneldustest Linuxis, sattusin FOU (Foo-over-UDP) peale, st miski, mis on UDP-sse mähitud. Praegu toetatakse midagi sarnast ainult IPIP ja GUE (Generic UDP Encapsulation).

«Siin see on, hõbedane kuul! Lihtsast IPIP-st piisab.» — mõtlesin ma.

Tegelikkuses osutus kuul mitte täiesti hõbedaseks. UDP-sse kapseldamine lahendab esimese probleemi — NAT-iga klientide kohta on võimalik väljastpoolt sisse ühenduda, kasutades eelnevalt seadistatud ühendust, kuid siinkohal paistab IPIP järgmise poole probleemi uus valgus — nähtavate avalike IP ja kliendi pordi taga võib peituda keegi igasugusest privaatvõrgust (puhtas IPIP-is sellist probleemi pole).

Selle pooliku probleemi lahendamiseks sündis utiliit ipipou. Sell on ain on saske leen konstruktsii, mis jääb kernelt FOU ja töötleb tõhusalt pakette kernelis.

Sinu skripti ei vajata!

Okei, kui tead kliendi avalikku porti ja IP-aadressi (näiteks, kuna nad ei liigu kuhugi, NAT püüab kaardistada pordid 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 ei pruugi vanemate tuumadega toetada, neid võib jätta vahele.
# peer ja peer_port kasutatakse ühenduse loomiseks kohe FOU-listener'i 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 nimi
  • 203.0.113.1 — serveri avalik IP
  • 198.51.100.2 — kliendi avalik IP
  • 192.168.0.2 — IP, mis on antud liidesele eth0
  • 10001 — kliendi lokaalne port FOU jaoks
  • 20001 — kliendi avalik port FOU jaoks
  • 10000 — serveri avalik port FOU jaoks
  • encap-csum — võimalus lisada UDP-pakettidesse sissetoodud kontrollsumma; saab asendada noencap-csum, et mitte arvesse võtta, sest terviklikkust kontrollitakse välise kapslitava kihi poolt (niikaua kui pakett on tunneli sees)
  • eth0 — lokaalsete liideste, kuhu ipip tunneli sidumine toimub
  • 172.28.0.1 — kliendi IP tunneli liides (privaatne)
  • 172.28.0.0 — serveri IP tunneli liides (privaatne)

Nii kaua, kui UDP-ühendus on aktiivne, jääb tunnel tööle, kuid kui see katkeb, siis sõltub see õnnest — kui IP: kliendi port jääb samaks — siis elab see, aga kui muutub — katkeb.

Kõige lihtsam on kõik tagasi pöörata, laadides moodulid tuumast välja: modprobe -r fou ipip

Isegi kui autentimine ei ole nõutav, ei ole avalikud IP-d ja kliendi port alati teada ja need on sageli ettearvamatud või muutlikud (oleneb NAT tüübist). Kui jätta välja encap-dport serveri küljest, ei tööta tunnel, see ei ole nii tark, et võtta kaugühenduse porti. Sellisel juhul võib ipipou samuti aidata, või WireGuard ja sellega sarnased lahendused aitavad sind.

Kuidas see töötab?

Klient (kes tavaliselt asub NAT-i taga) loob tunnelit (nagu eespool näidatud) ja saadab paketi autentimisega serverisse, et see saaks tunnelit oma poolt seadistada. Olenevalt seadistustest võib see olla tühi pakett (lihtsalt, et server näeks avalikke IP-aadresse ja ühenduse porti) või andmetega, mille alusel server suudab klienti tuvastada. Andmed võivad olla lihtne tekstipõhine paroolifraas (mida võib võrrelda HTTP Basic Auth'iga) või allkirjastatud erikujulised andmed privaatvõtmega (sarnane HTTP Digest Auth'ile, aga tugevam, vt funktsiooni client_auth koodis).

Serveris (pool, millel on avalik IP) käivitades ipipou loob see nfqueue järjekorra töötleja ja seadistab netfilter'i nii, et vajalikud paketid saadetakse õigesse kohta: ühenduse loomise pakettide järjekord nfqueue'sse ja [peaaegu] kõik muud otse listener FOU-sse.

Needless to say, nfqueue (or NetfilterQueue) is a special thing for amateurs who don't know how to develop kernel modules. It allows, using netfilter (nftables/iptables), to redirect network packets into user space and process them there with simple improvised tools: modify (optionally) and return them to the kernel, or drop them.

For some programming languages, there are bindings to work with nfqueue, but for bash, none were found (not surprising), so I had to use Python: ipipou uses NetfilterQueue.

If performance is not critical, this tool allows you to relatively quickly and easily create your own packet processing logic at a fairly low level, for example, to craft experimental data transfer protocols or to troll local and remote services with unconventional behavior.

Koos nfqueue'iga töötavad toorsoketid (raw sockets), näiteks kui tunnel on juba seadistatud ja FOU kuulab õiget porti, tavapäraselt ei saa paketti sellelt portilt saata — see on hõivatud, kuid võid võtta ja saata juhuslikult genereeritud paketi otse võrguliidesesse, kasutades toorsoketti, kuigi sellise paketi genereerimisega tuleb veidi rohkem vaeva näha. Nii luuakse ipipou's autentimisega pakette.

Kuna ipipou töötleb ainult ühenduse esimesi pakette (no ja need, mis on enne ühenduse loomist järjekorda sattunud), ei ole jõudlus peaaegu puudulik.

Kui ipipou-server saab autentitud paki, luuakse tunnel ja kõik järgnevad paketid ühenduses töödeldakse juba tuumast mööda nfq'd. Kui ühendus aegub, suunatakse järgmise esimene pakett nfq järjekorda, sõltuvalt seadistustest: kui see pole autentimise paketiga, vaid viimase salvestatud kliendi IP ja pordiga, võib see minna kas edasi või ära visata. Kui autentitud pakett tuleb uue IP ja pordi kaudu, kohandatakse tunnel nende kasutamiseks.

Tavalise IPIP-over-FOU korral on veel üks probleem NAT-i kasutamisel — ei saa luua kahte IPIP tunnelit UDP-sse pakendatuna sama IP-ga, kuna FOU ja IPIP moodulid on piisavalt isoleeritud üksteisest. See tähendab, et paar klienti ühe avaliku IP taga ei saa sel viisil samal ajal ühe serveriga ühenduda. Tulevikus, on võimalik, lahendatakse see tuuma tasemel, kuid see pole kindel. Seni saab NAT-i probleeme lahendada NAT-iga — kui juhtub, et paar IP-aadressi on juba hõivatud teise tunneliga, teeb ipipou NAT-i avalikust alternatiivseks privaatseks IP-ks, voilà! — tunnelite loomine on võimalik, kuni pordid otsa saavad.

Kuna kõik paketid ei ole ühenduses allkirjastatud, on see lihtne kaitse MITM-i vastu haavatav, seega kui kliendi ja serveri vahel varitseb kurjategija, kes võib liiklust kuulata ja seda juhtida, võib ta autentimisega paketid suunata teise aadressi kaudu ja luua tunneli usaldusväärselt hostilt.

Kui kellelgi on ideid, kuidas seda parandada, hoides enamikku liiklusest tuumas, siis ärge kartke — väljendage end.

Muide, UDP kapseldamine on väga hästi tõestanud oma väärtust. Võrreldes kapseldamisega IP kohal, on see palju stabiilsem ja sageli kiirem, vaatamata täiendavatele kuludele UDP päises. See tuleneb sellest, et Internetis töötab enamik hoste korralikult ainult kolmel kõige populaarsemal protokollil: TCP, UDP, ICMP. Oluliselt suur osa võib üldse kõik muu kõrvale jätta või töödelda aeglasemalt, kuna see on optimeeritud vaid nende kolme jaoks.

Näiteks seetõttu loodi QUICK, millel põhineb HTTP/3, just UDP peal, mitte IP peal.

Noh, piisab sõnadest, on aeg näha, kuidas see toimib „reaalses maailmas”.

Lahing

Reaalmaailma simuleerimiseks kasutatakse iperf3. Lähedus tegelikkusele on umbes nagu reaalse maailma emuleerimine Mängu maailmas, kuid hetkel piisab.

Võistluses osalevad:

  • standardne peakanal
  • artikli kangelane ipipou
  • OpenVPN autentsusega, kuid krüpteerimata
  • OpenVPN „kõik-ühes” režiimis
  • WireGuard ilma PresharedKey'ita, MTU=1440 (kuna ainult IPv4)

Tehnilised andmed geekidele
Mõõdikud 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 ribalaius, jagatud voogude arvu "-P" järgi, et üleliigseid pakette mitte genereerida ja mitte jõudlust rikkuda.

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 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"

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

kliendi
/etc/ipipou/client.conf:

kliendi
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üpti, autentimisega)
server

openvpn --genkey --secret ovpn.key  # Seejärel tuleb ovpn.key kliendile edastada
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

kliendi

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üptimisega, autentimisega, UDP kaudu, kõik nagu peab)
Seadistatud kasutades 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

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

Toores kole tabel
Serveri CPU koormus ei ole väga näitlik, kuna seal töötab palju teisi teenuseid, mis aeg-ajalt tarbivad ressursse:

proto laiuse[Mbps] CPU_idle_client[%] CPU_idle_server[%]
# 20 Mbps kanal mikrokontrollerilt (4 tuuma) kuni VPS-ini (1 tuum) üle Atlandi
# puhas
UDP 20.4      99.80 93.34
TCP 19.2      99.67 96.68
ICMP latentsus 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 latentsus min/avg/max/mdev = 199.562/208.919/220.222/7.905 ms
# openvpn0 (ainult autentimine, krüpteerimist pole)
UDP 19.3      99.89 72.90
TCP 16.1      95.95 88.46
ICMP latentsus min/avg/max/mdev = 191.631/193.538/198.724/2.520 ms
# openvpn (täiskrüpteeritud, autentimine jne)
UDP 19.6      99.75 72.35
TCP 17.0      94.47 87.99
ICMP latentsus 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 latentsus min/avg/max/mdev = 217.925/223.601/230.696/3.266 ms

## umbes-1Gbps kanal VPS Europa ja USA vahel (1 tuum)
# puhas
UDP 729      73.40 39.93
TCP 363      96.95 90.40
ICMP latentsus 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 latentsus min/avg/max/mdev = 107.444/107.523/107.648/0.058 ms
# openvpn0 (ainult autentimine, krüpteerimist pole)
UDP 193      17.51  1.62
TCP  12      95.45 92.80
ICMP latentsus 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 latentsus min/avg/max/mdev = 107.616/107.788/108.038/0.128 ms

20 Mbps kanal

ipipou: rohkem kui lihtsalt krüpteerimata tunnel

ipipou: rohkem kui lihtsalt krüpteerimata tunnel

1 optimistlik Gbps kanal

ipipou: rohkem kui lihtsalt krüpteerimata tunnel

ipipou: rohkem kui lihtsalt krüpteerimata tunnel

Käesolevas osas on ipipou tulemused põhilise kanali tulemusele üsna lähedased, ja see on suurepärane!

Krüpteerimata openvpn tunnel käitus kummaliselt mõlemas olukorras.

Kui keegi kavatseb testida, oleks huvitav kuulda tagasisidet.

Olgu meiega IPv6 ja NetPrickle!

Allikas: habr.com

Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster