ipipou: enemmän kuin vain salaamaton tunneli

Mitä sanomme IPv6:n Jumalalle?

ipipou: enemmän kuin vain salaamaton tunneli
Aivan oikein, sanomme saman salauksen jumalalle tänään.

Täällä puhumme salaamattomasta IPv4-tunnelista, mutta ei "lämpimästä lampusta", vaan nykyaikaisesta "LED"-tunnelista. Ja täällä vilkkuvat myös raaka-socketit, ja pakettien kanssa työskennellään käyttäjätilassa.

Tunnelointiprotokollaa on N jokaiseen makuun ja väriin:

  • tyylikäs, muodikas, nuori WireGuard
  • monikäyttöisiä, kuten sveitsiläiset veitset, OpenVPN ja SSH
  • vanha eikä paha GRE
  • yksinkertaisin, nopein, täysin salaamaton IPIP
  • kehittyy aktiivisesti GENEVE
  • monet muut.

Mutta olen ohjelmoija, joten lisään N:ää vain murto-osalla ja jätän oikeiden protokollien kehittämisen Kommersantin kehittäjille.

Yhdessä syntymättömässä projektiMitä teen nyt, on tavoittaa NAT:n takana olevat isännät ulkopuolelta. Käyttäen tähän aikuisten salausprotokollia, en voinut päästä eroon tunteesta, että se oli kuin varpusten ampumista tykistä. Koska tunnelia käytetään suurimmaksi osaksi vain NAT-e:n reikien töihin, sisäinen liikenne on yleensä myös salattua, mutta silti ne hukkuvat HTTPS:ään.

Erilaisia ​​tunnelointiprotokollia tutkiessani sisäinen perfektionistini veti IPIP:iin yhä uudelleen ja uudelleen sen minimaalisen yleiskustannusten vuoksi. Mutta sillä on puolitoista merkittävää haittaa tehtävieni kannalta:

  • se vaatii julkisia IP-osoitteita molemmilta puolilta,
  • eikä todennusta sinulle.

Siksi perfektionisti ajettiin takaisin kallon pimeään nurkkaan tai minne tahansa hän siellä istuu.

Ja sitten eräänä päivänä lukiessani artikkeleita aiheesta natiivisti tuetut tunnelit Linuxissa törmäsin FOU:iin (Foo-over-UDP), ts. mikä tahansa, kääritty UDP:hen. Toistaiseksi vain IPIP ja GUE (Generic UDP Encapsulation) ovat tuettuja.

"Tässä on hopealuodi! Yksinkertainen IPIP riittää minulle." - Ajattelin.

Itse asiassa luoti ei osoittautunut täysin hopeaksi. UDP:n kapselointi ratkaisee ensimmäisen ongelman - voit muodostaa yhteyden NAT:n takana oleviin asiakkaisiin ulkopuolelta käyttämällä ennalta muodostettua yhteyttä, mutta tässä puolet IPIP:n seuraavasta haitasta kukoistaa uudessa valossa - kuka tahansa yksityisestä verkosta voi piiloutua näkyvän verkon taakse. julkinen IP ja asiakasportti (puhtaan IPIP:ssä tätä ongelmaa ei ole).

Tämän puolitoista ongelman ratkaisemiseksi syntyi apuohjelma ipipou. Se toteuttaa kotitekoisen mekanismin etäisännän todentamiseen häiritsemättä ytimen FOU:n toimintaa, joka käsittelee paketteja nopeasti ja tehokkaasti ydintilassa.

Emme tarvitse käsikirjoitustasi!

Ok, jos tiedät asiakkaan julkisen portin ja IP-osoitteen (esimerkiksi kaikki sen takana olevat eivät mene minnekään, NAT yrittää kartoittaa portit 1-in-1), voit luoda IPIP-over-FOU-tunnelin seuraavat komennot ilman komentosarjoja.

palvelimella:

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

asiakkaalla:

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

missä

  • ipipou* — paikallisen tunnelin verkkoliitännän nimi
  • 203.0.113.1 — julkinen IP-palvelin
  • 198.51.100.2 — asiakkaan julkinen IP
  • 192.168.0.2 — käyttöliittymälle eth0 määritetty asiakkaan IP
  • 10001 — FOU:n paikallinen asiakasportti
  • 20001 — FOU:n julkinen asiakasportti
  • 10000 — FOU:n julkinen palvelinportti
  • encap-csum — mahdollisuus lisätä UDP-tarkistussumma kapseloituihin UDP-paketteihin; voidaan korvata noencap-csum, puhumattakaan, eheyttä ohjaa jo ulompi kapselointikerros (kun paketti on tunnelin sisällä)
  • eth0 — paikallinen rajapinta, johon ipip-tunneli sidotaan
  • 172.28.0.1 — Asiakastunnelirajapinnan IP (yksityinen)
  • 172.28.0.0 — IP-tunnelipalvelimen käyttöliittymä (yksityinen)

