VPN সংযোগ-পরবর্তী কাজটি ডেমন নয়, ব্যবহারকারী হিসেবেই চালান
USER=alice বলে এমন একটি পরিবেশ চলক হুকটি কোন অ্যাকাউন্টে চলে তা বদলায় না। ঘটনা, ট্রিগার ও কাজ আলাদা করুন, তারপর UID প্রমাণ করুন।
একটি VPN ডেমনের সংযোগ হুকগুলো ডেমন হিসেবেই চলে, এবং সাধারণত এর অর্থ সেগুলো root হিসেবে চলে। ওই হুকগুলোর একটি যখন কারও হোম ডিরেক্টরিতে লেখে বা কোনো ডেস্কটপ সহায়ক পুনরায় চালু করে, তখন আপনি একটি নেটওয়ার্ক ঘটনাকে যেকোনো স্থানীয় ব্যবহারকারী হিসেবে কাজ করার ক্ষমতা দিয়ে দেন। চেনা শর্টকাটটি, অর্থাৎ পরিবেশ চলক থেকে ব্যবহারকারীর নাম পড়ে সেটি পাস করা, সমস্যাটি মেটায় না। এটি অ্যাকশনটিকে নতুন লেবেল দেয়, কিন্তু কোন অ্যাকাউন্ট সেটি চালায় তা বদলায় না। যা কাজ করে তা হলো তিন অংশের হস্তান্তর, যেখানে সুবিধাভোগী ধাপটি বলে কী ঘটেছে এবং একটি আলাদা ইউনিট সঠিক পরিচয়ে কাজটি করে।
পরিবেশে থাকা ব্যবহারকারীর নাম কোনো পরিচয়-সুইচ নয়
Unix ঠিক করে একটি প্রসেস কী স্পর্শ করতে পারবে তা তার কার্যকর ব্যবহারকারী আইডি থেকে, তার পরিবেশের স্ট্রিং থেকে নয়। USER=alice সেট করা বা LOGNAME এক্সপোর্ট করা অসতর্ক সফটওয়্যার আউটপুটে কী ছাপে তা বদলায়; ফাইল মালিকানা যাচাইয়ে কিছুই বদলায় না। ওই চলক সেট থাকা অবস্থায় root হিসেবে চলা হুকটি তখনও root হিসেবেই অ্যালিসের ফাইল খোলে।
নামগুলোও একই নাম নয়। রিমোট অ্যাক্সেস লগইন, স্থানীয় Unix অ্যাকাউন্ট এবং সার্টিফিকেটের কমন নেম, এই তিনটি শনাক্তকারী প্রায়ই মিলে যায় আর মাঝে মাঝে মেলে না। যে ব্যবহারকারী a.smith হিসেবে প্রমাণিত হয়, তার স্থানীয় অ্যাকাউন্ট একেবারেই না থাকতে পারে, অথবা ডিরেক্টরি সেবার মাধ্যমে asmith-এ ম্যাপ হতে পারে। একটি স্ট্রিংই তিনটি ভূমিকা পালন করবে ধরে নেওয়া যেকোনো নকশা প্রথম চুক্তিকর্মীর কাছেই ভেঙে পড়বে।
তাই প্রথম প্রশ্নটি «কে সংযুক্ত» নয়, বরং «কোন স্থানীয় অ্যাকাউন্ট এই কাজটি করার অনুমতি পায়»। এর উত্তর দিন নিজের অ্যাকাউন্ট ডেটাবেস থেকে, ক্লায়েন্ট যা পাঠিয়েছে তা থেকে নয়:
id -u alice
getent passwd alice | cut -d: -f1,3,6
stat -c '%U:%G %a %n' /home/alice/.local/state/vpn-status.json
তৃতীয় কমান্ডটিই মানুষ এড়িয়ে যায়। লক্ষ্য ফাইলটি যদি root-এর মালিকানায় থাকে কারণ আগের হুক সেটি তৈরি করেছিল, তবে সঠিকভাবে কনফিগার করা ব্যবহারকারী-কাজটি অনুমতি-ত্রুটিতে ব্যর্থ হবে, যা systemd-এর সমস্যার মতো দেখায় কিন্তু তা নয়।
ডেমন যেখানে আছে সেখানেই থাকে
VPN সেবার নিজের User= বদলে অ্যালিস করা ভুল লিভার। এটি বদলে দেয় ডেমন কীভাবে ইন্টারফেস বাঁধে, কী-গুলো পড়ে, তার স্টেটাস ফাইল লেখে ও রুট পরিচালনা করে, আর সেই সমস্ত ঝুঁকি একটি কাজ-করা ইউনিটে সরিয়ে দেয়। ডেমনের তার বিশেষাধিকার দরকার; পরবর্তী কাজটির নয়।
ইউনিটটি স্পর্শ করার আগে দেখুন এটি আসলে কী করছে। দুটি কমান্ড আপনাকে চালনার পরিচয় ও বলবৎ থাকা সঠিক কমান্ড লাইন জানায়, ওভাররাইড ফাইল যা যোগ করেছে তা সহ:
systemctl show -p User -p Group -p ExecStart openvpn-server@server
systemctl cat openvpn-server@server
ডিফল্ট প্যাকেজ ইনস্টলে ডেমনটি root এবং --up স্ক্রিপ্ট সেটিই উত্তরাধিকারসূত্রে পায়। ধরে নেওয়ার বদলে এটি নিশ্চিত করুন, কারণ কঠোর করা কোনো ডিস্ট্রিবিউশন এটিকে আলাদা অ্যাকাউন্টে সরিয়ে থাকতে পারে, আর হাতে লেখা drop-in হুকটিকে ভিন্ন নিয়মের র্যাপারের মধ্য দিয়ে চালাতে পারে।
তিনটি নামকৃত অংশ, একটি সংকীর্ণ ট্রিগার
রক্ষণাবেক্ষণে টিকে থাকা বিন্যাসে থাকে একটি ঘটনা, একটি ট্রিগার ও একটি কাজ। ডেমন জানায় একটি নামকৃত সেশন উঠেছে। ট্রিগার সেই ছোট তথ্যটি গ্রহণ করে এবং একটি নির্দিষ্ট কাজ চায়। কাজটি সেই স্থানীয় অ্যাকাউন্টের অধীনে চলে যার মালিকানায় স্পর্শ করা ফাইলগুলো আছে। শৃঙ্খলে কিছুই কোনো ইচ্ছামতো কমান্ড পথ গ্রহণ করে না।
কাজটি নিজেই একটি সাধারণ সার্ভিস ইউনিট, আর পরিচয় হলো তার ভেতরের একটি নির্দেশিকা:
[Service]
Type=oneshot
User=alice
Group=alice
ExecStart=/usr/local/bin/refresh-vpn-status --slot %i
লক্ষ্য করুন User=alice পুরো ইউনিটে প্রযোজ্য, এবং systemd একটি ব্যতিক্রম নথিভুক্ত করে যা জানা দরকার: + উপসর্গযুক্ত কমান্ড যাই হোক পূর্ণ বিশেষাধিকার নিয়ে চলে। ওই উপসর্গ একক বিশেষাধিকারভোগী ধাপের জন্য বৈধ হাতিয়ার এবং আপনি এইমাত্র যে বিচ্ছেদ তৈরি করেছেন তা বাতিল করার সুবিধাজনক উপায়, তাই সেই ইউনিটে যেকোনো +-কে পর্যালোচনায় যুক্তিসঙ্গত প্রমাণ করতে হবে এমন কিছু হিসেবে দেখুন।
ট্রিগারের ইনপুট সংক্ষিপ্ত ও অসংবেদনশীল রাখুন। সেশন শনাক্তকারী, ম্যাপ করা অ্যাকাউন্ট ও একটি টাইমস্ট্যাম্প সাধারণত যা দরকার তার সবটুকু। কখনোই সীমানা পেরিয়ে শেল-অংশ, চালনাযোগ্য ফাইলের পথ বা ক্লায়েন্টের দেওয়া পরিবেশ-ব্লক পাঠাবেন না, কারণ গ্রহণকারী পক্ষের বৈধ মান আর ইনজেক্ট করা মান আলাদা করার কোনো উপায় থাকে না।
যে পরিচয়টি সত্যিই কাজ করেছে তা যাচাই করুন
কনফিগারেশন পর্যালোচনা প্রমাণ নয়। অনুমোদিত একটি পরীক্ষামূলক সংযোগের পর নিশ্চিত করুন কোন UID ফাইলটি স্পর্শ করেছে এবং ডেমন এখনও কোন UID ব্যবহার করছে:
stat -c '%U %G %y %n' /home/alice/.local/state/vpn-status.json
ps -o user=,pid=,cmd= -p "$(pgrep -o -f 'openvpn --daemon')"
systemd-run --uid=alice --pipe /usr/local/bin/refresh-vpn-status --dry-run
প্রথম লাইনটি অ্যালিস এবং আপনার পরীক্ষার সময়সীমার ভেতরের একটি টাইমস্ট্যাম্প দেখানো উচিত। দ্বিতীয়টি তখনও root বা প্যাকেজের সার্ভিস অ্যাকাউন্ট দেখানো উচিত, যা প্রমাণ করে ডেমন নড়েনি। তৃতীয়টি প্রকৃত পুনঃসংযোগের জন্য অপেক্ষা না করে কাজটির অনুমতি পরীক্ষা করার সবচেয়ে সস্তা উপায়।
ফাইলের মালিক অ্যালিস হলেও তার গ্রুপ বা মোড যদি দুই বার চালনার মধ্যে বদলে থাকে, তবে যুক্তি-ত্রুটি নয়, UMask= বা ডিরেক্টরি অনুমতির পার্থক্য খুঁজুন। টাইমস্ট্যাম্প যদি একেবারেই না নড়ে, তবে ট্রিগার কখনোই ছোঁড়া হয়নি, এবং পরবর্তী উপকারী ধাপ হলো ক্লায়েন্ট আবার সংযুক্ত নয়, কাজের ইউনিটের জন্য journalctl -u।
সংযোগ-ঘটনা এখনও যা প্রমাণ করে না
প্রতিষ্ঠিত টানেল একটি মাত্র তথ্য। এর অর্থ এই নয় যে ডেস্কটপ সেশন খোলা, সেশন বাসে পৌঁছানো যায়, বা কাজটি যে ব্যক্তিগত সম্পদ চায় তা এখনই পাওয়া যায়। অ্যালিসের UID-র অধীনে একটি oneshot ইউনিটের তার পরিচয় আছে, তার সেশনের কিছুই নেই, তাই গ্রাফিকাল বাস দরকার এমন সবকিছুকে সমর্থিত ব্যবহারকারী-সেশন ব্যবস্থার মধ্য দিয়ে যেতে হবে এবং সে লগআউট থাকলে কী হবে তা নির্ধারণ করতে হবে।
পুনঃসংযোগও বারবার ঘটে। ট্রেনে ঘুমানো একটি ল্যাপটপ এক ঘণ্টায় ডজনখানেক সংযোগ-ঘটনা তৈরি করতে পারে, আর প্রতিবার একটি লাইন যোগ করা হুক একটি স্টেটাস ফাইলকে এমন লগে পরিণত করে যা কেউ পড়তে পারে না। কাজটিকে ইডেম্পোটেন্ট করুন, অথবা সেশন-কী করা একটি রেকর্ড প্রতিস্থাপন করতে দিন।
শেষে, ইউনিটের ভেতরেই ক্ষতির পরিধি সীমিত করুন: স্টেট ডিরেক্টরি ছাড়া শুধু-পাঠযোগ্য ফাইলসিস্টেম দৃশ্য, নতুন বিশেষাধিকার নেই এবং একটি স্পষ্ট টাইমআউট। ডেমন ও ব্যবহারকারী-কাজের মধ্যে বিচ্ছেদ নিজেই মূল্যবান, কিন্তু কাজটি আপনি অনুমোদিত একমাত্র কাজ ছাড়া আর কিছুই করতে না পারলে তা অনেক বেশি মূল্যবান।