ipipou: lebih dari sekadar terowongan yang tidak terenkripsi

Apa yang kami katakan kepada dewa IPv6?



IPv6?  Tidak hari ini


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:





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 lokal
  • 203.0.113.1 - IP publik server
  • 198.51.100.2 - IP publik klien
  • 192.168.0.2 - IP klien ditugaskan ke antarmuka eth0
  • 10001 - port klien lokal untuk FOU
  • 20001 - port klien publik untuk FOU
  • 10000 - port server publik untuk FOU
  • encap-csum β€” UDP UDP ; noencap-csum, , ( )
  • eth0 β€” ipip
  • 172.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-dportdi 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_authdi 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 bagi amatir yang tidak tahu cara mengembangkan modul kernel , yang melalui netfilter (nftables / iptables) memungkinkan Anda untuk mengarahkan paket jaringan ke ruang pengguna dan memprosesnya di sana dengan cara improvisasi primitif : modifikasi (opsional ) dan mengembalikan ke kernel, atau buang.



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

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



perbandingan bandwidth pada 20 Mbps



perbandingan latensi pada 20 Mbps



untuk 1 Gbps optimis



Perbandingan bandwidth 1 Gbps



Perbandingan efisiensi CPU: Mbps / CPU_usage



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!



All Articles