ipipou: higit pa sa isang hindi naka-encrypt na lagusan

Ano ang sinasabi natin sa Diyos ng IPv6?

ipipou: higit pa sa isang hindi naka-encrypt na lagusan
Iyan ay tama, sasabihin natin ang parehong sa diyos ng pag-encrypt ngayon.

Dito ay pag-uusapan natin ang tungkol sa isang hindi naka-encrypt na IPv4 tunnel, ngunit hindi tungkol sa isang "mainit na lampara", ngunit tungkol sa isang modernong "LED". At mayroon ding mga hilaw na socket na kumikislap dito, at ginagawa ang mga packet sa espasyo ng gumagamit.

Mayroong N tunneling protocol para sa bawat panlasa at kulay:

  • sunod sa moda, sunod sa moda, kabataan WireGuard
  • multifunctional, tulad ng Swiss knives, OpenVPN at SSH
  • luma at hindi masamang GRE
  • ang pinakasimple, mabilis, ganap na hindi naka-encrypt na IPIP
  • aktibong umuunlad GENEVE
  • marami pang iba.

Ngunit ako ay isang programmer, kaya dadagdagan ko ang N sa pamamagitan lamang ng isang fraction, at iiwan ang pagbuo ng mga tunay na protocol sa mga developer ng Kommersant.

Sa isang hindi pa isinisilang proyektoAng ginagawa ko ngayon ay upang maabot ang mga host sa likod ng NAT mula sa labas. Gamit ang mga protocol na may pang-adultong cryptography para dito, hindi ko maalis ang pakiramdam na ito ay tulad ng pagbaril ng mga maya mula sa isang kanyon. kasi ang tunnel ay ginagamit para sa karamihan para lamang sa butas sa NAT-e, ang panloob na trapiko ay kadalasang naka-encrypt din, ngunit sila ay nalulunod pa rin sa HTTPS.

Habang nagsasaliksik ng iba't ibang tunneling protocol, paulit-ulit na natuon ang atensyon ng aking inner perfectionist sa IPIP dahil sa kaunting overhead nito. Ngunit mayroon itong isa at kalahating makabuluhang disbentaha para sa aking mga gawain:

  • nangangailangan ito ng mga pampublikong IP sa magkabilang panig,
  • at walang pagpapatunay para sa iyo.

Samakatuwid, ang perfectionist ay itinulak pabalik sa madilim na sulok ng bungo, o kung saan man siya umupo doon.

At pagkatapos ay isang araw, habang nagbabasa ng mga artikulo sa mga tunnel na sinusuportahan ng katutubong sa Linux nakatagpo ako ng FOU (Foo-over-UDP), i.e. kahit ano, nakabalot sa UDP. Sa ngayon, IPIP at GUE (Generic UDP Encapsulation) lang ang sinusuportahan.

“Eto ang pilak na bala! Ang isang simpleng IPIP ay sapat na para sa akin." - Akala ko.

Sa katunayan, ang bala ay naging hindi ganap na pilak. Nalulutas ng encapsulation sa UDP ang unang problema - maaari kang kumonekta sa mga kliyente sa likod ng NAT mula sa labas gamit ang isang paunang itinatag na koneksyon, ngunit dito kalahati ng susunod na disbentaha ng IPIP blossoms sa isang bagong liwanag - sinuman mula sa isang pribadong network ay maaaring magtago sa likod ng nakikita pampublikong IP at client port (sa purong IPIP ang problemang ito ay hindi umiiral).

Upang malutas ang isa at kalahating problemang ito, ipinanganak ang utility ipipou. Nagpapatupad ito ng isang home-made na mekanismo para sa pag-authenticate ng remote host, nang hindi nakakaabala sa pagpapatakbo ng kernel FOU, na mabilis at mahusay na magpoproseso ng mga packet sa kernel space.

Hindi namin kailangan ang iyong script!

Ok, kung alam mo ang pampublikong port at IP ng kliyente (halimbawa, lahat ng nasa likod nito ay hindi pumupunta kahit saan, sinusubukan ng NAT na i-map ang mga port 1-in-1), maaari kang lumikha ng IPIP-over-FOU tunnel na may sumusunod sa mga utos, nang walang anumang mga script.

sa 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

sa kliyente:

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

saan

  • ipipou* — pangalan ng lokal na tunnel network interface
  • 203.0.113.1 — pampublikong IP server
  • 198.51.100.2 — pampublikong IP ng kliyente
  • 192.168.0.2 — client IP na itinalaga sa interface eth0
  • 10001 — lokal na port ng kliyente para sa FOU
  • 20001 — pampublikong port ng kliyente para sa FOU
  • 10000 — pampublikong server port para sa FOU
  • encap-csum — opsyon na magdagdag ng UDP checksum sa mga naka-encapsulated na UDP packet; maaaring palitan ng noencap-csum, hindi banggitin, ang integridad ay kontrolado na ng panlabas na encapsulation layer (habang ang packet ay nasa loob ng tunnel)
  • eth0 — lokal na interface kung saan tatali ang ipip tunnel
  • 172.28.0.1 — IP ng interface ng tunnel ng kliyente (pribado)
  • 172.28.0.0 — IP tunnel server interface (pribado)

