FreeBind বনাম After=: systemd সকেটকে VPN ঠিকানায় বাঁধা
VPN ঠিকানা তৈরির আগেই FreeBind systemd-কে লিসেনারের মালিক হতে দেয়; After= শুধু কাজগুলো সাজায়। দুটো তুলনা করুন, তারপর ক্রম ও প্রস্তুতি পরীক্ষা করুন।
বুটের সময় নির্দিষ্ট VPN ঠিকানায় বাঁধা একটি সকেট ইউনিট টানেল ঠিকানাটি দেওয়ার আগেই ব্যর্থ হতে পারে, আর তার পেছনের সার্ভিস কখনোই চালু হয় না। দুটি সুইচ সমাধানের মতো দেখায় এবং সমস্যার আলাদা আলাদা অর্ধেক সমাধান করে। FreeBind systemd-কে ঠিকানা অনুপস্থিত থাকা অবস্থাতেই লিসেনার তৈরি করতে দেয়। After= শুধু কাজগুলো সাজায়, তাই এটি কখন জিনিস চালু হয় তা বদলায়, কিন্তু ঠিকানা আগে আসতে সাহায্য করে না।
দুটি আলাদা সমস্যা, দুটি আলাদা সুইচ
প্রথম সমস্যা বাঁধার ব্যর্থতা: হোস্ট যে ঠিকানার মালিক নয় সেখানে শোনার অনুমতি কার্নেল দেয় না, তাই সকেট ইউনিট তৎক্ষণাৎ ব্যর্থ হয় এবং সার্ভিস কখনো সক্রিয় হয় না। দ্বিতীয় সমস্যা প্রস্তুতির ব্যর্থতা: ঠিকানা শেষে বিদ্যমান থাকে, কিন্তু টানেল ট্রাফিক বহনের আগেই কিছু তা ব্যবহার করতে চায়। FreeBind প্রথমটি সমাধান করে, দ্বিতীয়টির জন্য কিছুই করে না। ক্রম-নির্দেশনা কোনোটিই সরাসরি সমাধান করে না, কারণ তারা শুধু ঠিক করে কোনটি কোন ক্রমে চালু হবে। আপনার যে ব্যর্থতা সত্যিই আছে তার নাম দেওয়াই পুরো সিদ্ধান্ত।
সার্ভিসের বর্ণনা থেকে নয়, জার্নাল থেকে নিশ্চিত করুন কোনটি আপনার আছে। বাঁধার ব্যর্থতা একটি ঠিকানা নাম বলে এবং জানায় যে তা দেওয়া যায় না। প্রস্তুতির ব্যর্থতা সাধারণত পরে দেখা যায়, টাইমআউট বা অপর প্রান্ত থেকে দেখা প্রত্যাখ্যাত সংযোগ হিসেবে, লগে তখন সম্পূর্ণ সুস্থ সকেট ইউনিট থাকে।
FreeBind: ঠিকানার আগেই লিসেনার
FreeBind কার্নেলকে অস্থানীয় ঠিকানায় বাঁধার অনুমতি দেয়, তাই systemd বুটের সময় শোনা সকেট তৈরি করে অ্যাপ্লিকেশন চালু হলে তা তাকে দিতে পারে। সকেট অ্যাক্টিভেশনের উদ্দেশ্য এটাই, আর এজন্যই সকেট তার পেছনের সার্ভিসের চেয়ে বেশি দিন টিকতে পারে।
[Socket]
ListenStream=
ListenStream=10.8.0.1:8443
FreeBind=yes
খালি অ্যাসাইনমেন্ট নতুন এন্ট্রি যোগ করার আগে ভেন্ডর ইউনিট থেকে উত্তরাধিকারসূত্রে পাওয়া শোনার এন্ট্রিগুলো মুছে দেয়, যা প্রতিটি ইন্টারফেসে উত্তর দেওয়া অবশিষ্ট wildcard লিসেনার প্রতিরোধ করে। ঠিকানা ও পোর্ট নিজের দিয়ে বদলান এবং শুধু drop-in ফাইল নয়, কার্যকর ইউনিট যাচাই করুন। প্যাকেজ ফাইল সরাসরি সম্পাদনার বদলে ইউনিটের নামে drop-in ব্যবহার করুন, কারণ পরবর্তী প্যাকেজ হালনাগাদ সম্পাদনাটি মুছে দেবে এবং উদ্দেশ্যের কোনো চিহ্ন রাখবে না। তারপর সকেট ইউনিট যে রিলোড ও রিস্টার্ট পদ্ধতি আশা করে তা দিয়ে প্রয়োগ করুন।
systemd সকেট রেফারেন্স এই অপশনের পেছনের IPv4 ও IPv6 আচরণ নথিভুক্ত করে, আর গুরুত্বপূর্ণ বিবরণ হলো এটি রাউটিংয়ের নয়, বাঁধার ক্ষেত্রে প্রযোজ্য। এতে কিছুই ঠিকানা দেয় না বা VPN চালু করে না। FreeBind লিসেনারকে দেওয়া একটি অনুমতি, ইন্টারফেসের বিকল্প নয়।
After= ও Wants=: ক্রম মানেই প্রস্তুতি নয়
ক্রম ও প্রয়োজন আলাদা অক্ষ, আর এদের গুলিয়ে ফেললে এমন ইউনিট তৈরি হয় যা সঠিক ক্রমে চালু হয়েও ব্যর্থ হয়। After=vpn-client.service শুধু বোঝায় যে দুটি কাজই চালু হলে এটি অন্যটির চালু হওয়ার জন্য অপেক্ষা করে। এটি VPN টেনে আনে না, আর VPN সংযোগ শেষ হওয়ার অপেক্ষাও করে না।
Wants= ও Requires=-এর মতো প্রয়োজন-নির্দেশনা সক্রিয়করণ সামলায়, আর নির্ভরতা ব্যর্থ হলে কী হয় তাতে তারা আলাদা: একটি চলতে থাকে, অন্যটি থেমে যায়। কোনোটিই জানে না সংযুক্ত টানেল মানে কী। একটি VPN প্রক্রিয়া ঠিকানা না পেয়েও সক্রিয় থাকতে পারে, বা ঠিকানা পেয়ে প্রতিপক্ষের কাছে রুট ছাড়াই, আর দুটি অবস্থাই নির্ভরতা মেটায়। অ্যাপ্লিকেশনের যদি ঠিকানার অস্তিত্ব দরকার হয়, প্রক্রিয়া চালু হওয়াকে প্রস্তুতির প্রমাণ ধরে না নিয়ে সেই শর্তটি স্পষ্টভাবে মডেল করুন।
systemctl cat ও systemctl show -p After -p Wants -p Requires দিয়ে ইউনিট আসলে কী ঘোষণা করে তা দেখুন। তিনটি আলাদা ডিরেক্টরির drop-in এমন নির্দেশনা যোগ করতে পারে যা আপনি কখনো লেখেননি, আর systemd শুধু কার্যকর ইউনিটই পড়ে।
network-online.target যা করে না
network-online.target-এর পরে সাজানো ইউনিট নেটওয়ার্ক ম্যানেজার নেটওয়ার্ককে ব্যবহারযোগ্য ঘোষণা করার জন্য অপেক্ষা করে, যা বুটের একটি সমন্বয় বিন্দু, ধারাবাহিক শর্ত নয়। নির্দিষ্ট কোনো টানেল চালু আছে কি না তা এটি বলে না, আর দুপুরের পর VPN আবার সংযুক্ত হলে এটি আবার চালু হবে না। এটিকে পুনঃসংযোগ মনিটর ভাবাই ওই টার্গেটের সবচেয়ে সাধারণ ভুল পাঠ।
systemd প্রকল্প এই পার্থক্য সরাসরি নথিভুক্ত করে, আর ব্যবহারিক ফল হলো টানেল ঠিকানা দরকার হলে সেই নির্ভরতা নিজেকেই ধরে রাখতে হবে। যে ইউনিট network-online-এর জন্য অপেক্ষা করে তারপর টানেল ঠিকানা বাঁধে, তা কেবল তখনই সঠিক যখন টানেল কাকতালীয়ভাবে আগে ওঠে, আর সেটি নকশা নয়, কাকতাল।
আপনি যে জীবনচক্র বেছেছেন তা পরীক্ষা করুন
পরিষ্কার বুট, ঠিকানা আসার পরের অনুরোধ, এবং VPN পড়ে গিয়ে ফিরে আসার পরের আচরণ পরীক্ষা করুন। এই তিনটি ক্ষেত্রেই কাজ করা লিসেনারকে কাজ করা সার্ভিস থেকে আলাদা করে।
systemd-analyze verify myapp.socket
systemctl cat myapp.socket
ss -ltn "sport = :8443"
প্রথম কমান্ড রিবুটের আগে ইউনিট-ফাইলের ত্রুটি ধরে, দ্বিতীয়টি একত্রিত ইউনিট দেখায়, আর তৃতীয়টি প্রমাণ করে লিসেনার আছে কি না এবং কোন ঠিকানায়। যেখানে টানেল ঠিকানা আশা করেছিলেন সেখানে wildcard ঠিকানায় লিসেনার থাকাই সেই অবশিষ্টাংশ যা খালি ListenStream সরানোর কথা ছিল। VPN পুনঃসংযোগের পর তৃতীয় কমান্ডটি আবার চালিয়ে দেখুন ঠিকানা সরে গেছে কি না।
জীবনচক্রটি সচেতনভাবে বেছে নিন: হয় স্থিতিশীল ঠিকানা ফিরে আসার অপেক্ষায় থাকা মুক্তভাবে বাঁধা লিসেনার, নয়তো টানেলের সঙ্গে থেমে যাওয়া এবং পুনরুদ্ধারে আবার চালু হওয়া সার্ভিস। এগুলো আলাদা নকশা এবং আলাদাভাবে ব্যর্থ হয়। তারপর অ্যাক্সেস নীতি আপনার উদ্দিষ্ট উৎস ও পথের সঙ্গে বাঁধা রাখুন, কারণ গন্তব্য ঠিকানা বাঁধার জন্য প্রয়োজন হয় না যে গৃহীত প্যাকেট বিশ্বস্ত ইন্টারফেস দিয়ে এসেছে।