OpenVPN عبر SOCKS5: طابق الإصدار والنقل وDNS
تفشل سلسلة SOCKS حين يختلف إصدار الوكيل أو النقل أو مسار DNS. طابق SOCKS5، واحمل TCP، وأبقِ السلسلة داخل فضاء أسماء.
أحد المسارات الخارجة من محطة العمل هذه وكيل SOCKS، بينما يبلّغ OpenVPN خلفه عن مهلة اتصال دون أي تفصيل مفيد. المتصفح على الجهاز نفسه يعمل عبر ذلك الوكيل، وبيانات الاعتماد صحيحة، والمنفذ يستجيب. ثلاثة أشياء تختلف كثيرًا بما يكفي لفحصها أولًا: إصدار SOCKS الذي يتحدثه الوكيل، والنقل الذي اختاره العميل، وكذلك مكان حدوث تحليل الأسماء. تحقق من كل واحد منها قبل أن تحكم بأن جدار الحماية هو السبب.
طابق إصدار SOCKS قبل جدار الحماية
OpenVPN المجتمعي يتحدث SOCKS5 من أجل socks-proxy. وجّهه إلى وكيل لا يقدّم سوى SOCKS4 فيُفتح اتصال TCP ثم يتوقف، لأن العميل ينتظر ردًا على تحية لا يحلّلها الطرف الآخر أبدًا. من الخارج يبدو هذا التوقف تمامًا كمنفذ مُرشَّح، ولهذا يأتي سؤال الإصدار قبل أي قاعدة جدار حماية. جلب واحد يدرك SOCKS يحسم الأمر بأمر واحد.
curl --socks5-hostname 127.0.0.1:9050 gw.lab.example
الطلب المكتمل يثبت أمرين معًا: الوكيل قَبِل طلب SOCKS وحلّ الاسم. لا حاجة إلى مخطط URL، لأن curl يعامل المضيف المجرد بوصفه HTTP، وهذا يكفي لهذا الاختبار.
ذلك الجلب يستبعد أيضًا العطل الذي يخفيه سجل العميل. يمكن للوكيل أن يسمح للمتصفح ويرفض في الوقت نفسه وجهة VPN، وحينها يقع الرفض عند CONNECT قبل أي مصادقة VPN. لا يبلّغ OpenVPN إلا عن مهلة، لذا فجواب الوكيل نفسه هو الدليل الذي تحتاجه.
يجب أن يكون النقل TCP على الطرفين
SOCKS5 يحمل هنا تدفق TCP، لذا يحتاج النفق نفسه إلى proto tcp-client. ملف تعريف ما زال مضبوطًا على UDP لن يعمل عبر هذا المسار، لأن العميل لا يستخدم وضع اقتران UDP الخاص بالبروتوكول. قلب الملف تغيير حقيقي وليس شكليًا: يجب أن يكون الطرف البعيد مستمعًا على TCP على المنفذ نفسه. ثم تصبح الحمولة TCP داخل TCP، حيث تُعاد إرسال القطعة المفقودة مرتين ويتراجع الإيقاع، وهو ما تلاحظه الجلسات التفاعلية أكثر بكثير من النقل الكبير.
proto tcp-client
remote gw.lab.example 8443
socks-proxy 127.0.0.1 9050
يأخذ التوجيه مضيف الوكيل ومنفذًا اختياريًا وملف بيانات اعتماد اختياريًا. ضعها في ملف التعريف نفسه كي تتصرف نسخة أخرى بالطريقة نفسها في مكان آخر.
احصر السلسلة كلها في حاوية واحدة
إجراء السلسلة على المضيف يعني الاستيلاء على مساره الافتراضي وترك المُحلِّل في حالة لا يستطيع أحد شرحها لاحقًا. فضاء أسماء أو حاوية يحصرها بدلًا من ذلك، فيحتفظ المضيف بمساره بينما تعيش قفزة SOCKS والنفق معًا. لا شيء ينهض داخلها دون جهاز نفق، وحقوق ضبط ذلك الجهاز، ووكيل يمكن الوصول إليه. خدمة Compose تحصل على ذلك عبر cap_add: NET_ADMIN و /dev/net/tun مربوط.
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
هذا الزوج أضيق من تشغيل الحاوية بامتيازات كاملة، وهو كل ما يلزم من وصول إلى الجهاز. يمكن لعميل Tor أو حاوية وكيل منفصلة أن توفّر المستمع. في الحالتين اربطه بواجهة loopback، واصله من فضاء الأسماء عبر المضيف بدل تعريض الوكيل للشبكة.
تحليل الأسماء هو مكان فشل العزل
نفق يحمل الحزم بينما يسأل مُحلِّل المضيف لم يعزل شيئًا. أمران يجعلان العزل حقيقيًا: أن يكون لفضاء الأسماء مُحلِّله الخاص، وأن تمر استعلاماته عبر الوكيل أو النفق، لا عبر الواجهة الفيزيائية أبدًا. استخدم اسمين للاختبار: اسمًا لا يوجد إلا خلف النفق، وآخر عامًا ينبغي أن يسلك المسار نفسه.
docker compose exec vpn cat /etc/resolv.conf
docker compose exec vpn getent hosts internal.lab.example
إذا حُلّ الاسم البعيد ولم يُحلّ الاسم العام، فالسلسلة انتقائية لا معطوبة، والفرق يخبرك بالمسار الذي سلكه كل استعلام. وإذا حُلّ الاثنان من المضيف ولم يُحلّ أي منهما داخل الحاوية، فالحاوية ما زالت تستعير مُحلِّل المضيف. سجّل ملف المُحلِّل الذي وجدته، لأن ذلك هو الإعداد الذي يجب تغييره.
أثبت كل قفزة بالترتيب
القائمة قصيرة. طلب SOCKS5 يحصل على جواب، والنفق يصل إلى مستمعه عبر الوكيل، والحزم الخارجة من فضاء الأسماء تحمل العنوان الذي يتوقعه الطرف البعيد. تحقق من كل واحد على حدة بدل إضافة مزيد من الإعداد. عندما يقول العميل إنه متصل ولا يتحرك شيء، يكون الانقطاع دائمًا تقريبًا في الحقيقة الثانية أو الثالثة.
curl --socks5-hostname 127.0.0.1:9050 gw.lab.example
docker compose exec vpn ip route get 203.0.113.10
docker compose exec vpn getent hosts internal.lab.example
دوّن التركيبة التي نجحت: إصدار SOCKS، والنقل، وإعدادات المُحلِّل وفضاء الأسماء. حل هذه السلسلة مرة ثانية من الذاكرة يكلف أكثر من الملاحظة. احتفظ بتلك الحقائق الأربع في التذكرة لا في سلسلة محادثة.
السلسلة التي تبلّغ عن الاتصال ولا تمرر شيئًا فشلت عادةً عند القفزة التي لم تثبتها بعد. اختبر تلك القفزة قبل إضافة طبقة أخرى.