OpenVPN errno 2 অভিযোগ নিয়ে থেমে যায়, সেটি /dev/net/tun সম্পর্কে, অথচ lsmod tun মডিউলটি সহজেই তালিকাভুক্ত করে। দুটি তথ্যই একই সময়ে সত্য। মডিউলটি ড্রাইভার দেয়, আর ক্লায়েন্ট যে পথটি খোলে সেটি একটি ডিভাইস নোড, যা অন্য কিছুর তৈরি করতে হয়। এদের একই বস্তু হিসেবে ধরা হলো সেই কারণ যার জন্য মডিউল পুনরায় লোড করার আপাত সমাধান কিছুই বদলায় না।

দুটি বস্তু, দুটি ভিন্ন মালিক

কার্নেল মডিউল ও ডিভাইস নোড স্বতন্ত্র জীবনচক্রযুক্ত স্বতন্ত্র বস্তু। মডিউল লোড করলে একটি ড্রাইভার নিবন্ধিত হয়, এবং devtmpfs থাকা সিস্টেমে কার্নেল সংশ্লিষ্ট নোড তৈরি করতে বলে। devtmpfs না থাকা সিস্টেমে কিছুই কিছু তৈরি করে না, এবং ড্রাইভারটি সেখানে বসে থাকে, তাকে দেখানো কোনো পথ ছাড়াই। মডিউলটি একই মুহূর্তে লোডেড, সুস্থ এবং ফাইলসিস্টেমের মাধ্যমে সম্পূর্ণ অপ্রাপ্য হতে পারে।

এই কারণেই ত্রুটির লেখা ও মডিউল তালিকা পরস্পরবিরোধী নয়। ক্লায়েন্ট একটি পথ খোলে, পথটি নেই, এবং tun ড্রাইভারকে জিজ্ঞাসা করার আগেই কার্নেল ENOENT ফেরত দেয়। মডিউল পুনরায় লোড করা অনুপস্থিত পথ ঠিক করতে পারে না, আর পথ তৈরি করা অনুপস্থিত ড্রাইভার ঠিক করতে পারে না।

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 বা udev-পরিচালিত /devকোনোটিই মাউন্ট করে না, তাই কোনো প্রক্রিয়া কখনো নোড লেখে না। এরপর /devযেটিই হোস্ট করুক, তার মাউন্ট অপশন পড়ুন, কারণ nodev পথটি থাকতে দেয় কিন্তু তা খুলতে অস্বীকার করে, আর কঠোর করা হোস্ট থেকে নেওয়া bind মাউন্ট নিজে না জানিয়েই ফ্ল্যাগটি বহন করে। শুধু-পাঠযোগ্য মাউন্ট আরও আগে ও আরও জোরে ব্যর্থ হয়: 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 সহ ক্যারেক্টার ডিভাইস কি না, মাউন্ট অপশন পরিষ্কার কি না, প্রক্রিয়া প্রসঙ্গে সামর্থ্য আছে কি না, এবং ব্যর্থতার টাইমস্ট্যাম্পে নীতি প্রত্যাখ্যান আছে কি না। পাঁচটিই পেরিয়ে যাওয়া কোনো খুঁত ডিভাইসের সমস্যা নয়, বার্তাটি যা-ই উল্লেখ করুক।

সম্পর্কিত নিবন্ধ