Terowongan IP yang sangat sederhana, berdasarkan DTLS.
Jika tidak diperlukan enkripsi yang kuat, Anda dapat mempertimbangkan untuk menggunakan utun yang lebih ringan?
go install github.com/taoso/dtun/cmd/dtun
# 服务端
dtun -key foo
# 客户端
dtun -connect addr:port -key foo
Berikut daftar singkat beberapa faktor yang perlu dipertimbangkan.
Tidak mudah untuk mencapai enkripsi data lapisan transport yang stabil dan andal, jadi saya selalu menggunakan TLS sebagai protokol dasarnya.
TLS menggunakan TCP, dan sebagian besar data terenkripsi juga merupakan data TCP. Dengan cara ini, transmisi paket data lapisan atas memerlukan konfirmasi koneksi TCP dalam dan luar. Masalah implementasi TCP melalui TCP semacam ini tidaklah kecil.
Oleh karena itu, yang terbaik adalah menggunakan transmisi UDP. Tentu saja, DTLS digunakan untuk enkripsi. Saat ini, DTLS tidak mendukung 1.3, dan bahasa go tidak secara resmi mendukungnya. Anda hanya dapat menggunakan implementasi pihak ketiga ini https://github.com/pion/dtls
Baik itu TLS atau DTLS, biasanya Anda perlu membuat sertifikat. Proses ini sekarang gratis, tetapi konfigurasinya masih rumit. Selain itu, sertifikat hanya menyelesaikan masalah enkripsi dan tidak menyelesaikan masalah otentikasi. Biasanya hanya klien yang memverifikasi sertifikat server. Anda juga dapat membiarkan server memverifikasi sertifikat klien, tapi ini terlalu merepotkan.
Selain itu, DTLS tidak memiliki koneksi dan tidak hanya dapat melakukan otentikasi saat membuat koneksi seperti koneksi TCP.
Oleh karena itu, yang terbaik adalah menyelesaikan otentikasi kedua ujungnya secara bersamaan selama jabat tangan DTLS. Jadi saya memilih mode Pre-Shared Key (PSK). Kita hanya perlu menggunakan -key
untuk menentukan kunci master di kedua ujungnya untuk menyelesaikan otentikasi dua ujung. Sesi DTLS tidak dapat dilakukan jika klien tidak mengetahui PSK.
Selain itu, PSK juga perlu menentukan parameter petunjuk. Anggap saja sebagai nama PSK. DTLS tidak terhubung, sehingga sulit untuk menentukan apakah klien telah offline. Saya memutuskan untuk memiliki parameter petunjuk unik untuk setiap klien. Server mengalokasikan perangkat tun untuk petunjuk. Jika klien terputus dan tersambung kembali, beberapa perangkat tun tidak akan dibuat. Namun efek sampingnya adalah klien dengan petunjuk yang sama tidak dapat login pada waktu yang sama.
Untuk mendukung macOS, perangkat tun hanya dapat diatur ke mode point-to-point. Jika kita ingin melakukan routing dan forwarding secara transparan, lihat gambar dibawah ini
pc <-----------> router <====== dtun ======> pc2 <---------> www
10.0.0.2/16 10.0.0.1/16 10.1.0.1/16 10.1.0.2/16
Harapannya paket yang dikirim melalui pc diteruskan ke pc2 melalui router dan kemudian diteruskan ke jaringan eksternal. Umumnya kita akan melakukan NAT satu kali di router dan kemudian di pc2. Kelebihannya adalah pc2 tidak perlu mengetahui konfigurasi jaringan pc ke router. Tapi kekurangannya juga jelas, ada dua nat. Kinerja router umumnya tidak kuat, jadi NAT harus dihindari sebisa mungkin.
Jadi rencana saya adalah langsung mendorong segmen jaringan 10.0.0.0/16 dimana pc berada ke pc2 dan menambahkan rute di pc2
ip route add 10.0.0.0/16 via 10.1.0.1
Dengan cara ini, router dapat meneruskan paket dari pc ke pc2 secara utuh, dan hanya perlu melakukan NAT satu kali di pc2.
Terkadang kita perlu menentukan daftar putih perutean. Gunakan rute default pada segmen jaringan dalam daftar putih, dan teruskan yang lain melalui terowongan.
Kita dapat menambahkan rute daftar putih ke router terlebih dahulu, dan mengatur hop berikutnya ke rute default router. Kemudian tentukan IP publik pc2 untuk mengambil rute default router (kunci!). terakhir ditambahkan
ip route add 0.0.0.0/1 via 10.1.0.2
ip route add 128.0.0.0/1 via 10.1.0.2
0.0.0.0/1
dan 128.0.0.1/1
di sini hanya mencakup seluruh segmen jaringan. Efeknya setara dengan default, tetapi tidak akan menimpa rute default. Jika terowongan ditutup secara tidak normal, semua rute terkait akan dihapus secara otomatis, yang mana ini sangat stabil.
Anda dapat menulisnya sebagai skrip dan menjalankannya menggunakan parameter -up
. Skrip saya adalah sebagai berikut:
#! /bin/sh
# curl -S https://cdn.jsdelivr.net/gh/misakaio/chnroutes2@master/chnroutes.txt|grep -v '#'|xargs -I % ip route add % via $DEFAULT_GW 2>/dev/null
VPN_IP= $( ping your-server-name -c 1 | grep from | cut -d ' ' -f4 | cut -d: -f1 )
DEFAULT_GW= $( ip route | grep default | cut -d ' ' -f3 )
ip route add $VPN_IP /32 via $DEFAULT_GW
ip route add 0.0.0.0/1 via $PEER_IP
ip route add 128.0.0.0/1 via $PEER_IP