OpenVPN client-connect হুক: আপনার ঠিকানা আসলে কোথায় যায়
একটি client-connect স্ক্রিপ্ট প্রিন্ট করে ঠিকানা ফেরত দিতে পারে না। দেখুন কীভাবে হুকের টেম্প ফাইল, এক্সিট স্ট্যাটাস ও টপোলজি ক্লায়েন্টের IP নির্ধারণ করে।
একটি client-connect স্ক্রিপ্ট থেকে ঠিকানা ফেরত দেওয়া দেখে মনে হয় এটি ক্লায়েন্টের IP সেট করবে। কিন্তু করে না: সার্ভারের সঙ্গে হুকের একমাত্র চ্যানেল হলো একটি অস্থায়ী ফাইল, যার পাথ স্ক্রিপ্টের শেষ আর্গুমেন্ট হিসেবে আসে, এবং ঠিকানাটি সেখানে ifconfig-push সিনট্যাক্সে লিখতে হয়। যে স্ক্রিপ্ট ঠিকানাটি প্রিন্ট করে বা কিছু না লিখেই শূন্য দিয়ে বেরিয়ে যায়, সেটি পুল থেকে পাওয়া ঠিকানা নিয়ে একটি সংযুক্ত ক্লায়েন্ট তৈরি করে, আর সার্ভার লগ একেবারে সুস্থ দেখায়।
বিভ্রান্তিটি যুক্তিসঙ্গত, কারণ আরও কয়েকটি হুক এক্সিট কোড বা পরিবেশ চলকের মাধ্যমে সত্যিই উত্তর দেয়। এই হুকের নিজস্ব চুক্তি আছে, আর চুক্তিটি শুরু হয় একটি ফাইলের নাম দিয়ে।
হুক একটি ফাইল লেখে, ফেরত মান নয়
ঘোষণাটি দুটি লাইন: কলটি অনুমোদন করতে script-security 2, তারপর client-connect /etc/openvpn/server/assign-address.sh। কোনো ক্লায়েন্ট প্রমাণীকরণ করলে সার্ভার সেই স্ক্রিপ্টটি তৈরি করা ফাইল-পাথ শেষ আর্গুমেন্ট হিসেবে যোগ করে চালায়, যা কেবল তখনই $1 হয় যখন ঘোষণাটি নিজে কোনো অতিরিক্ত আর্গুমেন্ট না দেয়। সেই ক্লায়েন্টে যা কিছু প্রয়োগ করা হয় তা ওই ফাইলে সাধারণ নির্দেশিকা হিসেবে, প্রতি লাইনে একটি করে, ঠিক যেমন কনফিগারেশনে দেখা যেত। নিজের প্যারামিটার যোগ করা কোনো র্যাপার অবস্থান সরিয়ে দেয়, আর চিরাচরিত উপসর্গ হলো এমন একটি স্ক্রিপ্ট যা --verbose-এর মতো দেখতে পাথে লিখছে।
এক্সিট স্ট্যাটাস চুক্তির অন্য অর্ধেক। শূন্য মানে গ্রহণ করো ও ফাইলটি পড়ো; অন্য যেকোনো কিছু সংযোগ প্রত্যাখ্যান করে, আর এভাবেই ম্যাপ না করা পরিচয় চুপচাপ পুলে ফিরে না গিয়ে প্রত্যাখ্যাত হয়। সফলতা ফেরত দেওয়ার আগে সম্পূর্ণ নির্দেশিকাটি লিখুন, যাতে আধা-লেখা ফাইল কখনো ক্লায়েন্টের কনফিগারেশন না হয়ে ওঠে।
দুটি নির্দেশিকা মনোযোগের যোগ্য, কারণ তারা বাকি সবকিছুর সঙ্গে মিথস্ক্রিয়া করে। ifconfig-push ঠিকানাটি নির্ধারণ করে, আর পাঠানো route ক্লায়েন্টকে জানায় টানেলের মাধ্যমে কী পৌঁছানো যায়; প্রথমটি ফেরত দিয়ে দ্বিতীয়টি ভুলে গেলে আপনি পান একটি ঠিকানা আছে কিন্তু যাওয়ার জায়গা নেই এমন ক্লায়েন্ট। ফাইলের ভেতরের ক্রম কোনো ব্যাপার নয়, কিন্তু সম্পূর্ণতা ব্যাপার। এমন কোনো প্রিফিক্সের জন্য রুট পাঠানো হুক, যেখানে কোনো পিয়ার পৌঁছাতে পারে না, তা অন্য প্রান্ত থেকে দেখা একই ভুল।
ইনপুট আসে পরিবেশ চলকের মাধ্যমে: common_name, trusted_ip, ifconfig_pool_remote_ip এবং বাকিগুলো। এদের সবাইকে সার্ভারের বাইরের স্ট্রিং হিসেবে ধরুন, কখনো শেলের টুকরো হিসেবে নয়।
ঠিকানা ম্যাপিং একটি নীতি, পাটিগণিত নয়
প্রলোভনময় একটি শর্টকাট হলো সার্টিফিকেটের নাম বিশ্লেষণ করে তার অঙ্কগুলোকে শেষ অক্টেট হিসেবে ব্যবহার করা। এটি কোনো বরাদ্দকারী নয়, এবং সাধারণভাবেই ব্যর্থ হয়: একই প্রত্যয়যুক্ত দুটি নাম সংঘর্ষ করে, 300-এ শেষ হওয়া নাম কোনো ঠিকানা নয়, আর প্রশাসকের নাম বদলানো সার্টিফিকেট নিঃশব্দে একটি ডিভাইস সরিয়ে দেয়। প্রতিটি কলে সাবনেট সদস্যতা, ব্যবহারযোগ্য হোস্ট পরিসর, সংরক্ষিত ঠিকানা ও অনন্যতা যাচাই করুন, এবং ম্যাপিংটি মানুষ পড়তে পারে এমন একটি টেবিলে রাখুন।
যে নাম নিয়ন্ত্রণ করে সে ঠিকানাও নিয়ন্ত্রণ করে, তাই এই ডিপ্লয়মেন্টে common_name আসলে কী প্রতিনিধিত্ব করে তা ঠিক করুন। username-as-common-name চালু থাকলে পরিচয় হলো লগইন, সার্টিফিকেট সাবজেক্ট নয়। সেই মান কখনো শেল মূল্যায়নে পাঠাবেন না, এবং ক্লায়েন্টকে কোনো ফাইল-পাথে প্রভাব ফেলতে দেবেন না।
রেজিস্ট্রি-সমর্থিত বরাদ্দকারীকে সমবর্তিতা সহ্য করতে হবে। ঠিকানাটি পরমাণুভাবে সংরক্ষণ করুন, ব্যর্থ লেখা সামলান যেন আধা-কনফিগার করা ক্লায়েন্ট প্রবেশ না করে, এবং প্রতিটি বরাদ্দকে তা যে সংযোগের মালিক সেই সংযোগ দিয়ে চিহ্নিত করুন, যাতে পুরোনো সেশন থেকে দেরিতে সংযোগ বিচ্ছিন্ন হয়ে নতুন সেশনের ইতিমধ্যে ধরে রাখা ঠিকানা মুক্ত করতে না পারে। একটি পুল ভাগ করা একাধিক সার্ভার ইনস্ট্যান্স এই প্রয়োজনটিকে ঐচ্ছিক নয়, আরও তীক্ষ্ণ করে।
টপোলজি ঠিক করে ifconfig-push-এর অর্থ
10.77.0.0/24-এ topology subnet দিয়ে ifconfig-push 10.77.0.20 255.255.255.0 হলো একটি ঠিকানা এবং তার নেটমাস্ক। topology net30-এর অধীনে দ্বিতীয় আর্গুমেন্ট মোটেই নেটমাস্ক নয়, বরং পিয়ার ঠিকানা, তাই সাবনেটের রূপটি net30 সার্ভারে কপি করলে আপনি এমন ক্লায়েন্ট পান যা সংযুক্ত হয় কিন্তু ট্রাফিক পার করতে পারে না। টপোলজি সচেতনভাবে বদলান, কখনোই উদাহরণকে সামঞ্জস্যপূর্ণ দেখাতে নয়। যে সার্ভার ইতিমধ্যে net30-এ চলছে তার পুরোনো অ্যাড্রেসিংয়ে জীবন্ত ক্লায়েন্ট আছে, তাই সুইচটি এক লাইনের সম্পাদনা নয়, রক্ষণাবেক্ষণ উইন্ডোসহ একটি মাইগ্রেশন।
স্থির ঠিকানাগুলোকে গতিশীল পুলের বাইরে এবং অন্য প্রতিটি স্থির বরাদ্দের বাইরে থাকতে হবে, যার মধ্যে সাধারণ client-config-dir ফাইল দিয়ে দেওয়া ঠিকানাও অন্তর্ভুক্ত। যদি দুটি প্রক্রিয়া ভিন্ন ক্লায়েন্টের জন্য একই ঠিকানা তৈরি করতে পারে, তবে তাদের একটি একসময় তা করবেই।
বিশ্বাস করার আগে চারটি কেস পরীক্ষা করুন
একই পরীক্ষাগুলো ম্যাপ করা পরিচয়, ম্যাপ না করা পরিচয়, পুনঃসংযোগ এবং অনুকরণ করা রেজিস্ট্রি ব্যর্থতার বিরুদ্ধে চালান। openvpn --config client.ovpn --verb 4 পুশ উত্তরে বরাদ্দ করা ঠিকানা দেখায়, আর সার্ভারে grep -A2 PUSH_REPLY /var/log/openvpn/openvpn.log নিশ্চিত করে আসলে কী পাঠানো হয়েছে। ম্যাপ না করা পরিচয়ের জন্য প্রত্যাশিত ফল হলো প্রত্যাখ্যাত সংযোগ, পুলের ঠিকানা নয়।
তারপর ডেমন যে ডিরেক্টরিতে ওই অস্থায়ী ফাইলগুলো লেখে তা পরীক্ষা করুন। স্ক্রিপ্টটি নিম্নমানের সার্ভিস প্রেক্ষাপটে চলে, তাই root লিখতে পারে কিন্তু ডেমন পারে না এমন পাথ প্রতিটি সংযোগকে প্রত্যাখ্যানে পরিণত করে, যেখানে অনুমতি ত্রুটি লগে কয়েক লাইন নিচে চাপা পড়ে থাকে।
বরাদ্দ মানেই অনুমোদন নয়: পিন করা ঠিকানা এখনও সার্ভারের পেছনের প্রতিটি গন্তব্যে প্রবেশাধিকার দেয় না। রাউটিং ও ফায়ারওয়াল নীতিকে তার নিজের স্তরে রাখুন, এবং আপনি এইমাত্র যে ঠিকানা স্থির করেছেন তার বিপরীতে তা যাচাই করুন।