Benar, dan kepada dewa enkripsi, kami akan mengatakan hal yang sama hari ini.
Di sini akan membahas tentang terowongan IPv4 yang tidak terenkripsi, tetapi bukan tentang "lampu hangat", tetapi tentang "lampu LED" modern. Dan kemudian soket mentah berkedip, dan ada pekerjaan dengan paket di ruang pengguna.
Ada N protokol tunneling untuk setiap rasa dan warna:
- WireGuard yang bergaya, trendi, dan berjiwa muda
- , , OpenVPN SSH
- GRE
- , , IPIP
- GENEVE
- .
Tapi saya seorang programmer, jadi saya akan meningkatkan N hanya sebagian kecil, dan menyerahkan pengembangan protokol nyata ke b-developer.
Dalam proyek lain yang belum lahir , yang saat ini saya lakukan, saya perlu menjangkau host di belakang NAT dari luar. Menggunakan protokol dengan kriptografi dewasa untuk ini, saya tidak pernah meninggalkan perasaan bahwa itu seperti bola meriam. Karena terowongan digunakan untuk sebagian besar hanya untuk menggali lubang di NAT-e, lalu lintas internal biasanya juga dienkripsi, namun mereka tenggelam untuk HTTPS.
Saat meneliti berbagai protokol tunneling, perhatian perfeksionis batiniah saya tertuju pada IPIP berulang kali karena overhead yang minimal. Tetapi ini memiliki satu setengah kekurangan yang signifikan untuk tugas saya:
- itu membutuhkan IP publik di kedua sisi,
- dan tidak ada otentikasi untuk Anda.
Oleh karena itu, perfeksionis didorong kembali ke sudut gelap tengkorak, atau dimanapun dia duduk di sana.
Dan suatu kali, saat membaca artikel tentang tunnel yang didukung secara native di Linux, saya menemukan FOU (Foo-over-UDP), mis. terserah, dibungkus dengan UDP. Sejauh ini, hanya IPIP dan GUE (Enkapsulasi UDP Generik) yang didukung dari yang lain.
βIni peluru perak! Saya dan IPIP sederhana untuk mata. " Saya pikir.
Nyatanya, peluru itu tidak seluruhnya perak. Enkapsulasi dalam UDP memecahkan masalah pertama - Anda dapat terhubung ke klien di belakang NAT dari luar menggunakan koneksi yang sudah ada sebelumnya, tetapi di sini setengah dari kerugian berikutnya dari IPIP mekar dalam cahaya baru - siapa pun dari jaringan pribadi dapat disembunyikan di balik IP publik yang terlihat dan port klien (dalam IPIP murni tidak ada masalah).
Untuk mengatasi masalah satu setengah ini, utilitas ipipou lahir . Ini mengimplementasikan mekanisme buatan sendiri untuk mengautentikasi host jarak jauh, sementara tidak mengganggu pengoperasian FOU yang kuat, yang akan memproses paket dengan cepat dan efisien di ruang kernel.
Tidak membutuhkan naskah Anda!
Oke, jika Anda mengetahui port publik dan IP klien (misalnya, semua milik Anda, ke mana pun mereka pergi, NAT mencoba memetakan port 1-ke-1), Anda dapat membuat terowongan IPIP-over-FOU dengan perintah berikut, tanpa skrip apa pun.
di 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
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
Dimana
ipipou*
- nama antarmuka jaringan terowongan lokal203.0.113.1
- IP publik server198.51.100.2
- IP publik klien192.168.0.2
- IP klien ditugaskan ke antarmuka eth010001
- port klien lokal untuk FOU20001
- port klien publik untuk FOU10000
- port server publik untuk FOUencap-csum
β UDP UDP ;noencap-csum
, , ( )eth0
β ipip172.28.0.1
β IP ()172.28.0.0
β IP ()
Selama koneksi UDP masih hidup, terowongan akan dalam keadaan bekerja, dan bagaimana itu rusak, betapa beruntungnya - jika IP: port klien tetap sama - itu akan hidup, berubah - itu akan rusak.
Cara termudah untuk membalikkan keadaan adalah dengan membongkar modul kernel:
modprobe -r fou ipip
Meskipun otentikasi tidak diperlukan, IP publik dan port klien tidak selalu dikenal dan seringkali tidak dapat diprediksi atau diubah (tergantung pada jenis NAT). Jika Anda menghilangkannya
encap-dport
di sisi server, terowongan tidak akan berfungsi, tidak cukup pintar untuk mengambil port koneksi jarak jauh. Dalam hal ini, ipipou juga dapat membantu, yah, atau WireGuard dan orang lain seperti dia untuk membantu Anda.
Bagaimana itu bekerja?
Klien (yang biasanya berada di belakang NAT) menyiapkan terowongan (seperti pada contoh di atas) dan mengirimkan paket yang diautentikasi ke server sehingga ia dapat mengkonfigurasi terowongan dari sisinya. Bergantung pada pengaturannya, ini bisa menjadi paket kosong (hanya agar server melihat IP publik: port koneksi), atau dengan data yang dengannya server dapat mengidentifikasi klien. Data dapat berupa frasa sandi teks biasa sederhana (analogi dengan HTTP Basic Auth muncul di benak) atau data yang diformat khusus yang ditandatangani dengan kunci pribadi (dengan analogi HTTP Digest Auth, hanya lebih kuat, lihat fungsi
client_auth
di kode).
Pada server (sisi dengan IP publik), saat startup, ipipou membuat penangan antrian nfqueue dan mengkonfigurasi netfilter sehingga paket yang diperlukan dikirim ke tempat tujuan: paket menginisialisasi koneksi ke antrian nfqueue, dan [hampir] sisanya langsung ke pendengar FOU.
Siapa yang tidak berada dalam subjek, nfqueue (atau NetfilterQueue) adalah hal yang istimewa
Untuk beberapa bahasa pemrograman ada binding untuk bekerja dengan nfqueue, untuk bash tidak ada (heh, tidak mengherankan), saya harus menggunakan python: ipipou menggunakan NetfilterQueue .
Jika kinerja tidak kritis, dengan bantuan hal ini Anda dapat dengan relatif cepat dan mudah memasak logika Anda sendiri untuk bekerja dengan paket pada tingkat yang cukup rendah, misalnya, memahat protokol transfer data eksperimental, atau mengendalikan layanan lokal dan jarak jauh dengan perilaku non-standar.
Soket mentah bekerja bergandengan tangan dengan nfqueue, misalnya, ketika terowongan sudah dikonfigurasi, dan FOU mendengarkan pada port yang diinginkan, itu tidak akan berfungsi dengan cara yang biasa untuk mengirim paket dari port yang sama - sibuk, tetapi Anda dapat mengambil dan mengaktifkan paket yang dibuat secara acak langsung ke jaringan antarmuka menggunakan soket mentah, meskipun menghasilkan paket seperti itu akan membutuhkan lebih banyak pekerjaan. Ini adalah bagaimana paket dengan otentikasi dibuat di ipipou.
Karena ipipou hanya memproses paket pertama dari koneksi (yah, yang berhasil bocor ke antrian sebelum koneksi dibuat), kinerja hampir tidak menderita.
Segera setelah server ipipou menerima paket yang diautentikasi, sebuah terowongan dibuat dan semua paket berikutnya dalam koneksi tersebut sudah diproses oleh kernel yang melewati nfqueue. Jika koneksinya buruk, maka paket pertama dari paket berikutnya akan dikirim ke antrian nfqueue, tergantung pada pengaturannya, jika ini bukan paket otentikasi, tetapi dari IP yang terakhir diingat dan port klien, itu dapat diteruskan atau dibuang. Jika paket yang diautentikasi berasal dari IP dan port baru, terowongan akan dikonfigurasi ulang untuk menggunakannya.
IPIP-over-FOU biasa memiliki masalah lain saat bekerja dengan NAT - Anda tidak dapat membuat dua tunnel IPIP yang dikemas dalam UDP dengan IP yang sama, karena modul FOU dan IPIP cukup terisolasi satu sama lain. Itu. sepasang klien di belakang satu IP publik tidak akan dapat terhubung secara bersamaan ke server yang sama dengan cara ini. Di masa mendatang, ini mungkin diselesaikan di tingkat kernel, tetapi ini tidak pasti. Sementara itu, masalah NAT dapat diatasi dengan NAT - jika kebetulan sepasang alamat IP telah ditempati oleh tunnel lain, ipipou akan NAT dari IP publik ke IP pribadi alternatif, voila! - Anda dapat membuat terowongan hingga port habis.
Karena tidak semua paket dalam koneksi ditandatangani, maka perlindungan sederhana seperti itu rentan terhadap MITM, jadi jika penjahat bersembunyi di jalur antara klien dan server, yang dapat mendengarkan dan mengontrol lalu lintas, dia dapat mengalihkan paket yang diautentikasi melalui alamat lain dan membuat terowongan dari host yang tidak tepercaya ...
Jika ada yang punya ide tentang cara memperbaikinya sambil tetap mempertahankan sebagian besar lalu lintas di inti, silakan angkat bicara.
Omong-omong, enkapsulasi UDP telah membuktikan dirinya dengan sangat baik. Dibandingkan dengan enkapsulasi melalui IP, ini jauh lebih stabil dan seringkali lebih cepat meskipun ada overhead header UDP tambahan. Hal ini disebabkan oleh fakta bahwa mayoritas host di Internet bekerja dengan cukup baik hanya dengan tiga protokol paling populer: TCP, UDP, ICMP. Bagian berwujud umumnya dapat membuang yang lainnya, atau memproses lebih lambat, karena dioptimalkan hanya untuk ketiganya.
Misalnya, oleh karena itu, QUICK, atas dasar HTTP / 3 dibuat, dibuat melalui UDP, bukan melalui IP.
Kata yang cukup baik, inilah saatnya untuk melihat cara kerjanya di "dunia nyata".
Pertarungan
Digunakan untuk meniru dunia nyata
iperf3
. Dalam hal tingkat kedekatan dengan kenyataan, ini tentang persaingan dunia nyata di Minecraft, tetapi untuk saat ini itu akan dilakukan.
Kompetisi tersebut melibatkan:
- referensi saluran induk
- Pahlawan artikel ini adalah ipipou
- OpenVPN dengan otentikasi tetapi tanpa enkripsi
- OpenVPN All Inclusive
- WireGuard tanpa PresharedKey, dengan MTU = 1440 (hanya untuk IPv4)
Data teknis untuk para geek
Metrik diambil dengan perintah berikut
di klien:
UDP
TCP
Latensi ICMP
( ):
UDP
TCP
ipipou
openvpn ( , )
openvpn (c , , UDP, )
openvpn-manage
wireguard
di 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"
Latensi ICMP
ping -c 10 SERVER_IP | tail -1
( ):
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"
ipipou
/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
/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 ( , )
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
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 (c , , UDP, )
openvpn-manage
wireguard
/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
/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
hasil
Tablet Jelek Mentah
CPU , .. :
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 untuk saluran 20 Mbps
untuk 1 Gbps optimis
Dalam semua kasus, ipipou cukup dekat dalam hal kinerja dengan saluran dasar, dan itu hebat!
Terowongan openvpn yang tidak terenkripsi berperilaku agak aneh dalam kedua kasus.
Jika ada yang akan mengujinya, akan menarik untuk mendengar tanggapannya.
Semoga IPv6 dan NetPrickle bersama kami!