দুটি OpenVPN সার্ভারের ক্লায়েন্টরা কি একে অপরকে পৌঁছাতে পারে?
দুটি OpenVPN সার্ভার দুটি ক্লায়েন্ট পুল তৈরি করে, একটি নেটওয়ার্ক নয়। আলাদা সাবনেট, পারস্পরিক রুট এবং স্পষ্ট ট্রাস্ট সীমানা দিয়ে তাদের মধ্যে রুট করুন।
একটি দ্বিতীয় OpenVPN সার্ভার চালু করলে ক্লায়েন্টদের সংযোগের জন্য দ্বিতীয় একটি জায়গা পাওয়া যায়, এর বেশি কিছু নয়। এটি ওই ক্লায়েন্টদের প্রথম সার্ভারের নেটওয়ার্কে রাখে না, আর client-to-client নামের অপশনটি কেবল একটি সার্ভার প্রসেসের ভিতরে ফরওয়ার্ডিং বদলায়। দুটি পুল তখনই একটি নেটওয়ার্ক হয় যখন আপনি উদ্দেশ্যমূলকভাবে তাদের মধ্যে রুট করেন, প্রতিটি দিকের জন্য একজন মালিক নিয়ে। নিচের সবকিছু ইউজারস্পেস TUN মোড এবং সেই অভ্যন্তরীণ ফরওয়ার্ডিং বন্ধ থাকার কথা ধরে নেয়, তাই সিদ্ধান্ত নেয় কার্নেল।
মিথ: একটি অ্যাকাউন্ট তালিকা, একটি নেটওয়ার্ক
প্রমাণীকরণ আর নাগাল পাওয়াকে গুলিয়ে ফেলা হয়, কারণ দুটোই সার্ভার কনফিগারেশনে থাকে। যে ব্যবহারকারী দুটি গেটওয়ের যেকোনোটিতে লগইন করতে পারেন, বাইরে থেকে তাকে দুটি দরজাওয়ালা এক সিস্টেমের ব্যবহারকারী বলে মনে হয়। ভিতরে প্রতিটি সার্ভার নিজের পুল থেকে ঠিকানা দেয় এবং কেবল নিজের টার্মিনেট করা ক্লায়েন্টদের জন্য রুট বসায়। তাই গেটওয়ে A-এর একটি ক্লায়েন্ট যখন গেটওয়ে B-এর ক্লায়েন্টের কাছে প্যাকেট পাঠায়, তখন এমন গন্তব্য চায় যা তার নিজের সার্ভার কখনো শোনেনি। প্যাকেটটি A-এর ডিফল্ট রুটে যায়, টানেল ছাড়ে, এবং এমন ফায়ারওয়ালে পৌঁছায় যাকে কখনো তা অনুমোদন করতে বলা হয়নি।
সুতরাং দ্বিতীয় সার্ভার যোগ করলে রিডান্ডেন্সি, ডিসকভারি বা ভাগ করা ব্রডকাস্ট ডোমেইন যোগ হয় না। যোগ হয় একটি রাউটেড নেটওয়ার্ক, যার একটি পরিকল্পনা দরকার, আর পরিকল্পনা শুরু হয় অ্যাড্রেসিং দিয়ে।
প্রতিটি গেটওয়েকে নিজের পুল ও ট্রানজিট ঠিকানা দিন
দুটি রেঞ্জ যা অন্য কিছুর সাথে ওভারল্যাপ করতে পারে না, আর হোস্টগুলোর মধ্যে একটি ছোট ট্রানজিট লিংক—এইটুকুই পুরো ঠিকানা পরিকল্পনা। ট্রানজিটটি আপনার নিয়ন্ত্রণাধীন একটি প্রাইভেট সেগমেন্টে রাখুন, এবং কোনো সার্ভার লিজ দেওয়ার আগেই সংখ্যাগুলো লিখে রাখুন।
| Gateway | Client pool | Transit address |
|---|---|---|
| gateway-a | 10.64.10.0/24 | 172.28.44.1/30 |
| gateway-b | 10.64.20.0/24 | 172.28.44.2/30 |
প্রোফাইল একই রাখতে দুটি সার্ভারকে একই পুল দেওয়ার প্রলোভন প্রতিরোধ করুন। কার্নেলের রুট বলতে পারে না শেয়ার করা রেঞ্জের ভিতরে কোনো ইচ্ছেমতো ঠিকানা এখন দুটি হোস্টের কোনটি মালিক, তাই রাউটিং টেবিল একটি গেটওয়ে দেখাবে আর ক্লায়েন্ট হয়তো অন্যটির সাথে যুক্ত থাকবে। ইন্টারফেসের নাম স্থানীয় রীতি, ভাগ করা অবস্থা নয়। এখানে দুটি হোস্টই টানেল ডিভাইসকে tun0 আর ট্রানজিট লিংককে transit0 বলে, যা ঠিক আছে কারণ কোনো প্যাকেট এই নাম বহন করে না।
দুই পাশেই রুটটি বসান
প্রতিটি গেটওয়ের ট্রানজিট ঠিকানা দিয়ে অন্যটির পুলের জন্য একটি রুট দরকার, আর যে কোনোটি হপ হিসেবে কাজ করতে চাইলে ফরওয়ার্ডিং চালু থাকতে হবে। আগে বর্তমান টেবিল নিশ্চিত করুন, তারপর এন্ট্রি যোগ করুন এবং পুনঃসংযোগ হুকের বদলে হোস্টের নেটওয়ার্ক ম্যানেজার দিয়ে তা টেকসই করুন।
sysctl net.ipv4.ip_forward
ip route add 10.64.20.0/24 via 172.28.44.2 dev transit0
ip route get 10.64.20.37
পুল অদলবদল করে অন্য হোস্টেও একই কাজ করুন। অসম্পর্কিত স্ক্রিপ্ট থেকে বারবার একই রুট যোগ করলেই হোস্টে কয়েকটি কপি জমে আর পরের বার কেউ টেবিল পড়লে রহস্যময় পরিবর্তন দেখে। ট্রানজিট লিংক নিজেই টানেল হলে রুটটি সেই টানেলের টপোলজির দিকে যায় এবং হপটিকে তার পুনঃসংযোগে টিকে থাকতে হবে। ত্রিশ সেকেন্ডের জন্য হারিয়ে যাওয়া ট্রানজিট ঠিকানা সঙ্গে করে পুলের মধ্যবর্তী পথটিও নিয়ে যায়, যা আবিষ্কার না করে ঘোষণা করার মতো একটি নকশা বৈশিষ্ট্য।
মালিকানা জাল না করে ক্লায়েন্ট রুট পুশ করুন
ক্লায়েন্টদের দূরবর্তী পুলের জন্য একটি রুট দরকার, নইলে তাদের নিজের অপারেটিং সিস্টেম প্যাকেটটি ডিফল্ট গেটওয়েতে পাঠায় আর টানেল তা কখনো দেখে না। সার্ভার কনফিগারেশনই তা পৌঁছে দেওয়ার স্বাভাবিক জায়গা।
push "route 10.64.20.0 255.255.255.0"
আয়না লাইনটি অন্য সার্ভারের কনফিগারেশনে রাখুন, তারপর একটি পরীক্ষামূলক ক্লায়েন্ট পুনঃসংযোগ করুন এবং তার টেবিল পড়ুন। পুশ করা রুট উপেক্ষা করা ক্লায়েন্টের নিজের অনুমোদিত কনফিগারেশন দরকার, আর যে রুট কখনো পৌঁছায় না তা অ্যাক্সেস নিয়ন্ত্রণ নয়। অন্য গেটওয়ের পুরো পুলের জন্য ক্লায়েন্টকে iroute দেবেন না। ওই নির্দেশটি একটি সংযুক্ত ক্লায়েন্টের পেছনের সাবনেটের জন্য, আর অনুপস্থিত আন্তঃগেটওয়ে রুট ঢাকতে এটি ব্যবহার করলে তৈরি হয় এমন সার্ভার যা ভাবে সে এমন ঠিকানার মালিক যেখানে পৌঁছাতে পারে না.
একটি অনুরোধ প্রমাণ করুন, অন্যটি প্রত্যাখ্যান করুন
একটি বাস্তব অপারেশন বাছুন, উদাহরণস্বরূপ 10.64.10.21-এ থাকা ক্লায়েন্ট থেকে 10.64.20.37-এর একটি সার্ভিসে HTTPS, এবং দুটি হোস্টেই ঠিক সেটিই অনুমোদন করুন। প্রতিটি ফায়ারওয়াল তার ইনবাউন্ড দিকে অনুরোধ এবং রিটার্ন দিকে ট্র্যাক করা উত্তর গ্রহণ করে; গন্তব্যের নিজের সার্ভিস নীতিকেও তা গ্রহণ করতে হবে।
iptables -A FORWARD -i tun0 -o transit0 -s 10.64.10.21 -d 10.64.20.37 -p tcp --dport 443 -j ACCEPT
iptables -A FORWARD -i transit0 -o tun0 -d 10.64.10.21 -s 10.64.20.37 -p tcp --sport 443 -m conntrack --ctstate ESTABLISHED -j ACCEPT
পারস্পরিক রুট থাকলে সোর্স NAT অপ্রয়োজনীয় এবং এখানে সক্রিয়ভাবে ক্ষতিকর: সোর্স অনুবাদ করলে লুকিয়ে যায় কোন ক্লায়েন্ট অনুরোধ করেছে এবং গন্তব্যের দিকে সোর্সভিত্তিক নীতি ব্যর্থ হয়। দেখুন, ইন্টারনেট ইগ্রেসের জন্য থাকা বিদ্যমান মাস্কারেড নিয়ম এই পথটিও ধরছে কি না। তারপর প্রত্যাখ্যান পরীক্ষা করুন। যে সার্ভিস পুল B-এর জন্য স্থানীয় থাকা উচিত তা পুল A থেকে অধরা থাকতেই হবে, আর একই গেটওয়ের ক্লায়েন্ট জোড়াও পরীক্ষা করা দরকার, কারণ আপনি এইমাত্র যে ফরওয়ার্ডিং নীতি বদলেছেন তা তাদের ক্ষেত্রেও প্রযোজ্য।
মানসিক মডেলে আরও একটি সংশোধন: ট্রানজিট লিংক ডিক্রিপ্ট করা ভিতরের প্যাকেট বহন করে, তাই এটি ব্যক্তিগত নিশ্চয়তা নয়, একটি ট্রাস্ট সীমানা। এটি যদি আপনার নিয়ন্ত্রণের বাইরের কোনো নেটওয়ার্ক অতিক্রম করে, তবে ওই হপটিকে অনুমোদিত এনক্রিপ্টেড টানেল দিয়ে সুরক্ষিত করুন এবং তার প্রকৃত টপোলজি দিয়ে রুট করুন। এন্ড-টু-এন্ড TLS এখনও অ্যাপ্লিকেশনকে নিজে থেকে প্রমাণীকরণ করে, তাই ভিতরের সার্ভিসের এটি ব্যবহার চালিয়ে যাওয়া উচিত।