Niin kauan kuin UDP-yhteys on elossa, tunneli on toimintakunnossa, mutta jos se katkeaa, olet onnekas - jos asiakkaan IP: portti pysyy samana - se elää, jos ne muuttuvat - se katkeaa.

Helpoin tapa kääntää kaikki takaisin on purkaa ydinmoduulit: modprobe -r fou ipip

Vaikka todennusta ei vaadita, asiakkaan julkista IP-osoitetta ja porttia ei aina tiedetä, ja ne ovat usein arvaamattomia tai muuttuvia (riippuen NAT-tyypistä). Jos jätät väliin encap-dport palvelimen puolella tunneli ei toimi, se ei ole tarpeeksi älykäs ottamaan etäyhteysporttia. Tässä tapauksessa ipipou voi myös auttaa tai WireGuard ja muut sen kaltaiset voivat auttaa sinua.

Miten se toimii?

Asiakas (joka on yleensä NAT:n takana) avaa tunnelin (kuten yllä olevassa esimerkissä) ja lähettää todennuspaketin palvelimelle, jotta se määrittää tunnelin puolelleen. Asetuksista riippuen tämä voi olla tyhjä paketti (jotta palvelin näkee julkisen IP:n yhteysportin) tai datalla, jonka perusteella palvelin voi tunnistaa asiakkaan. Tiedot voivat olla yksinkertaisia ​​salalauseita selkeässä tekstissä (tulkoon mieleen analogia HTTP Basic Authin kanssa) tai erityisesti suunniteltuja tietoja, jotka on allekirjoitettu yksityisellä avaimella (samanlainen kuin HTTP Digest Auth vain vahvempi, katso toiminto client_auth koodissa).

Palvelimelle (julkisen IP-osoitteen puolelle) ipipou luo käynnistyessään nfqueue-jononkäsittelijän ja määrittää netfilterin niin, että tarvittavat paketit lähetetään sinne, missä niiden pitäisi olla: paketit, jotka alustavat yhteyden nfqueue-jonoon, ja [melkein] kaikki loput menevät suoraan kuuntelijalle FOU.

Niille, jotka eivät tiedä, nfqueue (tai NetfilterQueue) on erityinen asia amatööreille, jotka eivät osaa kehittää ydinmoduuleja, jotka netfilterin (nftables/iptables) avulla voit ohjata verkkopaketteja käyttäjätilaan ja käsitellä niitä siellä. primitiiviset keinot käsillä: muokkaa (valinnainen ) ja anna se takaisin ytimelle tai hylkää se.

Joillekin ohjelmointikielille on sidoksia nfqueuen kanssa työskentelyä varten, bashille ei ollut mitään (heh, ei yllättävää), minun piti käyttää python: ipipou uses NetfilterQueue.

Jos suorituskyky ei ole kriittistä, tämän asian avulla voit suhteellisen nopeasti ja helposti keksiä oman logiikkasi melko matalan tason pakettien kanssa työskentelyyn, esimerkiksi luoda kokeellisia tiedonsiirtoprotokollia tai trollata paikallisia ja etäpalveluita epätyypillisellä käyttäytymisellä.

Raw socketit toimivat käsi kädessä nfqueuen kanssa, esimerkiksi kun tunneli on jo konfiguroitu ja FOU kuuntelee haluttua porttia, et voi lähettää pakettia samasta portista tavalliseen tapaan - se on varattu, mutta Voit ottaa ja lähettää satunnaisesti luodun paketin suoraan verkkorajapintaan käyttämällä raakaa socketia, vaikka tällaisen paketin luominen vaatii hieman enemmän puuhailua. Näin ipipoussa luodaan todennettuja paketteja.

Koska ipipou käsittelee vain ensimmäiset paketit yhteydestä (ja ne, jotka onnistuivat vuotamaan jonoon ennen yhteyden muodostumista), suorituskyky ei juurikaan kärsi.

Heti kun ipipou-palvelin vastaanottaa autentikoidun paketin, tunneli luodaan ja ydin käsittelee jo kaikki myöhemmät yhteyden paketit ohittamalla nfqueue. Jos yhteys epäonnistuu, seuraavan paketin ensimmäinen paketti lähetetään nfqueue-jonoon asetuksista riippuen, jos se ei ole todennettu paketti, mutta viimeksi muistetusta IP:stä ja asiakasportista, se voidaan joko välittää päällä tai heitetty pois. Jos todennettu paketti tulee uudesta IP-osoitteesta ja portista, tunneli konfiguroidaan uudelleen käyttämään niitä.

