ipipou: több, mint egy titkosítatlan alagút

Mit mondunk az IPv6 Istenének?

ipipou: több, mint egy titkosítatlan alagút
Így van, ma ugyanezt mondjuk a titkosítás istenének.

Itt egy titkosítatlan IPv4 alagútról lesz szó, de nem egy „meleglámpáról”, hanem egy modern „LED”-ről. És itt is villognak a nyers socketek, és zajlik a munka a csomagokkal a felhasználói térben.

Minden ízléshez és színhez N alagútkezelési protokoll létezik:

  • stílusos, divatos, fiatalos WireGuard
  • többfunkciós, mint például a svájci kések, az OpenVPN és az SSH
  • régi és nem gonosz GRE
  • a legegyszerűbb, leggyorsabb, teljesen titkosítatlan IPIP
  • aktívan fejlődik GENF
  • sok más.

De programozó vagyok, ezért az N-t csak töredékével növelem, a valódi protokollok fejlesztését pedig a Kommersant fejlesztőire bízom.

Egy meg nem születettben programAmit most csinálok, az az, hogy kívülről elérem a NAT mögötti házigazdákat. Felnőtt titkosítási protokollokat használva erre, nem tudtam megszabadulni attól az érzéstől, mintha ágyúból verebeket lőnék ki. Mert az alagutat nagyrészt csak a NAT-e-n való lyukasztásra használják, a belső forgalom is általában titkosítva van, de így is belefulladnak a HTTPS-be.

A különféle alagútkezelési protokollok kutatása közben a belső perfekcionistám figyelmét újra és újra felkeltette az IPIP a minimális rezsi miatt. De van másfél jelentős hátránya a feladataim szempontjából:

  • mindkét oldalon nyilvános IP-címekre van szükség,
  • és nincs hitelesítés neked.

Ezért a perfekcionistát visszaterelték a koponya sötét sarkába, vagy bárhová, ahol ül.

Aztán egy nap, miközben cikkeket olvasok róla natívan támogatott alagutak Linuxban találkoztam a FOU-val (Foo-over-UDP), azaz. mindegy, UDP-be csomagolva. Eddig csak az IPIP és a GUE (Generic UDP Encapsulation) támogatott.

„Itt az ezüstgolyó! Nekem elég egy egyszerű IPIP.” - Azt gondoltam.

Valójában kiderült, hogy a golyó nem teljesen ezüst. Az UDP-be ágyazás megoldja az első problémát – a NAT mögötti kliensekhez kívülről is kapcsolódhat egy előre kialakított kapcsolat segítségével, de itt az IPIP következő hátrányának fele új megvilágításban virágzik – a magánhálózatból bárki elbújhat a látható mögé. nyilvános IP és kliens port (tiszta IPIP esetén ez a probléma nem létezik).

Ennek a másfél problémának a megoldására született meg a segédprogram ipipou. Saját készítésű mechanizmust valósít meg a távoli gazdagép hitelesítésére anélkül, hogy megzavarná a kernel FOU működését, amely gyorsan és hatékonyan dolgozza fel a csomagokat a kerneltérben.

Nincs szükségünk a forgatókönyvére!

Ok, ha ismeri a kliens nyilvános portját és IP-jét (pl. mögötte mindenki nem megy sehova, a NAT megpróbálja leképezni a portokat 1 az 1-ben), létrehozhat egy IPIP-over-FOU alagutat a a következő parancsokat, szkriptek nélkül.

szerveren:

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

az ügyfélen:

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

ahol

  • ipipou* — a helyi alagúthálózati interfész neve
  • 203.0.113.1 — nyilvános IP-szerver
  • 198.51.100.2 — az ügyfél nyilvános IP-címe
  • 192.168.0.2 — az eth0 interfészhez rendelt kliens IP
  • 10001 — helyi ügyfélport a FOU számára
  • 20001 — nyilvános ügyfélport a FOU számára
  • 10000 — nyilvános szerver port a FOU számára
  • encap-csum — lehetőség UDP-ellenőrző összeg hozzáadására a beágyazott UDP-csomagokhoz; helyettesíthető noencap-csum, nem beszélve arról, hogy az integritást már a külső tokozási réteg szabályozza (amíg a csomag az alagútban van)
  • eth0 — helyi interfész, amelyhez az ipip alagút hozzá lesz kötve
  • 172.28.0.1 — a kliens alagút interfész IP-je (privát)
  • 172.28.0.0 — IP tunnel szerver interfész (privát)

