يتصل العميل بخادم OpenVPN على جهاز Compute Engine الافتراضي، وتقول نافذة الحالة إنه متصل، ومع ذلك لا يصل ping إلى مضيف داخل VPC إلى أي مكان. الغريزة تقول بإضافة سطر push آخر، وهذا لا يصلح المشكلة أبدًا. يقرر Compute Engine إلى أين تذهب الحزم بناءً على جدول المسارات الخاص به وبناءً على العناوين التي تملكها واجهة الجهاز الافتراضي فعليًا، لذا فإن pool النفق الذي لا يملكه الجهاز الافتراضي هو pool لا يسلّم إليه أحد.

تابع الحزمة التي تفشل بدلًا من ملف التكوين، وستظهر الأجزاء الناقصة بالترتيب.

ابدأ من الحزمة التي تموت

تغادر حزمة SYN العميل، وتدخل النفق، وتصل إلى الجهاز الافتراضي كحزمة مغلفة نحو وجهة داخل VPC. يفك OpenVPN تغليفها ويحاول تمريرها عبر eth0، حيث تطرح البنية سؤالًا واحدًا قبل أي شيء آخر: هل تملك هذه النسخة عنوان الوجهة. إن pool النفق المقتطع من subnet شخص آخر يفشل في ذلك السؤال، وتُسقط الحزمة قبل النظر في أي مسار أو قاعدة جدار حماية.

لذا فإن الاتجاه من العميل إلى VPC له متطلبان منفصلان، ولا يُعد أي منهما توجيه push. يحتاج الجهاز الافتراضي إلى نطاق alias يغطي pool النفق، وهذا ما يجعله المالك الشرعي لتلك العناوين. ويحتاج VPC إلى مسار يسمّي الجهاز الافتراضي كـ next hop لكل بادئة محمية. إن غاب أحدهما ماتت الحزمة في مكان آخر، بينما يرى العميل الصمت نفسه.

اقرأ العطل بهذا الترتيب، لأن الشرطين يبدوان متطابقين من جهة العميل. النفق الذي يعلن الاتصال بينما لا يجيب شيء هو بصمة مشكلة طوبولوجيا، لا بصمة تشفير سيئ.

هل تملك النسخة pool النفق

امنح الجهاز الافتراضي نطاقًا ثانويًا داخل subnet الخاص به، ثم اجعل OpenVPN يوزع عناوين من ذلك النطاق بالضبط. على نسخة عنوانها الأساسي 10.156.0.10/20، يحفظ alias /28 الـ pool منفصلًا عن العناوين التي تملكها نسخ أخرى بالفعل:

gcloud compute instances network-interfaces update openvpn-vm \
  --zone=europe-west1-b \
  --aliases=eth0:10.156.1.0/28

عندئذٍ يجب أن تصف توجيهات server الكتلة نفسها. يصبح عنوانها الأول بوابة النفق، وتُوزع العناوين المتبقية على العملاء. هنا يصف رقمان كتلة واحدة، شبكة وقناع شبكة، وهذه هي صيغة الـ pool التي لا يزال OpenVPN يتوقعها.

server 10.156.1.0 255.255.255.240

تأكد من أن العنوان وصل فعليًا إلى الواجهة وليس فقط داخل تكوين OpenVPN. تمرر البنية ما تبلغ عنه بطاقة الشبكة، لا ما يعتقده الـ daemon. أمر واحد يحسم ذلك:

ip -4 addr show dev eth0

العنوان الثانوي الذي لا يصل أبدًا إلى eth0، أو الـ pool الذي يتداخل مع subnet آخر، يظهر لاحقًا كفقدان متقطع لا كخطأ في بدء التشغيل. يبدأ الـ daemon، ويتصل العملاء، ولا تسيء التصرف إلا بعض الوجهات. أبقِ نطاق alias صغيرًا ليكون الـ pool سهل التمييز في جدول المسارات. لا تقتطعه أبدًا من subnet تستخدمه نسخة أخرى بالفعل.