Hangga't ang koneksyon ng UDP ay buhay, ang tunnel ay gagana, ngunit kung ito ay masira, ikaw ay mapalad - kung ang IP: port ng kliyente ay nananatiling pareho - ito ay mabubuhay, kung sila ay nagbago - ito ay masira.

Ang pinakamadaling paraan upang ibalik ang lahat ay ang pag-unload ng mga kernel module: modprobe -r fou ipip

Kahit na hindi kinakailangan ang pagpapatunay, ang pampublikong IP at port ng kliyente ay hindi palaging kilala at kadalasang hindi mahuhulaan o variable (depende sa uri ng NAT). Kung iiwan mo encap-dport sa gilid ng server, ang lagusan ay hindi gagana, ito ay hindi sapat na matalino upang kunin ang remote na port ng koneksyon. Sa kasong ito, makakatulong din ang ipipou, o makakatulong sa iyo ang WireGuard at iba pang katulad nito.

Paano ito gumagana?

Ang kliyente (na kadalasang nasa likod ng NAT) ay nagbubukas ng tunnel (tulad ng halimbawa sa itaas), at nagpapadala ng packet ng pagpapatunay sa server upang mai-configure nito ang tunnel sa gilid nito. Depende sa mga setting, maaari itong maging isang walang laman na packet (para lang makita ng server ang pampublikong IP: connection port), o gamit ang data kung saan makikilala ng server ang kliyente. Ang data ay maaaring isang simpleng passphrase sa malinaw na text (ang pagkakatulad sa HTTP Basic Auth ang naiisip) o espesyal na idinisenyong data na nilagdaan ng pribadong key (katulad ng HTTP Digest Auth na mas malakas lang, tingnan ang function. client_auth sa code).

Sa server (sa gilid ng pampublikong IP), kapag nagsimula ang ipipou, lumilikha ito ng nfqueue queue handler at iko-configure ang netfilter upang maipadala ang mga kinakailangang packet kung saan dapat sila: mga packet na nagpapasimula ng koneksyon sa nfqueue queue, at [halos] lahat ng iba ay dumiretso sa nakikinig na FOU.

Para sa mga hindi nakakaalam, ang nfqueue (o NetfilterQueue) ay isang espesyal na bagay para sa mga amateur na hindi alam kung paano bumuo ng mga kernel module, na gamit ang netfilter (nftables/iptables) ay nagbibigay-daan sa iyo na i-redirect ang mga network packet sa espasyo ng gumagamit at iproseso ang mga ito doon gamit ang primitive means at hand: baguhin (opsyonal ) at ibalik ito sa kernel, o itapon ito.

Para sa ilang mga programming language mayroong mga binding para sa pagtatrabaho sa nfqueue, para sa bash ay wala (heh, hindi nakakagulat), kailangan kong gumamit ng python: ginagamit ng ipipou NetfilterQueue.

Kung ang pagganap ay hindi kritikal, gamit ang bagay na ito maaari mong medyo mabilis at madaling gumawa ng iyong sariling lohika para sa pagtatrabaho sa mga packet sa isang medyo mababang antas, halimbawa, lumikha ng mga eksperimentong protocol ng paglilipat ng data, o troll sa mga lokal at malalayong serbisyo na may hindi karaniwang pag-uugali.

Ang mga raw socket ay gumagana nang magkahawak-kamay sa nfqueue, halimbawa, kapag ang tunnel ay na-configure na at ang FOU ay nakikinig sa nais na port, hindi ka makakapagpadala ng isang packet mula sa parehong port sa karaniwang paraan - ito ay abala, ngunit maaari kang kumuha at magpadala ng random na nabuong packet nang direkta sa interface ng network gamit ang isang raw socket, bagaman ang pagbuo ng naturang packet ay mangangailangan ng kaunti pang tinkering. Ito ay kung paano nilikha ang mga packet na may pagpapatunay sa ipipou.

Dahil ang ipipou ay nagpoproseso lamang ng mga unang packet mula sa koneksyon (at ang mga pinamamahalaang tumagas sa pila bago naitatag ang koneksyon), halos hindi naghihirap ang pagganap.

Sa sandaling makatanggap ang ipipou server ng isang authenticated na packet, isang tunnel ang gagawa at lahat ng kasunod na packet sa koneksyon ay naproseso na ng kernel na lumalampas sa nfqueue. Kung nabigo ang koneksyon, ang unang packet ng susunod ay ipapadala sa nfqueue queue, depende sa mga setting, kung hindi ito isang packet na may pagpapatunay, ngunit mula sa huling natatandaang IP at client port, maaari itong maipasa. sa o itinapon. Kung ang isang napatotohanan na packet ay nagmula sa isang bagong IP at port, ang tunnel ay muling iko-configure upang magamit ang mga ito.

