দুটি A রেকর্ড, একটি ঠিকানা, একটি ডেমন: ব্যবহারকারী যে নামই টাইপ করুন, যে প্যাকেট আসে তা অভিন্ন, আর 1194 পোর্টে বাঁধা প্রসেসের কাছে দুটিকে আলাদা করার মতো কিছু নেই। এটি সারানোর অপেক্ষায় থাকা কোনো ভুল কনফিগারেশন নয়; এটি হলো নাম-লুকআপ যা প্রকাশ করতে পারে তার সীমা। দুটি OpenVPN ইনস্ট্যান্সের মধ্যে বাছাই করে এমন যেকোনো কিছুকে হতে হবে এমন একটি মান যা ক্লায়েন্ট সংযোগে বসায় এবং ফ্রন্টএন্ড ফিরে পড়তে পারে, আর একটি সাধারণ OpenVPN ক্লায়েন্ট এমন কোনো মান প্রকাশ্যে বসায় না। এরপর যা আসছে তা হলো এটি আপনাকে কোথায় দাঁড় করায়, এবং কোন বন্দোবস্ত সত্যিই ট্র্যাফিক ভাগ করে।

রিজলভার যা ফিরিয়ে দেয় তা দিয়ে শুরু করুন

একটি ক্লায়েন্ট vpn-a.example চায় এবং একটি ঠিকানা পায়; সেই ঠিকানা আর একটি পোর্টই তার ডায়াল করার সবকিছু। নামটি লুকআপের সময় স্থানীয়ভাবে নিঃশেষ হয়ে যায়, আর তা কখনো তারের ওপর ফিল্ড হয়ে ওঠে না, তাই অন্যপ্রান্তের শ্রোতা কোন লেবেল ব্যবহার হয়েছে তা দেখতে পারে না। vpn-a.example এবং vpn-b.example-কে একই হোস্টে নির্দেশ করুন, দুটি লুকআপই একই গন্তব্য দেবে, আর সে কারণেই ডেমন কোনো পার্থক্য নিবন্ধন না করেই দুটি সংযোগই এক ইনস্ট্যান্সে শুষে নেয়। ঠিকানা-ভিত্তিক প্রোফাইলও একই কারণে নাম-ভিত্তিক প্রোফাইলের মতোই আচরণ করে।

এটি লোভনীয় কিছু বিকল্প পথও বন্ধ করে দেয়: অতিরিক্ত উপনাম, এক সকেটে প্রতিটি নামের জন্য আলাদা সার্টিফিকেট বাছাই, বা জিজ্ঞাসিত নামের ওপর নির্ভর করা ফায়ারওয়াল নিয়ম। এদের কোনোটিই এমন তথ্যের ওপর কাজ করতে পারে না যা ক্লায়েন্ট থেকে প্রথম প্যাকেট বেরোনোর আগেই বাতিল হয়ে গেছে। যদি দুটি সার্ভার আলাদা থাকতেই হয়, বিভাজনটিকে সংযোগের সঙ্গেই যেতে হবে, অর্থাৎ একটি ঠিকানা, একটি পোর্ট, বা প্রোটোকল যে পেলোড ফিল্ড সংজ্ঞায়িত করে।

যে একমাত্র নির্বাচক গণনা করে তা প্যাকেটের ভেতরে চলে

HTTP এটি করে Host হেডারের মাধ্যমে, আর TLS করে ClientHello-তে সার্ভার নাম এক্সটেনশনের মাধ্যমে, আর এভাবেই একটি ঠিকানা একটি শ্রোতার পেছনে অনেক সাইট পরিবেশন করে। দুটিই কাজ করে কারণ তারের প্রোটোকল নির্দিষ্ট সেবার জন্য অনুরোধ বহন করে। OpenVPN সম্পর্কে প্রাসঙ্গিক সত্য হলো, মধ্যবর্তী বক্স যে স্তর পরীক্ষা করে সেখানে এই দুটি ফিল্ডের কোনোটিই নেই।

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

যেখানে প্রোটোকল বিভাজক থেমে যায়

sslh প্রকল্প যে ধরনের মাল্টিপ্লেক্সার নথিভুক্ত করে তা এক পোর্টে শোনে, প্রারম্ভিক বাইট পরীক্ষা করে, এবং সংযোগটি যে ব্যাকএন্ড চেনা প্রোটোকল বলে তার কাছে হস্তান্তর করে। একটি পোর্টকে SSH, HTTPS ও OpenVPN একসঙ্গে পরিবেশন করতে হলে এটি প্রকৃত মূল্য।

