OpenVPN auth-user-pass: ফাইল, stdin নাকি প্রম্পট? কীভাবে বেছে নেবেন
কনসোল প্রম্পট, ক্রেডেনশিয়াল ফাইল, স্ট্রিম ও ব্যবস্থাপনা ইন্টারফেসের মধ্যে বেছে নিন, তারপর ভুল পাসওয়ার্ডের মতো দেখানো ত্রুটিগুলো ঠিক করুন।
কোন ক্রেডেনশিয়াল উৎস ব্যবহার করবেন তা তিনটি বিষয় ঠিক করে: কনসোলে কেউ বসে আছে কি না, গোপন তথ্য ডিস্কে থাকতে পারে কি না, এবং অন্য কোনো প্রক্রিয়াকে প্রম্পটের উত্তর দিতে হবে কি না। ভুল বাছাই করলে পাসওয়ার্ড পুরোপুরি বৈধ হলেও ক্লায়েন্ট stdin সমস্যা রিপোর্ট করে, আর এতে অনেকেই কারণ ছাড়াই সার্ভারের দিকে চলে যান। আগে পথ বেছে নিন; কোন পথ সেগুলো তৈরি করেছে তা জানলেই ত্রুটির বার্তার অর্থ হয়।
যে তিনটি শর্ত এটি ঠিক করে
কনসোল প্রম্পটই একমাত্র পথ যার জন্য মানুষ দরকার, তাই systemd ইউনিট বা কনটেইনারে নিঃশব্দে ব্যর্থ হওয়া একমাত্র পথও এটিই। কেউ ক্লায়েন্ট চালু করে পাসওয়ার্ড টাইপ করলে কোনো ফাইল জড়িত থাকে না এবং সংবেদনশীল কিছু ডিস্কে যায় না। ক্লায়েন্ট বুটের সময় চালু হলে সেই প্রম্পটই ঝুলে যাওয়ায় পরিণত হয়, আর সময় শেষ হওয়া সাধারণত ক্রেডেনশিয়াল ত্রুটি হিসেবে নয়, সাধারণ সংযোগ ব্যর্থতা হিসেবে দেখা যায়।
প্রক্রিয়া তত্ত্বাবধান ছাড়া চালু হলে এবং নিয়ন্ত্রিত অনুমতির আওতায় গোপন তথ্য ডিস্কে থাকতে পারলে ক্রেডেনশিয়াল ফাইলই সঠিক উত্তর। যখন গোপন তথ্য একেবারেই লেখা যাবে না - কেবল ভল্ট নীতি, স্বল্পমেয়াদি টোকেন - তখন ক্লায়েন্ট যে স্ট্রিম খুলতে পারে তা দরকার, যার ব্যবহারিক অর্থ প্রক্রিয়া প্রতিস্থাপন বা ফাইল ডেসক্রিপ্টরে লেখা সহায়ক। ব্যবস্থাপনা ইন্টারফেস চতুর্থ ক্ষেত্রটি ঢাকে: যে নিয়ন্ত্রক ইতিমধ্যে টানেলের জীবনচক্র পরিচালনা করে এবং সকেটের মাধ্যমে প্রশ্নের উত্তর দিতে পারে।
- কনসোলে মানুষ, কোনো স্বয়ংক্রিয়তা নেই: ইন্টারঅ্যাকটিভ প্রম্পট।
- তত্ত্বাবধান ছাড়া শুরু, গোপন তথ্য সংরক্ষণ করা যায়: মোড 0600 ক্রেডেনশিয়াল ফাইল।
- তত্ত্বাবধান ছাড়া শুরু, গোপন তথ্য সংরক্ষণ করা যায় না: প্রক্রিয়া প্রতিস্থাপন বা গোপন এজেন্টের লেখা fd।
- ক্লায়েন্ট অন্য প্রক্রিয়ার মালিকানায়: ব্যবস্থাপনা ইন্টারফেস।
দুটি উত্তরই মানালে এমনটি বেছে নিন যা গোপন তথ্যকে argv ও shell ইতিহাসের বাইরে রাখে। প্রোগ্রামের আর্গুমেন্ট হিসেবে দেওয়া পাসওয়ার্ড প্রক্রিয়া তালিকার মাধ্যমে যেকোনো স্থানীয় ব্যবহারকারী পড়তে পারেন, আর সেই প্রকাশ ফেরানো কঠিন।
প্রতিটি ইনপুট পথ আসলে কী করে
--auth-user-pass একা কনসোলে ব্যবহারকারীর নাম ও পাসওয়ার্ড চায়। ফাইলের নাম দিলে ক্লায়েন্ট প্রথম লাইনকে ব্যবহারকারীর নাম এবং দ্বিতীয় লাইনকে পাসওয়ার্ড হিসেবে নেয়; উদ্ধৃতি, মন্তব্য বা কী-মান সিনট্যাক্সের কোনো সমর্থন নেই। এটাই পুরো ফরম্যাট, তাই যে কেউ INI ফাইলের আশায় এটি সম্পাদনা করে সেটি নষ্ট করে। ইনলাইন <auth-user-pass> ব্লক প্রোফাইলের ভেতরে সেই দুটি লাইনই রাখে, যা প্রোফাইলকে নিজেই গোপন তথ্য বানায় এবং ব্যক্তিগত কী-এর মতো একই পরিচালনা শ্রেণিতে রাখে।
বাকি দুটি পথ স্ট্রিম ও সকেট। OpenVPN-এর শুধু একটি পঠনযোগ্য ফাইল ডেসক্রিপ্টর দরকার, তাই এটি প্রক্রিয়া প্রতিস্থাপন, পাইপ-সমর্থিত /dev/fd এন্ট্রি বা আসলে FIFO এমন ফাইলের নাম গ্রহণ করবে। ব্যবস্থাপনা ইন্টারফেস প্রকৃতিগতভাবে আলাদা: ক্লায়েন্ট নিজে পড়ার বদলে তত্ত্বাবধায়ক প্রক্রিয়ার কাছে মানগুলো চায়। পুনঃসংযোগের সময় এই পার্থক্য গুরুত্বপূর্ণ: ক্রেডেনশিয়াল ফাইল, গোপন সহায়ক যে FIFO-তে আবার লিখতে পারে, এবং ব্যবস্থাপনা ইন্টারফেস মানুষ ছাড়াই আবার সরবরাহ করতে পারে; প্রক্রিয়া প্রতিস্থাপন পারে না, কারণ ডেসক্রিপ্টর প্রথম পঠনেই শেষ হয়ে যায়।
ফাইলটি ঠিক দুই লাইনের হতে হবে
নষ্ট ক্রেডেনশিয়াল ফাইলের বেশিরভাগই দুই ব্যর্থতার ধরনে পড়ে। Windows সম্পাদক CRLF শেষ রাখে, ক্যারেজ রিটার্ন পাসওয়ার্ডের অংশ হয়ে যায়, আর সার্ভার স্ক্রিনে সঠিক দেখানো মান প্রত্যাখ্যান করে। খালি দ্বিতীয় লাইন - যেখানে পাসওয়ার্ড থাকা উচিত সেখানে খালি লাইন - ক্লায়েন্টকে খালি পাসওয়ার্ড দিয়ে রেখে যায়, যা সার্ভার প্রত্যাখ্যান করে যদিও স্ক্রিনের মান সঠিক দেখায়। পাসওয়ার্ডের পরে অতিরিক্ত নতুন লাইন ক্ষতিকর নয়। ফাইলটি সম্পাদক নয়, shell থেকে লিখুন এবং বাইট যাচাই করুন:
install -m 600 /dev/null /etc/openvpn/client.creds
printf '%s\n%s\n' "$VPN_USER" "$VPN_PASS" > /etc/openvpn/client.creds
od -c /etc/openvpn/client.creds | head -3পথও বিষয়বস্তুর মতোই গুরুত্বপূর্ণ। আপেক্ষিক পথ প্রক্রিয়ার কার্যকারী ডিরেক্টরির সাপেক্ষে সমাধান হয়, যা কোনো পরিষেবার জন্য প্রায়ই আপনার পরীক্ষা করা ডিরেক্টরি হয় না। পরম পথ ব্যবহার করুন, ফাইলটিকে ক্লায়েন্ট চালানো অ্যাকাউন্টের মালিকানায় করুন এবং গ্রুপ ও অন্যরা যাতে পড়তে না পারে সেজন্য মোড 0600 রাখুন। OpenVPN 2.6 নির্দেশিকা নির্দেশের গৃহীত রূপগুলো তালিকাভুক্ত করে; তৃতীয়টি উদ্ভাবনের আগে সেটি দেখুন।
সার্ভারকে দোষ দেওয়ার আগে ফাইলটি পরীক্ষা করুন। openvpn --config client.ovpn --auth-user-pass /etc/openvpn/client.creds --verb 4 চালালে মুদ্রিত হয় ফাইলটি খোলা হয়েছিল কি না এবং পরে ক্রেডেনশিয়াল গৃহীত হয়েছিল কি না, যা বলে দেয় পরের ধাপে কোন স্তর বদলাতে হবে।
স্ট্রিম, stdin এবং এরা যে ত্রুটি তৈরি করে
পাসওয়ার্ড পাইপে দেওয়া বেশিরভাগ মানুষ প্রথমেই যা চেষ্টা করেন এবং এটিই সবচেয়ে বেশি বিস্ময়ের পথ। প্রক্রিয়া প্রতিস্থাপন কাজ করে কারণ ক্লায়েন্টের কেবল একটি পঠনযোগ্য ডেসক্রিপ্টর দরকার: openvpn --config client.ovpn --verb 3 --auth-user-pass <(printf '%s\n%s\n' "$VPN_USER" "$VPN_PASS")। /dev/stdin পাঠানো কেবল তখনই কাজ করে যখন ক্লায়েন্ট প্রশ্ন করার মুহূর্তে stdin এখনও খোলা ও পঠনযোগ্য থাকে, যা ইতিমধ্যে সেটি খরচ করে ফেলা পাইপলাইনে সত্য নয়।
ERROR: could not read Auth username from stdin-এর দুইটি ভিন্ন কারণ আছে। কিছু 2.3.x ক্লায়েন্টে বার্তাটি stdin পরিচালনার একটি ত্রুটি থেকে এসেছিল যা পরবর্তী 2.3 সংস্করণগুলো ঠিক করে, তাই এত পুরনো ক্লায়েন্ট কেবল আপগ্রেডেই ভালো হয়। বর্তমান ক্লায়েন্টে একই বাক্য মানে ক্লায়েন্ট কনসোল ইনপুট চেয়েছিল এবং stdin টার্মিনাল ছিল না - ঠিক সেই অবস্থা যা systemd ইউনিট, cron কাজ বা -t ছাড়া চালু করা কনটেইনারে থাকে।
auth-nocache তৃতীয় একটি লুপ যোগ করে যা নষ্ট পাসওয়ার্ডের মতো দেখায়। এটি ব্যবহারের পরে ক্রেডেনশিয়াল স্মৃতি থেকে ফেলে দেয়, তাই নেটওয়ার্ক পরিবর্তনের কারণে হওয়া পুনঃসংযোগের আবার চালানোর কিছু থাকে না এবং প্রম্পট ফিরে আসে। এটি ডিজাইন অনুযায়ী কাজ করা নির্দেশ। auth-nocache ক্লায়েন্ট স্মৃতিতে কী রাখে তা বদলায়, সার্ভার বা পরিচয় প্রদানকারী অ্যাকাউন্ট সম্পর্কে কী ভাবে তা নয়, তাই পুরো সমাধান হলো সেই ফাইলটিই আবার সরবরাহ করা, পুনরায় চালুর সময় আবার পড়া হয় - আর ব্যবস্থাপিত সংযোগের জন্য সেই সরবরাহ অনুমোদিত গোপন ভান্ডার থেকে আসা উচিত, স্ক্রিপ্টে থাকা পাসওয়ার্ড থেকে নয়।
প্রম্পট অন্য প্রক্রিয়ার মালিকানায় থাকলে ব্যবস্থাপনা ইন্টারফেস
যে নিয়ন্ত্রক ইতিমধ্যে টানেল তত্ত্বাবধান করছে সে এর প্রশ্নেরও উত্তর দিতে পারে। ক্লায়েন্ট --management 127.0.0.1 7505 দিয়ে চালু করুন, অবস্থা লাইন পড়ুন এবং >PASSWORD:Need 'Auth' username/password লক্ষ্য করুন। নিয়ন্ত্রক আলাদা কমান্ড লাইনে username "Auth" alice এবং তারপর password "Auth" ... দিয়ে উত্তর দেয়। 'Auth' টোকেন অনুরোধের শনাক্তকারী পুনরাবৃত্তি করে এবং মিলতে হবে, নইলে উত্তর উপেক্ষিত হয় এবং ক্লায়েন্ট অপেক্ষা করে।
খরচ হলো এখন আপনার মালিকানার একটি অবস্থা যন্ত্র: সংযোগের ক্রম, ক্লায়েন্ট পুনরায় চালু এবং হোস্টের অন্য ব্যবহারকারীরা যাতে না পৌঁছায় এমন স্থানীয় সকেট। আপনি কিনছেন চালনার সময়ে সরবরাহ করা ক্রেডেনশিয়াল, ডিস্কে ফাইল ছাড়া এবং ঝুলে যেতে পারে এমন প্রম্পট ছাড়া। আপনার স্ট্যাকের অন্য কিছু যদি ইতিমধ্যে এই প্রোটোকল না বলে, তবে এই পথ একটি রক্ষণাবেক্ষণযোগ্য উপাদান যোগ করে।
ক্রেডেনশিয়াল সমস্যার মতো দেখানো ব্যর্থতা
কখনো সম্পূর্ণ না হওয়া TLS হ্যান্ডশেক, বা VERIFY ERROR: depth=0, error=certificate signature failure, বিশ্বাসের সমস্যা এবং যেকোনো ব্যবহারকারীর নাম পড়ার আগেই ঘটে। UDP শ্রোতার দিকে লক্ষ্য করা proto tcp ক্লায়েন্টও একই জায়গায় ব্যর্থ হয়: প্যাকেট কখনো প্রমাণীকরণ পর্যায়ে পৌঁছায় না, তাই প্রতিটি পাসওয়ার্ড সম্পর্কের কারণে ভুল দেখায়। ক্রেডেনশিয়াল পাঠানোর আগে সার্টিফিকেট যাচাই চালু রাখুন; পরিচিত প্রম্পট পাসওয়ার্ড কে পায় সে সম্পর্কে কিছুই বলে না। ক্রেডেনশিয়াল স্পর্শ করার আগে সার্টিফিকেট চেইন, সাধারণ নাম ও পরিবহন যাচাই করুন।
প্রোফাইল জোড়া দেওয়া স্ক্রিপ্টের shell ত্রুটি আরেকটি মিথ্যা সূত্র। [ ! -f "$file" ]-এর ভেতরে অনুপস্থিত স্পেস command not found তৈরি করে, স্ক্রিপ্ট তাড়াতাড়ি থেমে যায়, প্রোফাইল আর কখনো পুনর্নির্মিত হয় না এবং ক্লায়েন্ট আগেরটি দিয়ে শুরু হয়। সেই ত্রুটি shell-এর, প্রমাণীকরণের নয়, আর পাসওয়ার্ড যতবারই আবার টাইপ করুন এটি মোছে না।
এই প্রবাহের প্রতিটি প্রম্পট এই ক্রেডেনশিয়াল নয়। ব্যক্তিগত কী-এর পাসফ্রেজ, HTTP প্রক্সি লগইন এবং পরিষেবার পাসওয়ার্ড ভিন্ন ভিন্ন পর্যায়ে চাওয়া তিনটি ভিন্ন গোপন তথ্য, আর কী পাসফ্রেজ সাধারণত auth-user-pass নয়, ক্লায়েন্ট বা এজেন্ট সামলায়। TLS সেশন দাঁড়ানোর আগে প্রম্পট দেখা দিলে আপনি ভুল প্রশ্নের উত্তর দিচ্ছেন এবং কোনো অ্যাকাউন্ট রিসেট সাহায্য করবে না। ভুল প্রম্পট বাদ দেওয়ার পরে বাকি পরীক্ষাগুলো সবচেয়ে আগের স্তর থেকে শুরু হয়:
- শেষ ক্রেডেনশিয়াল লাইন নয়, প্রথম প্রোটোকল ত্রুটি পড়ুন: TLS, তারপর প্রমাণীকরণ, তারপর push।
- নিশ্চিত করুন ফাইলটি দুই লাইনের, ক্যারেজ রিটার্ন নেই এবং পরম পথে উল্লেখ করা হয়েছে।
- নিশ্চিত করুন প্রোফাইল ও কমান্ড লাইন নির্দেশ সম্পর্কে একমত নয় এমন দ্বিমত নেই।
- "ক্রেডেনশিয়াল গৃহীত"-কে "ট্র্যাফিক প্রবাহিত" থেকে আলাদা করুন - রাউটিং ও DNS পরের স্তর।
ক্লায়েন্ট push পর্যায়ে পৌঁছালে ক্রেডেনশিয়াল দেখা বন্ধ করুন এবং সার্ভার যে রুট ও DNS সার্ভার পাঠিয়েছে তা পড়া শুরু করুন। সেটি পরের সমস্যা, এবং আপনি এইমাত্র যে পাসওয়ার্ড ঠিক করেছেন তার সঙ্গে এর কোনো সম্পর্ক নেই।