Ang karaniwang IPIP-over-FOU ay may isa pang problema kapag nagtatrabaho sa NAT - imposibleng lumikha ng dalawang IPIP tunnel na naka-encapsulated sa UDP na may parehong IP, dahil ang FOU at IPIP module ay medyo nakahiwalay sa isa't isa. Yung. ang isang pares ng mga kliyente sa likod ng parehong pampublikong IP ay hindi makakakonekta sa parehong server sa paraang ito nang sabay-sabay. Sa hinaharap, marahil, ito ay malulutas sa antas ng kernel, ngunit hindi ito tiyak. Pansamantala, ang mga problema sa NAT ay maaaring malutas ng NAT - kung mangyari na ang isang pares ng mga IP address ay inookupahan na ng isa pang tunnel, gagawin ng ipipou ang NAT mula sa publiko patungo sa isang alternatibong pribadong IP, voila! - maaari kang lumikha ng mga tunnel hanggang sa maubos ang mga port.

kasi Hindi lahat ng mga packet sa koneksyon ay nilagdaan, kung gayon ang simpleng proteksyon na ito ay mahina sa MITM, kaya kung mayroong isang kontrabida na nakatago sa landas sa pagitan ng kliyente at ng server na maaaring makinig sa trapiko at manipulahin ito, maaari niyang i-redirect ang mga napatunayang packet sa pamamagitan ng isa pang address at gumawa ng tunnel mula sa isang hindi pinagkakatiwalaang host .

Kung sinuman ang may ideya kung paano ito ayusin habang iniiwan ang karamihan sa trapiko sa core, huwag mag-atubiling magsalita.

Sa pamamagitan ng paraan, ang encapsulation sa UDP ay napatunayan nang mahusay. Kung ikukumpara sa encapsulation sa IP, ito ay mas matatag at kadalasang mas mabilis sa kabila ng karagdagang overhead ng UDP header. Ito ay dahil sa ang katunayan na ang karamihan sa mga host sa Internet ay gumagana nang maayos lamang sa tatlong pinakasikat na mga protocol: TCP, UDP, ICMP. Ang nasasalat na bahagi ay maaaring ganap na itapon ang lahat ng iba pa, o iproseso ito nang mas mabagal, dahil ito ay na-optimize para lamang sa tatlong ito.

Halimbawa, ito ang dahilan kung bakit ang QUICK, kung saan nakabatay ang HTTP/3, ay ginawa sa ibabaw ng UDP, at hindi sa ibabaw ng IP.

Well, sapat na mga salita, oras na upang makita kung paano ito gumagana sa "tunay na mundo".

Labanan

Ginamit upang tularan ang totoong mundo iperf3. Sa mga tuntunin ng antas ng pagiging malapit sa katotohanan, ito ay humigit-kumulang kapareho ng pagtulad sa totoong mundo sa Minecraft, ngunit sa ngayon ay gagawin nito.

Mga kalahok sa kumpetisyon:

  • sanggunian pangunahing channel
  • ang bayani ng artikulong ito ay si ipipou
  • OpenVPN na may authentication ngunit walang encryption
  • OpenVPN sa all-inclusive mode
  • WireGuard na walang PresharedKey, na may MTU=1440 (mula sa IPv4-only)

Teknikal na data para sa mga geeks
Kinukuha ang mga sukatan gamit ang mga sumusunod na command:

sa kliyente:

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 latency

ping -c 10 SERVER_IP | tail -1

sa server (tumatakbo nang sabay-sabay sa kliyente):

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"

Configuration ng lagusan

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

kostumer
/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 (walang encryption, may authentication)
server

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

kostumer

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 (na may encryption, authentication, sa pamamagitan ng UDP, lahat gaya ng inaasahan)
Na-configure gamit ang openvpn-manage

tagapag-alaga
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

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

Natuklasan

Damp pangit na palatandaan
Ang pag-load ng CPU ng server ay hindi masyadong nagpapahiwatig, dahil... Mayroong maraming iba pang mga serbisyo na tumatakbo doon, kung minsan kumakain sila ng mga mapagkukunan:

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 na channel

ipipou: higit pa sa isang hindi naka-encrypt na lagusan

ipipou: higit pa sa isang hindi naka-encrypt na lagusan

channel per 1 optimistic Gbps

ipipou: higit pa sa isang hindi naka-encrypt na lagusan

ipipou: higit pa sa isang hindi naka-encrypt na lagusan

Sa lahat ng kaso, ang ipipou ay medyo malapit sa pagganap sa base channel, na mahusay!

Ang hindi naka-encrypt na openvpn tunnel ay kumilos nang medyo kakaiba sa parehong mga kaso.

Kung sinuman ang susubok nito, magiging kawili-wiling marinig ang feedback.

Nawa'y makasama natin ang IPv6 at NetPrickle!

Pinagmulan: www.habr.com

Magdagdag ng komento