Amíg az UDP kapcsolat él, az alagút üzemképes, de ha megszakad, akkor szerencséd lesz - ha a kliens IP: portja változatlan marad - él, ha változnak - megszakad.

A legegyszerűbb módja annak, hogy mindent visszafordítson, a kernelmodulok eltávolítása: modprobe -r fou ipip

Még ha nincs is szükség hitelesítésre, az ügyfél nyilvános IP-címe és portja nem mindig ismert, és gyakran kiszámíthatatlan vagy változó (a NAT típusától függően). Ha kihagyja encap-dport szerver oldalon az alagút nem fog működni, nem elég okos a távoli kapcsolat portját venni. Ebben az esetben az ipipou is segíthet, vagy a WireGuard és a hozzá hasonlók.

Hogyan működik?

A kliens (amely általában a NAT mögött van) megnyit egy alagutat (mint a fenti példában), és hitelesítési csomagot küld a kiszolgálónak, hogy az a maga oldalán konfigurálja az alagutat. Ez a beállításoktól függően lehet üres csomag (csak azért, hogy a szerver lássa a nyilvános IP: kapcsolati portot), vagy olyan adatokkal, amelyek alapján a szerver azonosítani tudja a klienst. Az adatok lehetnek egyszerű jelmondatok egyértelmű szövegben (a HTTP Basic Auth analógiája jut eszembe), vagy speciálisan tervezett, privát kulccsal aláírt adat (hasonlóan a HTTP Digest Auth-hoz, csak erősebb, lásd a funkciót client_auth a kódban).

A szerveren (a nyilvános IP-vel rendelkező oldalon) az ipipou elindulásakor létrehoz egy nfqueue sorkezelőt, és beállítja a netfiltert úgy, hogy a szükséges csomagok oda kerüljenek elküldésre, ahol lenniük kell: az nfqueue sorhoz való csatlakozást inicializáló csomagok, és [majdnem] az összes többi egyenesen a FOU hallgatóhoz kerül.

Azok számára, akik nem ismerik, az nfqueue (vagy NetfilterQueue) egy speciális dolog az amatőrök számára, akik nem tudják, hogyan kell kernelmodulokat fejleszteni, ami a netfilter (nftables/iptables) segítségével lehetővé teszi a hálózati csomagok átirányítását a felhasználói térbe, és ott feldolgozva. primitív azt jelenti, hogy kéznél van: módosítsd (opcionális ) és add vissza a kernelnek, vagy dobd el.

Néhány programozási nyelvhez vannak kötések az nfqueue-val való munkavégzéshez, a bash-hoz nem volt (heh, nem meglepő), pythont kellett használnom: ipipou használ NetfilterQueue.

Ha a teljesítmény nem kritikus, akkor ezzel a dologgal viszonylag gyorsan és egyszerűen kitalálhatja a saját logikáját a meglehetősen alacsony szintű csomagokkal való munkavégzéshez, például kísérleti adatátviteli protokollokat készíthet, vagy helyi és távoli szolgáltatásokat nem szabványos viselkedéssel.

A nyers socketek kéz a kézben működnek az nfqueue-val, például amikor az alagút már konfigurálva van, és a FOU a kívánt porton figyel, akkor ugyanarról a portról nem fog tudni csomagot küldeni a szokásos módon – foglalt, de egy véletlenszerűen generált csomagot nyers socket segítségével közvetlenül a hálózati interfészre vehetünk és küldhetünk, bár egy ilyen csomag előállítása még egy kis trükközést igényel. Így jönnek létre a hitelesítéssel ellátott csomagok az ipipou-ban.

Mivel az ipipou csak a kapcsolat első csomagjait dolgozza fel (és azokat, amelyeknek sikerült a sorba szivárogniuk a kapcsolat létrejötte előtt), a teljesítmény szinte nem csorbul.

Amint az ipipou kiszolgáló hitelesített csomagot kap, egy alagút jön létre, és a kapcsolat minden további csomagját már feldolgozza a kernel, megkerülve az nfqueue-t. Ha a kapcsolat meghiúsul, akkor a következő első csomagja az nfqueue sorba kerül, beállításoktól függően, ha nem hitelesítéssel rendelkező csomag, hanem az utoljára emlékezett IP-ről és kliens portról, akkor vagy átadható bekapcsolva vagy eldobva. Ha egy hitelesített csomag új IP-címről és portról érkezik, az alagút újrakonfigurálva van ezek használatára.

