อุโมงค์ IP ที่เรียบง่ายมาก อิงตาม DTLS
หากไม่จำเป็นต้องมีการเข้ารหัสที่รัดกุม คุณสามารถลองใช้ utun ที่มีน้ำหนักเบากว่านี้ได้หรือไม่
go install github.com/taoso/dtun/cmd/dtun
# 服务端
dtun -key foo
# 客户端
dtun -connect addr:port -key foo
ต่อไปนี้คือรายการปัจจัยบางประการที่ควรพิจารณาโดยย่อ
ไม่ใช่เรื่องง่ายที่จะบรรลุการเข้ารหัสข้อมูลเลเยอร์การขนส่งที่เสถียรและเชื่อถือได้ ดังนั้นฉันจึงใช้ TLS เป็นโปรโตคอลพื้นฐานมาโดยตลอด
TLS ใช้ TCP และข้อมูลที่เข้ารหัสก็เป็นข้อมูล TCP ในระดับสูงเช่นกัน ด้วยวิธีนี้ การส่งแพ็กเก็ตข้อมูลชั้นบนจำเป็นต้องมีการยืนยันการเชื่อมต่อ TCP ภายในและภายนอก ปัญหาการใช้งาน TCP ประเภทนี้บน TCP นั้นไม่ใช่เรื่องเล็ก สำหรับรายละเอียด โปรดดูที่: อ้างอิง http://sites.inka.de/~bigred/devel/tcp-tcp.html
ดังนั้นจึงเป็นการดีที่สุดที่จะใช้การส่งผ่าน UDP โดยปกติแล้ว DTLS จะใช้สำหรับการเข้ารหัส ปัจจุบัน DTLS ไม่รองรับ 1.3 และภาษา go ไม่รองรับอย่างเป็นทางการ คุณสามารถใช้ได้เฉพาะการใช้งานของบุคคลที่สามนี้ https://github.com/pion/dtls
ไม่ว่าจะเป็น TLS หรือ DTLS โดยทั่วไปคุณจะต้องสร้างใบรับรอง ขณะนี้กระบวนการนี้ไม่มีค่าใช้จ่าย แต่ยังกำหนดค่าได้ยาก นอกจากนี้ ใบรับรองจะแก้ปัญหาการเข้ารหัสเท่านั้น และไม่ได้แก้ปัญหาการตรวจสอบสิทธิ์ โดยปกติแล้วจะมีเพียงไคลเอ็นต์เท่านั้นที่ตรวจสอบใบรับรองเซิร์ฟเวอร์ คุณยังสามารถให้เซิร์ฟเวอร์ตรวจสอบใบรับรองไคลเอ็นต์ได้ แต่การดำเนินการนี้ยุ่งยากเกินไป
นอกจากนี้ DTLS ยังไม่มีการเชื่อมต่อและไม่สามารถดำเนินการตรวจสอบสิทธิ์ได้เฉพาะเมื่อสร้างการเชื่อมต่อเช่นการเชื่อมต่อ TCP เท่านั้น
ดังนั้นจึงเป็นการดีที่สุดที่จะทำการรับรองความถูกต้องของปลายทั้งสองด้านให้เสร็จสิ้นในเวลาเดียวกันระหว่างการจับมือ DTLS ดังนั้นฉันจึงเลือกโหมด Pre-Shared Key (PSK) เราจำเป็นต้องใช้เพียง -key
เพื่อระบุคีย์หลักที่ปลายทั้งสองข้างเพื่อให้การรับรองความถูกต้องแบบ double-end เสร็จสมบูรณ์ ไม่สามารถสร้างเซสชัน DTLS ได้หากไคลเอนต์ไม่รู้จัก PSK
นอกจากนี้ PSK ยังต้องระบุพารามิเตอร์คำใบ้ด้วย คุณสามารถคิดว่ามันเป็นชื่อของ PSK ไม่ได้เชื่อมต่อ DTLS ดังนั้นจึงเป็นการยากที่จะระบุได้ว่าไคลเอ็นต์ออฟไลน์อยู่หรือไม่ ฉันตัดสินใจที่จะมีพารามิเตอร์คำใบ้ที่ไม่ซ้ำกันสำหรับลูกค้าแต่ละราย เซิร์ฟเวอร์จัดสรรอุปกรณ์ปรับแต่งสำหรับคำแนะนำ หากไคลเอ็นต์ถูกตัดการเชื่อมต่อและเชื่อมต่อใหม่ อุปกรณ์จูนหลายเครื่องจะไม่ถูกสร้างขึ้น แต่ผลข้างเคียงคือไคลเอ็นต์ที่มีข้อจำกัดเดียวกันไม่สามารถเข้าสู่ระบบพร้อมกันได้
เพื่อรองรับ Macos อุปกรณ์ปรับแต่งสามารถตั้งค่าเป็นโหมดจุดต่อจุดเท่านั้น หากเราต้องการกำหนดเส้นทางและการส่งต่ออย่างโปร่งใส ดูภาพด้านล่าง
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
เราหวังว่าแพ็คเก็ตที่ส่งโดยพีซีจะถูกส่งต่อไปยัง pc2 ผ่านเราเตอร์ จากนั้นส่งต่อไปยังเครือข่ายภายนอก โดยทั่วไป เราจะทำ NAT หนึ่งครั้งบนเราเตอร์ และอีกครั้งบน pc2 ข้อดีของสิ่งนี้ก็คือ pc2 ไม่จำเป็นต้องรู้การกำหนดค่าเครือข่ายของพีซีไปยังเราเตอร์ แต่ข้อเสียก็ชัดเจนเช่นกัน มีแนทสองตัว ประสิทธิภาพของเราเตอร์โดยทั่วไปไม่แข็งแกร่ง ดังนั้นควรหลีกเลี่ยง NAT ให้มากที่สุด
ดังนั้นแผนของฉันคือการผลักดันส่วนเครือข่าย 10.0.0.0/16 โดยตรงโดยที่พีซีอยู่ที่ pc2 และเพิ่มเส้นทางบน pc2
ip route add 10.0.0.0/16 via 10.1.0.1
ด้วยวิธีนี้ เราเตอร์สามารถส่งต่อแพ็กเก็ตจากพีซีไปยัง pc2 ได้โดยสมบูรณ์ และต้องทำ NAT เพียงครั้งเดียวบน pc2
บางครั้งเราจำเป็นต้องระบุรายการเส้นทางที่อนุญาต ใช้เส้นทางเริ่มต้นบนส่วนเครือข่ายในรายการที่อนุญาต และส่งต่อเส้นทางอื่นๆ ผ่านอุโมงค์
เราสามารถเพิ่มเส้นทางไวท์ลิสต์ให้กับเราเตอร์ก่อน และตั้งค่าการกระโดดถัดไปเป็นเส้นทางเริ่มต้นของเราเตอร์ จากนั้นระบุ IP สาธารณะของ pc2 เพื่อใช้เส้นทางเริ่มต้นของเราเตอร์ (คีย์!) เพิ่มครั้งล่าสุด
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
และ 128.0.0.1/1
ที่นี่เพียงครอบคลุมส่วนของเครือข่ายทั้งหมด เอฟเฟกต์จะเทียบเท่ากับค่าเริ่มต้น แต่จะไม่เขียนทับเส้นทางเริ่มต้น หากอุโมงค์ปิดอย่างผิดปกติ เส้นทางที่เกี่ยวข้องทั้งหมดจะถูกลบโดยอัตโนมัติซึ่งมีความเสถียรมาก
คุณสามารถเขียนเป็นสคริปต์และรันโดยใช้พารามิเตอร์ -up
สคริปต์ของฉันเป็นดังนี้:
#! /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