ipipou: lebih daripada sekadar terowong yang tidak disulitkan

Apa yang kita katakan kepada Tuhan IPv6?

ipipou: lebih daripada sekadar terowong yang tidak disulitkan
Betul, kami akan mengatakan perkara yang sama kepada dewa penyulitan hari ini.

Di sini kita akan bercakap tentang terowong IPv4 yang tidak disulitkan, tetapi bukan tentang "lampu hangat", tetapi tentang "LED" moden. Dan terdapat juga soket mentah berkelip di sini, dan kerja sedang dijalankan dengan paket dalam ruang pengguna.

Terdapat N protokol terowong untuk setiap rasa dan warna:

  • bergaya, bergaya, belia WireGuard
  • pelbagai fungsi, seperti pisau Swiss, OpenVPN dan SSH
  • GRE lama dan bukan jahat
  • IPIP yang paling mudah, pantas dan tidak disulitkan sepenuhnya
  • berkembang secara aktif GENEVA
  • ramai lagi.

Tetapi saya seorang pengaturcara, jadi saya akan meningkatkan N hanya dengan pecahan, dan menyerahkan pembangunan protokol sebenar kepada pemaju Kommersant.

Dalam satu kandungan projekApa yang saya lakukan sekarang ialah menjangkau hos di belakang NAT dari luar. Menggunakan protokol dengan kriptografi dewasa untuk ini, saya tidak dapat menghilangkan perasaan bahawa ia seperti menembak burung pipit keluar dari meriam. Kerana terowong digunakan sebahagian besarnya hanya untuk mencucuk lubang di NAT-e, trafik dalaman biasanya juga disulitkan, tetapi mereka masih lemas dalam HTTPS.

Semasa meneliti pelbagai protokol terowong, perhatian perfeksionis dalaman saya tertarik kepada IPIP berulang kali kerana overhed yang minimum. Tetapi ia mempunyai satu setengah kelemahan penting untuk tugas saya:

  • ia memerlukan IP awam di kedua-dua belah pihak,
  • dan tiada pengesahan untuk anda.

Oleh itu, perfeksionis itu didorong kembali ke sudut gelap tengkorak, atau di mana sahaja dia duduk di sana.

Dan kemudian suatu hari, semasa membaca artikel mengenai terowong asli yang disokong dalam Linux saya terjumpa FOU (Foo-over-UDP), i.e. apa pun, dibungkus dengan UDP. Setakat ini, hanya IPIP dan GUE (Generic UDP Encapsulation) disokong.

“Ini peluru perak! IPIP yang ringkas sudah memadai untuk saya.” - Saya fikir.

Malah, peluru itu ternyata bukan perak sepenuhnya. Enkapsulasi dalam UDP menyelesaikan masalah pertama - anda boleh menyambung kepada pelanggan di belakang NAT dari luar menggunakan sambungan yang telah ditetapkan, tetapi di sini separuh daripada kelemahan seterusnya IPIP berkembang dalam cahaya baharu - di sebalik IP awam yang boleh dilihat dan port klien sesiapa sahaja dari rangkaian persendirian boleh bersembunyi (dalam IPIP tulen masalah ini tidak wujud).

Untuk menyelesaikan satu setengah masalah ini, utiliti itu dilahirkan ipipou. Ia melaksanakan mekanisme buatan sendiri untuk mengesahkan hos jauh, tanpa mengganggu operasi FOU kernel, yang akan memproses paket dengan cepat dan cekap dalam ruang kernel.

Kami tidak memerlukan skrip anda!

Ok, jika anda tahu port awam dan IP klien (contohnya, semua orang di belakangnya tidak pergi ke mana-mana, NAT cuba memetakan port 1-dalam-1), anda boleh membuat terowong IPIP-over-FOU dengan mengikut arahan, tanpa sebarang skrip.

pada pelayan:

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

pada klien:

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

mana

  • ipipou* — nama antara muka rangkaian terowong tempatan
  • 203.0.113.1 — pelayan IP awam
  • 198.51.100.2 — IP awam pelanggan
  • 192.168.0.2 — IP klien diberikan kepada antara muka eth0
  • 10001 — pelabuhan pelanggan tempatan untuk FOU
  • 20001 — pelabuhan pelanggan awam untuk FOU
  • 10000 — pelabuhan pelayan awam untuk FOU
  • encap-csum — pilihan untuk menambah checksum UDP pada paket UDP terkapsul; boleh digantikan dengan noencap-csum, apatah lagi, integriti sudah dikawal oleh lapisan enkapsulasi luar (semasa paket berada di dalam terowong)
  • eth0 — antara muka tempatan di mana terowong ipip akan terikat
  • 172.28.0.1 — IP antara muka terowong pelanggan (peribadi)
  • 172.28.0.0 — Antara muka pelayan terowong IP (peribadi)