A szokásos IPIP-over-FOU-nak van még egy problémája a NAT-tal való munka során - lehetetlen létrehozni két UDP-be burkolt IPIP alagutat ugyanazzal az IP-vel, mivel a FOU és az IPIP modulok meglehetősen el vannak szigetelve egymástól. Azok. ugyanazon nyilvános IP-cím mögött lévő klienspárok nem tudnak egyszerre csatlakozni ugyanahhoz a szerverhez ilyen módon. A jövőben, lehetséges, kernel szinten lesz megoldva, de ez nem biztos. Addig is a NAT-problémák megoldhatók NAT-tal - ha előfordul, hogy egy IP-címpárt már elfoglal egy másik alagút, akkor az ipipou a NAT-ot nyilvánosról alternatív privát IP-re végzi, íme! - alagutakat hozhat létre, amíg el nem fogynak a portok.

Mert A kapcsolaton belül nem minden csomag van aláírva, így ez az egyszerű védelem sebezhető a MITM-mel szemben, így ha a kliens és a szerver közötti úton egy gazember ólálkodik, aki meg tudja hallgatni a forgalmat és manipulálni tudja azt, át tudja irányítani a hitelesített csomagokat egy másik címet, és hozzon létre egy alagutat egy nem megbízható gazdagépről.

Ha valakinek van ötlete a probléma megoldására, miközben a forgalom nagy részét a magban hagyja, ne habozzon megszólalni.

Egyébként az UDP-be való tokozás nagyon jól bevált. Az IP-n keresztüli beágyazáshoz képest sokkal stabilabb és gyakran gyorsabb az UDP-fejléc többletterhelése ellenére. Ez annak a ténynek köszönhető, hogy az interneten a legtöbb gazdagép csak a három legnépszerűbb protokollal működik jól: TCP, UDP, ICMP. A kézzelfogható rész minden mást teljesen el tud dobni, vagy lassabban dolgozza fel, mert csak erre a háromra van optimalizálva.

Például ezért jött létre a QUICK, amelyen a HTTP/3 alapul, az UDP-n, és nem az IP-n.

Nos, elég a szóból, ideje megnézni, hogyan működik ez a „való világban”.

Csata

A való világ utánzására használják iperf3. A valósághoz való közelség mértékét tekintve ez megközelítőleg megegyezik a valós világ Minecraftban való utánzásával, de egyelőre megteszi.

A verseny résztvevői:

  • referencia fő csatorna
  • ennek a cikknek a hőse ipipou
  • OpenVPN hitelesítéssel, de titkosítás nélkül
  • OpenVPN all-inclusive módban
  • WireGuard PresharedKey nélkül, MTU=1440 (csak IPv4 óta)

Technikai adatok strébereknek
A metrikák a következő parancsokkal vehetők fel:

az ügyfélen:

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 késleltetés

ping -c 10 SERVER_IP | tail -1

a szerveren (egyidejűleg fut a klienssel):

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"

Alagút konfiguráció

ipipou
szerveren
/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

ügyfél
/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 (titkosítás nélkül, hitelesítéssel)
szerveren

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

ügyfél

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 (titkosítással, hitelesítéssel, UDP-n keresztül, minden a várt módon)
segítségével konfigurálva openvpn-manage

drótvédő
szerveren
/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

ügyfél
/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

Álláspontja

Nyirkos csúnya jel
A szerver CPU terhelése nem túl jelzésértékű, mert... Sok más szolgáltatás is fut ott, néha felemésztik az erőforrásokat:

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 csatorna

ipipou: több, mint egy titkosítatlan alagút

ipipou: több, mint egy titkosítatlan alagút

csatorna per 1 optimista Gbps

ipipou: több, mint egy titkosítatlan alagút

ipipou: több, mint egy titkosítatlan alagút

Az ipipou teljesítményében minden esetben nagyon közel áll az alapcsatornához, ami nagyszerű!

A titkosítatlan openvpn alagút mindkét esetben meglehetősen furcsán viselkedett.

Ha valaki kipróbálná, érdekes lesz hallani a visszajelzéseket.

Az IPv6 és a NetPrickle legyen velünk!

Forrás: will.com

Hozzászólás