امنح حركة العودة next hop

يُوجَّه رد من مضيف في VPC إلى عنوان عميل في pool النفق، وهو عنوان لا ينتمي إلى أي subnet يعرفه VPC. وبدون مسار لذلك الـ pool يتوقف الرد عند أول hop لا يجد تطابقًا، وقد يكون الطلب قد نجح تمامًا في الطرف الآخر.

gcloud compute routes create openvpn-return \
  --network=prod-vpc \
  --destination-range=192.168.127.0/24 \
  --next-hop-instance=openvpn-vm \
  --next-hop-instance-zone=europe-west1-b \
  --priority=800

المسار نفسه مطلوب لأي بادئة تقع خلف عميل بدلًا من داخل VPC. وتحتاج تلك البادئات أيضًا إلى إدخال iroute في ملف ccd لذلك العميل. ذلك الإدخال محاسبة من جهة الخادم: يخبر الخادم أي عميل يملك البادئة، ولا يثبّت شيئًا على العميل نفسه.

أبقِ قائمة push لجانب العميل من المحادثة، لأنها تضيف مسارات إلى الجهاز المتصل فقط. سطر push لـ subnet في VPC ومسار VPC عائد إلى الـ pool هما نصفا المسار نفسه، وكل نصف وحده ينتج نفقًا يحمل الطلبات ولا يحمل الردود.

جدران الحماية والتمرير والـ hops بينها

يقيّم جدار حماية VPC الحزمة بعد فك التغليف، لذا يجب أن تسمح قاعدة ingress بـ pool النفق وأي بادئة موقع تصل إلى الجهاز الافتراضي بتلك الطريقة. موقف الرفض الافتراضي يفشل هنا بصمت: تُسقط الحزمة بعد فك التغليف، ويظهر سجل OpenVPN جلسة سليمة.

على أي مضيف Linux يمرر بدلًا من أن ينهي، تحقق من أن net.ipv4.ip_forward مفعّل. تنطبق قاعدة الملكية هناك أيضًا: الجهاز الذي يمرر لـ subnet لا يملكه يُسقط الحزمة تمامًا كما يفعل الجهاز الافتراضي. اقرأ القيمة قبل أن تلوم النفق.

عندما تفشل بادئة واحدة بالضبط

الفشل الجزئي هو الحالة الأسهل قراءة، لأن كل شيء آخر في المسار مُثبت بالفعل. ابدأ بقائمة المسارات واقرأ نطاق الوجهة وnext hop للإدخال الذي يفترض أن يغطي البادئة، ثم اقرأ وصف النسخة وقارن نطاق alias الخاص بها مع الـ pool الذي يوزعه الخادم.

gcloud compute routes list --filter=destination-range~10.164.0.0
 gcloud compute instances describe openvpn-vm --format=get(networkInterfaces[0].aliasIpRanges)

المسار الناقص يظهر كغياب next hop للبادئة، بينما يظهر الـ alias الناقص كحزمة تُسقط عند الواجهة؛ من جهة العميل يبدو الأمران متشابهين، وفي هذين المخرجين مختلفان تمامًا. إن وُجد الاثنان معًا، فإن المشتبه المتبقي هو iroute في ccd الخاص بالعميل الذي يدّعي البادئة.

اكتب القيم الأربع بجوار النفق: نطاق alias، وpool الخادم، والبادئات المدفوعة، ومسارات VPC. الـ alias القديم يكسر كل عنوان في الـ pool، والمسار القديم يكسر اتجاهًا واحدًا، وpush الناقص يخفي البادئة عن العميل، وiroute الخاطئ يرسل البادئة إلى peer خاطئ. الشخص التالي الذي يضيف subnet يحتاج الأربعة في مكان واحد، والملاحظة أرخص من الأمسية.

مقالات ذات صلة