Selagi sambungan UDP masih hidup, terowong akan berfungsi, tetapi jika ia pecah, anda bertuah - jika IP klien: port kekal sama - ia akan hidup, jika ia berubah - ia akan pecah.

Cara paling mudah untuk mengembalikan semuanya adalah dengan memunggah modul kernel: modprobe -r fou ipip

Walaupun pengesahan tidak diperlukan, IP awam dan port pelanggan tidak selalu diketahui dan selalunya tidak dapat diramalkan atau berubah-ubah (bergantung pada jenis NAT). Jika anda tinggalkan encap-dport di sisi pelayan, terowong tidak akan berfungsi, ia tidak cukup pintar untuk mengambil port sambungan jauh. Dalam kes ini, ipipou juga boleh membantu, atau WireGuard dan lain-lain seperti ia boleh membantu anda.

Bagaimana ia berfungsi?

Pelanggan (yang biasanya berada di belakang NAT) membuka terowong (seperti dalam contoh di atas), dan menghantar paket pengesahan ke pelayan supaya ia mengkonfigurasi terowong di sebelahnya. Bergantung pada tetapan, ini boleh menjadi paket kosong (hanya supaya pelayan dapat melihat IP awam: port sambungan), atau dengan data yang mana pelayan boleh mengenal pasti klien. Data boleh menjadi frasa laluan mudah dalam teks yang jelas (analogi dengan Pengesahan Asas HTTP muncul di fikiran) atau data yang direka khas yang ditandatangani dengan kunci peribadi (serupa dengan HTTP Digest Auth sahaja yang lebih kuat, lihat fungsi client_auth dalam kod).

Pada pelayan (sebelah dengan IP awam), apabila ipipou bermula, ia mencipta pengendali gilir nfqueue dan mengkonfigurasi netfilter supaya paket yang diperlukan dihantar ke tempat yang sepatutnya: paket yang memulakan sambungan ke baris gilir nfqueue, dan [hampir] semua yang lain terus kepada FOU pendengar.

Bagi mereka yang tidak tahu, nfqueue (atau NetfilterQueue) adalah perkara istimewa untuk amatur yang tidak tahu cara membangunkan modul kernel, yang menggunakan netfilter (nftables/iptables) membolehkan anda mengalihkan paket rangkaian ke ruang pengguna dan memprosesnya di sana menggunakan cara primitif di tangan: ubah suai (pilihan ) dan berikan semula kepada kernel, atau buangnya.

Untuk beberapa bahasa pengaturcaraan terdapat pengikatan untuk bekerja dengan nfqueue, untuk bash tidak ada (heh, tidak menghairankan), saya terpaksa menggunakan python: ipipou menggunakan NetfilterQueue.

Jika prestasi tidak kritikal, menggunakan perkara ini anda boleh dengan cepat dan mudah mengarang logik anda sendiri untuk bekerja dengan paket pada tahap yang agak rendah, sebagai contoh, mencipta protokol pemindahan data percubaan, atau troll perkhidmatan tempatan dan jauh dengan tingkah laku tidak standard.

Soket mentah berfungsi seiring dengan nfqueue, sebagai contoh, apabila terowong sudah dikonfigurasikan dan FOU sedang mendengar pada port yang dikehendaki, anda tidak akan dapat menghantar paket dari port yang sama dengan cara biasa - ia sibuk, tetapi anda boleh mengambil dan menghantar paket yang dijana secara rawak terus ke antara muka rangkaian menggunakan soket mentah, walaupun menjana paket sebegitu akan memerlukan sedikit lagi mengurut. Beginilah cara paket dengan pengesahan dibuat dalam ipipou.

Memandangkan ipipou hanya memproses paket pertama daripada sambungan (dan paket yang berjaya bocor ke dalam baris gilir sebelum sambungan diwujudkan), prestasi hampir tidak terjejas.

Sebaik sahaja pelayan ipipou menerima paket yang disahkan, terowong dibuat dan semua paket berikutnya dalam sambungan sudah diproses oleh kernel memintas nfqueue. Jika sambungan gagal, maka paket pertama yang seterusnya akan dihantar ke baris gilir nfqueue, bergantung pada tetapan, jika ia bukan paket dengan pengesahan, tetapi dari IP dan port klien yang diingati terakhir, ia boleh diluluskan sama ada pada atau dibuang. Jika paket yang disahkan datang daripada IP dan port baharu, terowong dikonfigurasikan semula untuk menggunakannya.

