OpenVPN يتوقف مع شكوى errno 2 بشأن /dev/net/tun بينما lsmod يسرد وحدة tun بكل سرور. الحقيقتان صحيحتان في الوقت نفسه. الوحدة توفّر مشغّلًا، والمسار الذي يفتحه العميل هو عقدة جهاز يجب على شيء آخر إنشاؤها. التعامل معهما ككائن واحد هو سبب أن الإصلاح البديهي بإعادة تحميل الوحدة لا يغيّر شيئًا على الإطلاق.

كائنان، مالكَان مختلفان

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

لهذا لا يتناقض نص الخطأ مع قائمة الوحدات. يفتح العميل مسارًا، والمسار غير موجود، فتعيد النواة ENOENT قبل أن يُستشار مشغّل tun أصلًا. إعادة تحميل الوحدة لا تصلح مسارًا مفقودًا، وإنشاء المسار لا يصلح مشغّلًا مفقودًا.

lsmod | grep -w tun
stat -c "%F %t:%T" /dev/net/tun
grep " /dev " /proc/mounts

devtmpfs مقابل mknod صريح

آليتان تنشئان تلك العقدة عادةً، ومعرفة أيّهما يُفترض أن تكون مسؤولة تخبرك بما يجب إصلاحه. devtmpfs يجعل النواة تنشئ عقد الأجهزة في نسخة مركّبة، ويطبّق udev الملكية والأذونات فوقها. أما mknod فهو المسار اليدوي للصور والنطاقات حيث لا تعمل أي منهما عند الإقلاع.

قارن النتائج لا النوايا. إذا كان devtmpfs مركّبًا على /dev والعقدة ما زالت غائبة، فالمشغّل ليس الذي تفترضه، أو أن شيئًا حذف العقدة بعد الإقلاع. وإذا كان /dev مجلدًا عاديًا داخل rootfs غير مُحزَّم، فلا توجد آلية تلقائية ومن يبني الصورة عليه إنشاء العقدة.

stat -c "%F major=%t minor=%T" /dev/net/tun
# expect: character special file major=a minor=c8

حيث لا تعمل أي من الآليتين، يجب صنع العقدة يدويًا، والترتيب مهم. أنشئ المجلد الأب أولًا، لأن mknod لا يستطيع اختراعه، ثم جهاز الحرف، ثم وضعًا يجعله قابلًا للكتابة من root وحده. أعد تحميل الوحدة قبل إنشاء العقدة، ولا تحذف مسارًا موجودًا إلا بعد أن يُظهر ls أنه مجلد وليس جهازًا.

sudo modprobe tun
sudo mkdir -p /dev/net
sudo mknod /dev/net/tun c 10 200
sudo chmod 600 /dev/net/tun
ls -l /dev/net/tun

النوع الذي يبلّغ عنه stat هو أسرع مُميِّز، ووجود مجلد في ذلك المسار هو أكثر المفاجآت شيوعًا في الصور المصغّرة. أما mkdir بحسن نية في Dockerfile فيترك ذلك بالضبط، ولا مقدار من تحميل الوحدات يستبدل مجلدًا بجهاز حرف. الزوج Major 10 مع minor 200 هو الزوج المسجّل لـ tun، ويُعبَّر عنه بالست عشري بـ a و c8.

أربعة آثار، أربعة أسباب

أربعة أسباب تفسّر تقريبًا كل حالة، وكل منها يترك أثرًا مختلفًا في السجلات. ابدأ ببيئة الإقلاع. الصور بلا أقراص واللوحات المدمجة ومراحل initramfs غالبًا لا تركّب devtmpfs ولا /devيديره udev، فلا يكتب أي عملية العقدة. ثم اقرأ خيارات التركيب على أي شيء يستضيف /dev، لأن nodev يسمح بوجود المسار مع رفض فتحه، والتركيب المرتبط المأخوذ من مضيف محصّن يحمل العلامة دون أن يعلن نفسه. التركيب للقراءة فقط يفشل أبكر وأعلى صوتًا: mknod يعيد EROFS هناك، بينما EPERM يعني أن العملية تفتقر إلى القدرة لا أن نظام الملفات يحمي نفسه. وأخيرًا، وقت تشغيل حاويات له /dev tmpfs خاص به يحتاج إلى حقن العقدة في نطاقه الخاص، ويجب أن تسمح cgroup الأجهزة الخاصة به بزوج major و minor.

افحص طبقة السياسة قبل تغيير الأذونات مرة أخرى. يمكن لـ SELinux وAppArmor رفض فتح تسمح به كل سمات الملف، ويظهر ذلك الرفض في سجل التدقيق لا في مخرجات العميل. تغيير إذن لا يظهر أبدًا في رفض ما هو وقت يُهدر في الطبقة الخاطئة تمامًا.

sudo journalctl -k -n 20 --no-pager
sudo ausearch -m AVC -ts recent | tail -5

أثبته بواجهة، لا بقائمة

قائمة ناجحة تثبت وجود مسار ولا شيء أكثر. افتح عقدة tun سليمة للقراءة فيعود النداء بخطأ، لأن الجهاز لا دلالات قراءة له وليس ملفًا عاديًا. ذلك الخطأ هو إشارة النجاح هنا، والتعرف عليه يمنعك من ملاحقته كعيب.

head -c 1 /dev/net/tun
head: error reading '/dev/net/tun': File descriptor in bad state

الاختبار الحاسم ينشئ واجهة، لأنه يمرّن المشغّل والعقدة وصلاحياتك في خطوة واحدة. إذا نجحت الإضافة وظهر الرابط، فالثلاثة تعمل. وعندما يفشل، يفصل errno الأسباب: ENOENT يعني عدم وجود عقدة صالحة، وEPERM يشير إلى القدرة أو أعلام التركيب أو السياسة، وEBUSY يعني أن عملية أخرى تملك الواجهة بالفعل.

sudo ip tuntap add dev tun7 mode tun
ip -brief link show tun7
sudo ip tuntap del dev tun7 mode tun

شغّل ذلك الاختبار في السياق الذي يفشل فعلًا، لأن وحدة خدمة أو حاوية أو مهمة مجدولة قد تحمل مجموعة قدرات مختلفة عن صدفة دخولك. اختبار ينجح في السياق الخاطئ لا يثبت شيئًا عن السياق الفاشل.

عندما لا يكون الجهاز هو المشكلة

إذا نجح اختبار الواجهة وما زال العميل يفشل، فالمشكلة المتبقية هي الملف الشخصي أو سياق الخدمة أو المسار، والجهاز سليم. تلك هي اللحظة للتوقف عن تعديل عقد الأجهزة، لأن التغييرات الإضافية تزيد فقط المسافة عن نظام عامل.

شغّل الفحوص الخمسة نفسها كل مرة بدلًا من اختراع فحص جديد: هل الوحدة محمّلة دون وحدة منافسة، هل المسار جهاز حرف بالـ major والـ minor الصحيحين، هل خيارات التركيب نظيفة، هل سياق العملية يحمل القدرة، وهل يوجد رفض سياسة عند الطابع الزمني للفشل. عيب ينجو من الخمسة كلها ليس مشكلة جهاز، أيًا كان ما تذكره الرسالة.

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