GCE-তে OpenVPN: রুট push করার আগে একটি alias IP যোগ করুন
push করা রুট VM-কে next hop করে না। alias IP পরিসর যোগ করুন, সার্ভারের pool-এর সাথে মিলিয়ে নিন এবং ক্লায়েন্ট পরীক্ষা করার আগে VPC-তে ফেরার রুট তৈরি করুন।
একটি ক্লায়েন্ট Compute Engine VM-এ OpenVPN সার্ভারে ডায়াল করে, স্ট্যাটাস উইন্ডো বলে সংযুক্ত, কিন্তু VPC-এর ভিতরের একটি হোস্টে ping এখনও কোথাও পৌঁছায় না। স্বাভাবিক প্রবৃত্তি বলে আরেকটি push লাইন যোগ করতে, এবং তাতে কখনও সমাধান হয় না। Compute Engine নিজের রুট টেবিল এবং VM-এর ইন্টারফেস প্রকৃতপক্ষে যে ঠিকানাগুলো ধরে রাখে তার ভিত্তিতে প্যাকেট কোথায় যাবে তা ঠিক করে, তাই যে tunnel pool VM-এর মালিকানায় নেই তা এমন pool যেখানে কেউ পৌঁছায় না।
কনফিগারেশন ফাইলের বদলে যে প্যাকেটটি ব্যর্থ হচ্ছে তা অনুসরণ করুন, এবং অনুপস্থিত অংশগুলো ক্রমে দেখা যাবে।
মৃত প্যাকেট থেকে শুরু করুন
SYN ক্লায়েন্ট ছেড়ে tunnel-এ ঢোকে এবং VPC-এর ভিতরের একটি গন্তব্যের জন্য encapsulated প্যাকেট হিসেবে VM-এ পৌঁছায়। OpenVPN এটি decapsulate করে eth0 দিয়ে পাঠানোর চেষ্টা করে, যেখানে fabric সবকিছুর আগে একটি প্রশ্ন করে: এই ইনস্ট্যান্স কি গন্তব্য ঠিকানার মালিক। অন্য কারও subnet থেকে কাটা tunnel pool সেই প্রশ্নে ব্যর্থ হয়, এবং কোনো রুট বা firewall নিয়ম দেখার আগেই প্যাকেটটি ফেলে দেওয়া হয়।
তাই ক্লায়েন্ট থেকে VPC-র অভিমুখে দুটি আলাদা প্রয়োজন আছে, এবং কোনোটিই push নির্দেশ নয়। VM-এর দরকার tunnel pool ঢেকে রাখে এমন alias পরিসর, আর সেটাই তাকে ওই ঠিকানাগুলোর বৈধ মালিক করে তোলে। VPC-র দরকার এমন রুট যা প্রতিটি সুরক্ষিত prefix-এর জন্য VM-কে next hop হিসেবে নাম দেয়। একটি বাদ পড়লে প্যাকেট অন্য জায়গায় মরে, অথচ ক্লায়েন্ট একই নীরবতা দেখে।
ব্যর্থতাটি ওই ক্রমে পড়ুন, কারণ ক্লায়েন্টের দিক থেকে দুটি শর্তই একই রকম দেখায়। যে tunnel সংযুক্ত বলে জানায় অথচ কিছুই উত্তর দেয় না, তা টপোলজি সমস্যার চিহ্ন, খারাপ cipher-এর নয়।
ইনস্ট্যান্স কি tunnel pool-এর মালিক
VM-কে তার নিজের subnet-এর ভিতরে একটি গৌণ পরিসর দিন, তারপর OpenVPN ঠিক ওই পরিসর থেকেই ঠিকানা বিতরণ করুক। যে ইনস্ট্যান্সের প্রাথমিক ঠিকানা 10.156.0.10/20, সেখানে /28 alias pool-কে অন্য ইনস্ট্যান্সরা ইতিমধ্যে ধরে রাখা ঠিকানা থেকে আলাদা রাখে:
gcloud compute instances network-interfaces update openvpn-vm \
--zone=europe-west1-b \
--aliases=eth0:10.156.1.0/28তারপর server নির্দেশটিকে একই ব্লক বর্ণনা করতে হবে। এর প্রথম ঠিকানা tunnel-এর gateway হয়, আর বাকি ঠিকানাগুলো ক্লায়েন্টদের দেওয়া হয়। এখানে দুটি সংখ্যা একটি ব্লক বর্ণনা করে, একটি নেটওয়ার্ক ও একটি netmask, এবং এটাই সেই pool সিনট্যাক্স যা OpenVPN এখনও আশা করে।
server 10.156.1.0 255.255.255.240নিশ্চিত করুন যে ঠিকানাটি সত্যিই ইন্টারফেসে পৌঁছেছে, শুধু OpenVPN কনফিগারেশনে নয়। fabric যা NIC রিপোর্ট করে তা পাঠায়, daemon যা বিশ্বাস করে তা নয়। একটি কমান্ডই তা ঠিক করে দেয়:
ip -4 addr show dev eth0এমন গৌণ ঠিকানা যা কখনও eth0-তে পৌঁছায় না, বা এমন pool যা অন্য subnet-এর সাথে ওভারল্যাপ করে, পরে শুরুর ত্রুটি হিসেবে নয় বরং বিরতিহীন প্যাকেট হার হিসেবে দেখা দেয়। daemon চালু হয়, ক্লায়েন্ট সংযুক্ত হয়, এবং কেবল কিছু গন্তব্য ভুল আচরণ করে। alias পরিসর ছোট রাখুন যাতে রুট টেবিলে pool সহজে চেনা যায়। অন্য ইনস্ট্যান্স ইতিমধ্যে যে subnet ব্যবহার করছে তা থেকে এটি কখনও কাটবেন না।
ফিরতি ট্রাফিককে next hop দিন
VPC-র একটি হোস্ট থেকে উত্তর tunnel pool-এর একটি ক্লায়েন্ট ঠিকানায় পাঠানো হয়, যা VPC-র জানা কোনো subnet-এর অন্তর্গত নয়। সেই pool-এর জন্য রুট না থাকলে উত্তরটি মিলহীন প্রথম hop-এ থেমে যায়, আর অনুরোধটি ওপারে সফলও হয়ে থাকতে পারে।
gcloud compute routes create openvpn-return \
--network=prod-vpc \
--destination-range=192.168.127.0/24 \
--next-hop-instance=openvpn-vm \
--next-hop-instance-zone=europe-west1-b \
--priority=800একই রুট প্রয়োজন যে কোনো prefix-এর জন্য যা VPC-র ভিতরে নয়, ক্লায়েন্টের পেছনে থাকে। সেই prefix-গুলোর জন্য ওই ক্লায়েন্টের ccd ফাইলে একটি iroute এন্ট্রিও দরকার। সেই এন্ট্রি সার্ভার পক্ষের হিসাব: এটি সার্ভারকে বলে কোন ক্লায়েন্ট prefix-এর মালিক, এবং ক্লায়েন্টের নিজের উপর কিছু ইনস্টল করে না।
push তালিকাটি কথোপকথনের ক্লায়েন্ট পক্ষের জন্য রাখুন, কারণ এটি কেবল সংযুক্ত হওয়া মেশিনে রুট যোগ করে। VPC subnet-এর জন্য একটি push লাইন এবং pool-এ ফেরার VPC রুট একই পথের দুই অর্ধেক, এবং যেকোনো একটি অর্ধেক একা এমন tunnel তৈরি করে যা অনুরোধ বহন করে কিন্তু উত্তর নয়।
Firewall, forwarding এবং মাঝের hop-গুলো
VPC-র firewall decapsulated প্যাকেট মূল্যায়ন করে, তাই ingress নিয়মকে tunnel pool এবং যে কোনো site prefix অনুমতি দিতে হবে যা ওই পথে VM-এ পৌঁছায়। default-deny মনোভাব এখানে নীরবে ব্যর্থ হয়: decapsulation-এর পরে প্যাকেট ফেলে দেওয়া হয়, আর OpenVPN লগ সুস্থ সেশন দেখায়।
যে কোনো Linux হোস্ট যা terminate না করে forward করে, সেখানে net.ipv4.ip_forward চালু আছে কি না দেখুন। মালিকানার নিয়ম সেখানেও প্রযোজ্য: যে মেশিন এমন subnet-এর জন্য forward করে যা তার নেই, সে ঠিক VM-এর মতোই প্যাকেট ফেলে দেয়। tunnel-কে দোষ দেওয়ার আগে মানটি পড়ুন।
যখন ঠিক একটি prefix ব্যর্থ হয়
আংশিক ব্যর্থতা সবচেয়ে সহজে পড়া যায়, কারণ পথের বাকি সবকিছু ইতিমধ্যে প্রমাণিত। রুট তালিকা দিয়ে শুরু করুন এবং যে এন্ট্রির ওই prefix ঢাকা উচিত তার গন্তব্য পরিসর ও next hop পড়ুন, তারপর ইনস্ট্যান্সের বিবরণ পড়ে তার alias পরিসর সার্ভার যে pool বিতরণ করে তার সাথে তুলনা করুন।
gcloud compute routes list --filter=destination-range~10.164.0.0
gcloud compute instances describe openvpn-vm --format=get(networkInterfaces[0].aliasIpRanges)অনুপস্থিত রুট prefix-এর জন্য next hop না থাকা হিসেবে দেখা যায়, আর অনুপস্থিত alias ইন্টারফেসে ফেলে দেওয়া প্যাকেট হিসেবে; ক্লায়েন্টের দিক থেকে দুটোই একই রকম দেখায় এবং ওই দুটি আউটপুটে সম্পূর্ণ আলাদা। দুটোই থাকলে বাকি সন্দেহভাজন হলো যেই ক্লায়েন্ট prefix দাবি করে তার ccd iroute।
চারটি মান tunnel-এর পাশে লিখে রাখুন: alias পরিসর, সার্ভারের pool, push করা prefix, VPC রুট। পুরোনো alias pool-এর প্রতিটি ঠিকানা ভাঙে, পুরোনো রুট এক দিক ভাঙে, অনুপস্থিত push ক্লায়েন্ট থেকে prefix লুকায়, আর ভুল iroute prefix-কে ভুল peer-এ পাঠায়। পরের যে ব্যক্তি subnet যোগ করবে তার চারটিই এক জায়গায় দরকার, আর ওই নোটটি সন্ধ্যার চেয়ে সস্তা।