IPIP-over-FOU biasa mempunyai satu lagi masalah apabila bekerja dengan NAT - adalah mustahil untuk mencipta dua terowong IPIP yang terkandung dalam UDP dengan IP yang sama, kerana modul FOU dan IPIP agak terpencil antara satu sama lain. Itu. sepasang pelanggan di belakang IP awam yang sama tidak akan dapat menyambung ke pelayan yang sama secara serentak dengan cara ini. Pada masa akan datang, mungkin, ia akan diselesaikan pada peringkat kernel, tetapi ini tidak pasti. Sementara itu, masalah NAT boleh diselesaikan oleh NAT - jika ia berlaku bahawa sepasang alamat IP sudah diduduki oleh terowong lain, ipipou akan melakukan NAT daripada awam kepada IP persendirian alternatif, voila! - anda boleh membuat terowong sehingga port habis.

Kerana Tidak semua paket dalam sambungan ditandatangani, maka perlindungan mudah ini terdedah kepada MITM, jadi jika terdapat penjahat yang mengintai di laluan antara pelanggan dan pelayan yang boleh mendengar lalu lintas dan memanipulasinya, dia boleh mengalihkan paket yang disahkan melalui alamat lain dan buat terowong daripada hos yang tidak dipercayai .

Jika sesiapa mempunyai idea tentang cara untuk membetulkan perkara ini sambil meninggalkan sebahagian besar trafik dalam teras, jangan teragak-agak untuk bersuara.

Dengan cara ini, enkapsulasi dalam UDP telah membuktikan dirinya dengan baik. Berbanding dengan enkapsulasi melalui IP, ia jauh lebih stabil dan selalunya lebih pantas walaupun terdapat overhed tambahan pengepala UDP. Ini disebabkan oleh fakta bahawa kebanyakan hos di Internet berfungsi dengan baik hanya dengan tiga protokol paling popular: TCP, UDP, ICMP. Bahagian ketara boleh membuang semua yang lain sepenuhnya, atau memprosesnya dengan lebih perlahan, kerana ia dioptimumkan hanya untuk ketiga-tiga ini.

Sebagai contoh, inilah sebabnya QUICK, yang berasaskan HTTP/3, dicipta di atas UDP, dan bukan di atas IP.

Nah, cukup perkataan, sudah tiba masanya untuk melihat cara ia berfungsi dalam "dunia nyata".

Pertempuran

Digunakan untuk mencontohi dunia sebenar iperf3. Dari segi tahap kedekatan dengan realiti, ini lebih kurang sama dengan meniru dunia sebenar dalam Minecraft, tetapi buat masa ini ia akan berlaku.

Peserta pertandingan:

  • rujukan saluran utama
  • hero artikel ini ialah ipipou
  • OpenVPN dengan pengesahan tetapi tiada penyulitan
  • OpenVPN dalam mod semua termasuk
  • WireGuard tanpa PresharedKey, dengan MTU=1440 (sejak IPv4 sahaja)

Data teknikal untuk geeks
Metrik diambil dengan arahan berikut:

pada klien:

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"

Kependaman ICMP

ping -c 10 SERVER_IP | tail -1

pada pelayan (berjalan serentak dengan klien):

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"

Konfigurasi terowong

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

pelanggan
/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 (tiada penyulitan, dengan pengesahan)
pelayan

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

pelanggan

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 (dengan penyulitan, pengesahan, melalui UDP, semuanya seperti yang diharapkan)
Dikonfigurasikan menggunakan openvpn-urus

penjaga gol
pelayan
/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

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

Penemuan

Tanda hodoh lembap
Muatan CPU pelayan tidak begitu menunjukkan, kerana... Terdapat banyak perkhidmatan lain yang dijalankan di sana, kadangkala ia memakan sumber:

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

saluran 20 Mbps

ipipou: lebih daripada sekadar terowong yang tidak disulitkan

ipipou: lebih daripada sekadar terowong yang tidak disulitkan

saluran setiap 1 Gbps optimistik

ipipou: lebih daripada sekadar terowong yang tidak disulitkan

ipipou: lebih daripada sekadar terowong yang tidak disulitkan

Dalam semua kes, prestasi ipipou agak hampir dengan saluran asas, yang sangat bagus!

Terowong openvpn yang tidak disulitkan berkelakuan agak pelik dalam kedua-dua kes.

Jika sesiapa akan mengujinya, ia akan menjadi menarik untuk mendengar maklum balas.

Semoga IPv6 dan NetPrickle bersama kami!

Sumber: www.habr.com

Tambah komen