ipipou: več kot le nešifriran tunel

Kaj sporočamo bogu IPv6?

ipipou: več kot le nešifriran tunel
Tako je, danes bomo enako rekli bogu šifriranja.

Tukaj bomo govorili o nešifriranem tunelu IPv4, vendar ne o "topli svetilki", ampak o sodobnem "LED". Tu utripajo tudi neobdelane vtičnice in poteka delo s paketi v uporabniškem prostoru.

Obstaja N protokolov tuneliranja za vsak okus in barvo:

  • stilsko, modno, mladostno WireGuard
  • večnamenski, kot so švicarski noži, OpenVPN in SSH
  • stari in ne zlobni GRE
  • najbolj preprost, hiter, popolnoma nešifriran IPIP
  • aktivno razvijajo ŽENEV
  • mnogi drugi.

Sem pa programer, zato bom N povečal le za delček, razvoj pravih protokolov pa prepustil razvijalcem Kommersanta.

V enem še nerojenem projektKar zdaj počnem, je doseči gostitelje za NAT od zunaj. Če sem za to uporabil protokole s kriptografijo za odrasle, se nisem mogel otresti občutka, da je to kot streljanje vrabcev iz topa. Ker tunel se uporablja večinoma samo za luknjanje v NAT-e, interni promet je običajno tudi šifriran, a se še vedno utapljajo v HTTPS.

Med raziskovanjem različnih protokolov tuneliranja je pozornost mojega notranjega perfekcionista znova in znova pritegnil IPIP zaradi minimalnih stroškov. Vendar ima eno in pol pomembne pomanjkljivosti za moje naloge:

  • zahteva javne IP-je na obeh straneh,
  • in brez preverjanja pristnosti za vas.

Zato je bil perfekcionist vrnjen v temni kot lobanje oziroma kamor koli tam sedi.

In potem nekega dne, med branjem člankov o izvorno podprti tuneli v Linuxu sem naletel na FOU (Foo-over-UDP), tj. karkoli, zavito v UDP. Zaenkrat sta podprta samo IPIP in GUE (Generic UDP Encapsulation).

»Tukaj je srebrna krogla! Zame je dovolj preprost IPIP.” - Mislil sem.

Pravzaprav se je izkazalo, da krogla ni popolnoma srebrna. Enkapsulacija v UDP rešuje prvo težavo – z vnaprej vzpostavljeno povezavo se lahko povežete z odjemalci za NAT od zunaj, tu pa polovica naslednje pomanjkljivosti IPIP zacveti v novi luči – kdorkoli iz zasebnega omrežja se lahko skrije za vidno javni IP in vrata odjemalca (pri čistem IPIP ta problem ne obstaja).

Za rešitev te težave in pol se je rodil pripomoček ipipou. Implementira domač mehanizem za avtentikacijo oddaljenega gostitelja, ne da bi motil delovanje jedra FOU, ki bo hitro in učinkovito obdelal pakete v prostoru jedra.

Ne potrebujemo tvojega scenarija!

V redu, če poznate javna vrata in IP odjemalca (na primer, vsi za njim ne gredo nikamor, NAT poskuša preslikati vrata 1-v-1), lahko ustvarite tunel IPIP-over-FOU z naslednje ukaze, brez skriptov.

na strežniku:

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

na stranki:

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

če

  • ipipou* — ime vmesnika lokalnega tunelskega omrežja
  • 203.0.113.1 — javni IP strežnik
  • 198.51.100.2 — javni IP odjemalca
  • 192.168.0.2 — IP odjemalca, dodeljen vmesniku eth0
  • 10001 — vrata lokalnega odjemalca za FOU
  • 20001 — vrata javnega odjemalca za FOU
  • 10000 — vrata javnega strežnika za FOU
  • encap-csum — možnost dodajanja kontrolne vsote UDP enkapsuliranim paketom UDP; se lahko nadomesti z noencap-csum, da ne omenjam, celovitost že nadzoruje zunanja enkapsulacijska plast (medtem ko je paket znotraj tunela)
  • eth0 — lokalni vmesnik, na katerega bo vezan tunel ipip
  • 172.28.0.1 — IP vmesnika odjemalskega tunela (zasebno)
  • 172.28.0.0 — Vmesnik IP tunelskega strežnika (zasebno)