sslh প্রতিটি প্রোটোকলের জন্য আলাদা প্রোব রাখে, আর তার TLS প্রোব একটি প্রকৃত ClientHello থেকে সার্ভার নাম বা ALPN মান বের করতে পারে। নেটিভ OpenVPN চেনা TLS এক্সটেনশন পড়ার চেয়ে ভিন্ন শ্রেণিবিন্যাস, আর দুটি একসঙ্গে চলে না, কারণ যে ক্লায়েন্ট শ্রবণ সকেটে কখনো ClientHello পাঠায় না সে প্রোবকে পড়ার মতো কিছু ছাড়াই রেখে যায়। তাই OpenVPN-এর সঙ্গে মেলে এমন নিয়ম উত্তর দেয় “এটি একটি OpenVPN ক্লায়েন্ট” এবং আর এগোয় না। সেই নিয়মের পেছনে দুটি OpenVPN ব্যাকএন্ড আলাদা করা যায় না, ফ্রন্টএন্ডের বাছাইয়ের কোনো ভিত্তি থাকে না, এবং প্রতিটি সেশন একই জায়গায় গিয়ে পড়ে। মাল্টিপ্লেক্সিং একটি পোর্ট বিভিন্ন সেবার মধ্যে ভাগ করে; এটি একটি সেবার ভেতরে ভার্চুয়াল হোস্টিং করে না।

যে বন্দোবস্ত সত্যিই দুটি সার্ভার আলাদা করে

সবচেয়ে সস্তা সৎ বিভাজন হলো দ্বিতীয় একটি পাবলিক ঠিকানা, প্রতি ইনস্ট্যান্সে একটি, আর বিদ্যমান প্রোফাইল ইতিমধ্যেই যা দরকার তা বহন করে কারণ তারা ভিন্ন ঠিকানায় নির্দেশ করে। এরপর হলো একই ঠিকানায় ভিন্ন পোর্ট, যা প্রতিটি প্রোফাইলে একটি সংখ্যার বেশি কিছু খরচ করে না। TCP ও UDP আলাদা পোর্ট টেবিল রাখে, তাই 1194/tcp এবং 1194/udp অসংযুক্ত সকেট এবং প্রতিটি থেকে একটি একই হোস্টে সহাবস্থান করতে পারে; এটি নাম-রাউটিং নয়, পরিবহন বিভাজন, এবং প্রায়ই এটির সঙ্গে গুলিয়ে ফেলা হয়। দুটি বিকল্পই ফায়ারওয়াল পর্যালোচনা পেরোয়, কারণ নিয়মটি প্যাকেটে সত্যিই যা আছে তার সঙ্গে মেলে।

আপনার প্রয়োজনীয় সীমা যদি দুটি বাস্তবায়নের বদলে ব্যবহারকারী গোষ্ঠীর মধ্যে চলে, তবে ভিন্ন ক্লায়েন্ট কনফিগারেশন, নিজস্ব সার্টিফিকেট পরিচালনা এবং স্পষ্ট অ্যাক্সেস নীতি সহ একটি ইনস্ট্যান্স তা ঢাকতে পারে। এটি কিনে দেয় সার্ভারের ভেতরের নীতি, সার্ভারগুলোর মধ্যে বিচ্ছিন্নতা নয়, আর দুটি ভিন্ন প্রয়োজন। যে বিচ্ছিন্নতা আপসের মধ্যেও টিকতে হবে তার এখনও ঠিকানা বা ফায়ারওয়াল প্রান্ত দরকার।

OpenVPN-এর সামনে বসানো একটি TLS টার্মিনেটর সক্ষম ফ্রন্টএন্ডের কাছে প্রকৃত সার্ভার নাম প্রকাশ করতে পারে, কিন্তু কেবল তখনই যখন ক্লায়েন্ট দিকটিও সেই অতিরিক্ত স্তরের জন্য কনফিগার করা থাকে। বিদ্যমান প্রোফাইল একই ঠিকানায় নির্দেশ করালেই সেই আচরণ পায় না।

নির্মাণের আগে নির্বাচক প্রমাণ করুন

যে ফিল্ড ব্যাকএন্ড চিহ্নিত করবে তার নাম দিন, তারপর নিশ্চিত করুন ক্লায়েন্ট সত্যিই তা পাঠায়; উত্তর যদি ঠিকানা হয় তবে পরিকল্পনা টেকে, আর যদি তা এমন হ্যান্ডশেকের ভেতরের সার্ভার নাম হয় যা কখনো শ্রোতার কাছে পৌঁছায় না, তবে কোনো DNS কাজই তা বাঁচাতে পারবে না। তিনটি কমান্ড শ্রবণ দিকটি দ্রুত নিষ্পত্তি করে।

ss -lntup | grep -E ':443|:1194'
openssl s_client -connect vpn-a.example:443 -servername vpn-a.example </dev/null | head -n 20
journalctl -u openvpn-server@server-a -n 20 --no-pager

openssl লাইন কেবল তখনই সার্টিফিকেট দেয় যখন সেই ঠিকানায় কিছু TLS সমাপ্ত করে; নেটিভ OpenVPN শ্রোতার বিরুদ্ধে এটি আটকে যায় বা ব্যর্থ হয়, যা নিজেই বাইরের স্তর কী প্রকাশ করে তার উত্তর। journal লাইন প্রতিটি ব্যাকএন্ডে পড়লে দেখায় কোন ইনস্ট্যান্স সেশনটি গ্রহণ করেছে। ফ্রন্টএন্ড লগ যা শ্রেণিবদ্ধ হয়েছে তা লিখে রাখে, কখনো যা অভিপ্রেত ছিল তা নয়, তাই ব্যবহারকারী কোথায় পৌঁছেছে সে বিষয়ে ব্যাকএন্ডই একমাত্র কর্তৃত্ব।

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

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