نفق 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. لذلك اخترت وضع المفتاح المشترك مسبقًا (PSK). نحتاج فقط إلى استخدام -key
لتحديد المفتاح الرئيسي في كلا الطرفين لإكمال المصادقة المزدوجة. لا يمكن إنشاء جلسة 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
نأمل أن تتم إعادة توجيه الحزم المرسلة بواسطة الكمبيوتر إلى جهاز الكمبيوتر 2 عبر جهاز التوجيه ثم إعادة توجيهها إلى الشبكة الخارجية. بشكل عام، سنقوم بإجراء NAT مرة واحدة على جهاز التوجيه ثم مرة واحدة على جهاز الكمبيوتر 2. وتتمثل ميزة ذلك في أن جهاز الكمبيوتر 2 لا يحتاج إلى معرفة تكوين شبكة الكمبيوتر لجهاز التوجيه. لكن العيوب واضحة أيضًا، فهناك نوعان من النات. أداء أجهزة التوجيه ليس قويًا بشكل عام، لذا يجب تجنب NAT قدر الإمكان.
لذا فإن خطتي هي دفع جزء الشبكة مباشرة 10.0.0.0/16 حيث يوجد الكمبيوتر الشخصي إلى pc2 وإضافة مسار على pc2
ip route add 10.0.0.0/16 via 10.1.0.1
بهذه الطريقة، يمكن لجهاز التوجيه إعادة توجيه الحزم من جهاز الكمبيوتر إلى جهاز الكمبيوتر الشخصي 2 سليمًا، ويحتاج إلى إجراء NAT مرة واحدة فقط على جهاز الكمبيوتر الشخصي 2.
في بعض الأحيان نحتاج إلى تحديد قائمة بيضاء للتوجيه. استخدم المسار الافتراضي لأجزاء الشبكة في القائمة البيضاء، وأعد توجيه الأجزاء الأخرى عبر النفق.
يمكننا إضافة مسار القائمة البيضاء إلى جهاز التوجيه أولاً، وتعيين الخطوة التالية إلى المسار الافتراضي لجهاز التوجيه. ثم حدد عنوان 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