Tavallisella IPIP-over-FOU:lla on vielä yksi ongelma NAT:n kanssa työskennellessä - on mahdotonta luoda kahta UDP:hen kapseloitua IPIP-tunnelia samalla IP-osoitteella, koska FOU- ja IPIP-moduulit ovat melko eristettyjä toisistaan. Nuo. saman julkisen IP-osoitteen takana oleva asiakaspari ei pysty samanaikaisesti muodostamaan yhteyttä samaan palvelimeen tällä tavalla. Tulevaisuudessa, ehkä, se ratkaistaan ​​ytimen tasolla, mutta tämä ei ole varmaa. Sillä välin NAT-ongelmat voidaan ratkaista NAT:lla - jos tapahtuu, että IP-osoitepari on jo toisen tunnelin varassa, ipipou tekee NATin julkisesta vaihtoehtoiseen yksityiseen IP-osoitteeseen, voila! - Voit luoda tunneleita, kunnes portit loppuvat.

Koska Kaikkia yhteyden paketteja ei allekirjoiteta, jolloin tämä yksinkertainen suojaus on haavoittuvainen MITM:lle, joten jos asiakkaan ja palvelimen välisellä tiellä väijyy konna, joka voi kuunnella liikennettä ja manipuloida sitä, hän voi ohjata todennettuja paketteja toinen osoite ja luo tunneli epäluotettavasta isännästä .

Jos jollakulla on ideoita tämän korjaamiseksi jättäen suurin osa liikenteestä ytimeen, älä epäröi ottaa yhteyttä.

Muuten, kapselointi UDP: hen on osoittautunut erittäin hyvin. Verrattuna kapselointiin IP:n kautta, se on paljon vakaampi ja usein nopeampi huolimatta UDP-otsikon ylimääräisestä ylärajasta. Tämä johtuu siitä, että useimmat Internetin isännät toimivat hyvin vain kolmen suosituimman protokollan kanssa: TCP, UDP, ICMP. Konkreettinen osa voi kokonaan hylätä kaiken muun tai käsitellä sitä hitaammin, koska se on optimoitu vain näille kolmelle.

Esimerkiksi tämän vuoksi QUICK, johon HTTP/3 perustuu, luotiin UDP:n päälle, ei IP:n päälle.

No, tarpeeksi sanoja, on aika nähdä, kuinka se toimii "todellisessa maailmassa".

Taistelu

Käytetään jäljittelemään todellista maailmaa iperf3. Todellisuuden läheisyyden suhteen tämä on suunnilleen sama kuin todellisen maailman jäljitteleminen Minecraftissa, mutta toistaiseksi se tekee.

Kilpailuun osallistuneet:

  • referenssipääkanava
  • tämän artikkelin sankari on ipipou
  • OpenVPN todennuksella, mutta ilman salausta
  • OpenVPN all inclusive -tilassa
  • WireGuard ilman PresharedKeyä, MTU=1440 (vain IPv4:stä lähtien)

Tekniset tiedot nörteille
Mittarit otetaan seuraavilla komennoilla:

asiakkaalla:

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

ping -c 10 SERVER_IP | tail -1

palvelimella (toimii samanaikaisesti asiakkaan kanssa):

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"

Tunnelin kokoonpano

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

asiakas
/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 (ei salausta, todennus)
palvelin

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

asiakas

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 (salauksella, todennuksella, UDP:n kautta, kaikki odotetusti)
Konfiguroitu käyttämällä openvpn-hallinta

lankasuoja
palvelin
/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

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

Tulokset

Kostea ruma merkki
Palvelimen suorittimen kuormitus ei ole kovin viitteellinen, koska... Siellä on käynnissä monia muita palveluita, jotka joskus syövät resursseja:

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 kanava

ipipou: enemmän kuin vain salaamaton tunneli

ipipou: enemmän kuin vain salaamaton tunneli

kanava per 1 optimistinen Gbps

ipipou: enemmän kuin vain salaamaton tunneli

ipipou: enemmän kuin vain salaamaton tunneli

Kaikissa tapauksissa ipipou on suorituskyvyltään melko lähellä peruskanavaa, mikä on hienoa!

Salaamaton openvpn-tunneli käyttäytyi kummassakin tapauksessa melko oudosti.

Jos joku aikoo testata, on mielenkiintoista kuulla palautetta.

Olkoon IPv6 ja NetPrickle kanssamme!

Lähde: will.com

Lisää kommentti