Dokler je povezava UDP živa, bo predor deloval, če pa se pokvari, boste imeli srečo - če odjemalčeva IP: vrata ostanejo enaka - bo živela, če se spremenijo - se bo pokvarila.

Najlažji način, da vse vrnete nazaj, je, da razložite module jedra: modprobe -r fou ipip

Tudi če preverjanje pristnosti ni potrebno, odjemalčev javni IP in vrata niso vedno znani in so pogosto nepredvidljivi ali spremenljivi (odvisno od vrste NAT). Če izpustite encap-dport na strani strežnika tunel ne bo deloval, ni dovolj pameten, da bi prevzel vrata za oddaljeno povezavo. V tem primeru lahko pomaga tudi ipipou ali WireGuard in njemu podobni.

Kako deluje?

Odjemalec (ki je običajno za NAT) odpre tunel (kot v zgornjem primeru) in strežniku pošlje paket za preverjanje pristnosti, tako da konfigurira tunel na svoji strani. Odvisno od nastavitev je to lahko prazen paket (samo, da strežnik vidi javni IP: port povezave) ali s podatki, po katerih lahko strežnik identificira odjemalca. Podatki so lahko preprosto geslo v jasnem besedilu (na misel pride analogija s HTTP Basic Auth) ali posebej zasnovani podatki, podpisani z zasebnim ključem (podobno HTTP Digest Auth, le močnejše, glejte funkcijo client_auth v kodi).

Na strežniku (na strani z javnim naslovom IP), ko se ipipou zažene, ustvari upravljalnik čakalne vrste nfqueue in konfigurira netfilter, tako da so potrebni paketi poslani, kamor bi morali biti: paketi inicializirajo povezavo s čakalno vrsto nfqueue in [skoraj] vse ostalo gre naravnost k poslušalcu FOU.

Za tiste, ki se ne spoznajo, je nfqueue (ali NetfilterQueue) posebna zadeva za amaterje, ki ne znajo razvijati modulov jedra, ki z uporabo netfilterja (nftables/iptables) omogoča preusmeritev omrežnih paketov v uporabniški prostor in njihovo obdelavo tam z primitivna sredstva pri roki: spremenite (neobvezno) in ga vrnite jedru ali zavrzite.

Za nekatere programske jezike obstajajo vezave za delo z nfqueue, za bash jih ni bilo (heh, ni presenetljivo), moral sem uporabiti python: ipipou uporablja NetfilterQueue.

Če zmogljivost ni kritična, lahko s to stvarjo razmeroma hitro in enostavno sestavite lastno logiko za delo s paketi na dokaj nizki ravni, na primer ustvarite eksperimentalne protokole za prenos podatkov ali nadzirate lokalne in oddaljene storitve z nestandardnim vedenjem.

Neobdelane vtičnice delujejo z roko v roki z nfqueue, na primer, ko je tunel že konfiguriran in FOU posluša na želenih vratih, ne boste mogli poslati paketa iz istih vrat na običajen način - zasedena so, vendar lahko vzamete in pošljete naključno generiran paket neposredno v omrežni vmesnik z uporabo neobdelane vtičnice, čeprav bo generiranje takega paketa zahtevalo malo več poigravanja. Tako se ustvarijo paketi z avtentikacijo v ipipou.

Ker ipipou obdela le prve pakete iz povezave (in tiste, ki so uspeli uhajati v čakalno vrsto, preden je bila povezava vzpostavljena), zmogljivost skoraj ne trpi.

Takoj, ko strežnik ipipou prejme overjen paket, se ustvari tunel in vse naslednje pakete v povezavi že obdela jedro mimo nfqueue. Če povezava ne uspe, bo prvi paket naslednjega poslan v čakalno vrsto nfqueue, odvisno od nastavitev, če ne gre za paket z avtentikacijo, ampak iz zadnjega shranjenega IP-ja in vrat odjemalca, se lahko posreduje bodisi vklopljen ali zavržen. Če preverjeni paket prihaja z novega naslova IP in vrat, se predor ponovno konfigurira za njihovo uporabo.

Običajni IPIP-over-FOU ima pri delu z NAT še eno težavo - nemogoče je ustvariti dva tunela IPIP, inkapsulirana v UDP z istim IP-jem, ker sta modula FOU in IPIP precej izolirana drug od drugega. Tisti. par odjemalcev za istim javnim IP-jem se na ta način ne bo mogel istočasno povezati z istim strežnikom. V prihodnosti, morda, bo rešeno na ravni jedra, vendar to ni gotovo. Medtem lahko težave z NAT reši NAT - če se zgodi, da je par naslovov IP že zaseden z drugim tunelom, bo ipipou naredil NAT iz javnega v alternativni zasebni IP, voila! - lahko ustvarite tunele, dokler ne zmanjka vrat.

Ker Niso vsi paketi v povezavi podpisani, potem je ta preprosta zaščita ranljiva za MITM, tako da, če se na poti med odjemalcem in strežnikom skriva zlobnež, ki lahko posluša promet in z njim manipulira, lahko preusmeri overjene pakete prek drug naslov in ustvarite tunel iz nezaupljivega gostitelja.

Če ima kdo ideje, kako to popraviti, pri tem pa pustiti večji del prometa v jedru, ne oklevajte in spregovorite.

Mimogrede, enkapsulacija v UDP se je zelo dobro izkazala. V primerjavi z enkapsulacijo prek IP je veliko bolj stabilna in pogosto hitrejša kljub dodatnim obremenitvam glave UDP. To je posledica dejstva, da večina gostiteljev na internetu dobro deluje samo s tremi najbolj priljubljenimi protokoli: TCP, UDP, ICMP. Oprijemljivi del lahko vse ostalo popolnoma zavrže ali pa počasneje predela, ker je optimiziran le za te tri.

Na primer, zato je bil QUICK, na katerem temelji HTTP/3, ustvarjen na vrhu UDP in ne na vrhu IP.

No, dovolj besed, čas je, da vidimo, kako deluje v "resničnem svetu".

Bitka

Uporablja se za posnemanje resničnega sveta iperf3. Kar zadeva stopnjo bližine realnosti, je to približno enako kot posnemanje resničnega sveta v Minecraftu, vendar bo zaenkrat dovolj.

Udeleženci tekmovanja:

  • referenčni glavni kanal
  • junak tega članka je ipipou
  • OpenVPN z avtentikacijo, vendar brez šifriranja
  • OpenVPN v načinu vse vključeno
  • WireGuard brez PresharedKey, z MTU=1440 (samo od IPv4)

Tehnični podatki za geeke
Meritve se zajemajo z naslednjimi ukazi:

na stranki:

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"

zakasnitev ICMP

ping -c 10 SERVER_IP | tail -1

na strežniku (teče hkrati z odjemalcem):

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"

Konfiguracija tunela

ipipou
strežnik
/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

stranka
/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 (brez šifriranja, z avtentikacijo)
strežnik

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

stranka

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 (s šifriranjem, avtentikacijo, prek UDP, vse po pričakovanjih)
Konfigurirano z uporabo openvpn-manage

žična garda
strežnik
/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

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

Ugotovitve

Vlažen grd znak
Obremenitev procesorja strežnika ni zelo indikativna, ker ... Tam deluje veliko drugih storitev, ki včasih požrejo vire:

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: več kot le nešifriran tunel

ipipou: več kot le nešifriran tunel

kanala na 1 optimističen Gbps

ipipou: več kot le nešifriran tunel

ipipou: več kot le nešifriran tunel

V vseh primerih je ipipou po zmogljivosti precej blizu osnovnemu kanalu, kar je odlično!

Nešifrirani tunel openvpn se je v obeh primerih obnašal precej čudno.

Če ga bo kdo testiral, bo zanimivo slišati povratne informacije.

Naj bosta IPv6 in NetPrickle z nami!

Vir: www.habr.com

Dodaj komentar