নেস্টেড WireGuard: মধ্যম হপ নিজের পোর্টে উত্তর দিতে পারে না
মধ্যম হপ সবকিছু একটি টানেলে পাঠালে তার আগত পরিষেবার উত্তর ভুল পথে বেরোয়। ইন্টারফেসে সোর্স-পোর্ট নিয়ম এটি ঠিক করে।
তিনটি WireGuard হপ এমন একটি নেটওয়ার্কে পৌঁছায় যার কোনো পাবলিক ঠিকানা নেই, এরপর মাঝের মেশিনটি যে পোর্টে শোনার কথা ছিল সেখানে উত্তর দেওয়া বন্ধ করে দেয়। সামনের টানেল তখনও কাজ করে, দূরের হোস্ট তখনও সাড়া দেয়, আর শুধু মাঝের সার্ভারটাই বাইরে থেকে চুপ হয়ে গেছে। এই সংমিশ্রণটি বিভ্রান্তিকর কারণ এটি নিজেই তৈরি করা: মধ্যম হপ তার নিজের রাউটিং টেবিল মেনে চলছে, আর টেবিলটি তার উত্তরগুলোকে ভুল দিকে পাঠাচ্ছে।
এমন একটি শৃঙ্খল যা মাঝের বাক্সের সাথে কথা না বলা পর্যন্ত কাজ করে
একটি দৃষ্টান্তমূলক শৃঙ্খল নিন: ক্লায়েন্ট A UDP 500-এ সার্ভার B-তে পৌঁছায়, আর B UDP 500-এ সার্ভার C-র দিকে এগিয়ে যায়। C কেবল তার একমাত্র পিয়ার ঠিকানা থেকে ট্রাফিক গ্রহণ করে, যা এটিকে একটি লিফ করে এবং এর আচরণ সরল রাখে। B লিফ নয়, আর এই ব্যর্থতার সব আকর্ষণীয় বিষয় সেখানেই ঘটে।
পার্থক্যটি গুরুত্বপূর্ণ কারণ লিফ ও মধ্যম ভূমিকা পরস্পরবিরোধী দিকে টানে। একটি লিফ কোনো পরিণতি ছাড়াই সবকিছু একটি টানেলে পাঠাতে পারে, কারণ এর ওপর আর কিছু নির্ভর করে না। একটি মধ্যম হপ একই সাথে ক্লায়েন্টদের জন্য একটি প্রান্তবিন্দু এবং দূরের দিকের প্রতি একটি ক্লায়েন্ট, আর এই দুটি কাজ ভিন্ন রাউটিং চায়।
উত্তরটি কেন টানেল দিয়ে বেরোয়
B-তে, C-র দিকে মুখ করা ইন্টারফেসটি সংশ্লিষ্ট ডিফল্ট রুটের সাথে AllowedIPs = 0.0.0.0/0 বহন করে। তাই B-র উৎপন্ন প্রতিটি প্যাকেট সেই টানেলে যায়, যদি না আরও নির্দিষ্ট কিছু অগ্রাধিকার পায়।
A থেকে B-র ঠিকানায় পাঠানো একটি প্যাকেট আসে এবং গ্রহণ করা হয়, কারণ B-ই গন্তব্য এবং স্থানীয় ডেলিভারি আগে ঘটে। উত্তরটি স্থানীয়ভাবে তৈরি একেবারে নতুন একটি প্যাকেট যা A-র পাবলিক ঠিকানায় লক্ষ্য করা, আর সেই গন্তব্য টানেলের ভেতরের ডিফল্ট রুটের সাথে মেলে। C এটি পায়, সেই ঠিকানার মালিক নয়, এবং এটি ফেলে দেয়।
লক্ষণটি ফায়ারওয়াল সমস্যা বা কী মিলছে না এমন মনে হয়, আর এখানে দুটির কোনোটিই সত্য নয়। C-র দিকে টানেলে একটি ক্যাপচার দেখায় উত্তরগুলো ভুল দিকে যাচ্ছে। ওই একটি পর্যবেক্ষণ যেকোনো পরিমাণ কনফিগারেশন পড়ার চেয়ে বেশি সময় বাঁচায়, তাই কী বদলানো শুরু করার আগে এটি লিখে রাখুন। যে ক্যাপচারটি দেখেনি সে ধরে নেবে টানেলটাই নষ্ট।
সংকীর্ণ মেরামত: সোর্স পোর্টের সাথে মেলে এমন নীতি নিয়ম
B-র শোনা সকেট থেকে উত্তরগুলো সোর্স পোর্ট 500 নিয়ে বেরোয়। একটি নীতি নিয়ম সেটির সাথে মিলে ওই প্যাকেটগুলোকে সাধারণ টেবিলে ফিরিয়ে পাঠাতে পারে:
ip rule add sport 500 table main priority 100
ip rule add sport 8080 table main priority 101
নীতি নিয়মগুলো অগ্রাধিকার ক্রমে দেখা হয়, আর মূল টেবিলটি 32766-এ থাকে, তাই 100-এর একটি নিয়ম টানেলের ডিফল্ট রুটের আগে জিজ্ঞাসা করা হয়। বাইরে থেকে পৌঁছানোযোগ্য থাকতে হবে এমন প্রতিটি পোর্টের জন্য একটি করে এন্ট্রি যোগ করুন আর কিছু নয়, যাতে ফরোয়ার্ড করা ট্রাফিক যে টানেলের জন্য তৈরি হয়েছিল সেটিই ব্যবহার করে।
এই কৌশলের সীমা জানুন। sport নির্বাচকটি স্থানীয়ভাবে তৈরি প্যাকেটের সাথে মেলে, যা ঠিক উত্তরের ক্ষেত্রটিই ঢাকে এবং ইচ্ছাকৃতভাবে সেই ট্রাফিক ঢাকে না যা B কেবল অন্য কারও জন্য ফরোয়ার্ড করে। B-র পেছনে হোস্ট করা একটি পরিষেবার এখনও নিজের উত্তর দরকার, আর অন্যথায় ভান করলে এমন সমাধান আসে যা প্রথম পরিষেবায় কাজ করে আর দ্বিতীয়টিতে ব্যর্থ হয়।
নিয়মকে একটি মালিক দিন
প্রম্পটে টাইপ করা একটি নিয়ম পরের বার ইন্টারফেস পুনর্নির্মাণের সময় অদৃশ্য হয়ে যায়। WireGuard সেটআপে এটি সেখানে রাখুন যেখানে ইন্টারফেস তৈরি ও সরানো হয়:
PostUp = ip rule add sport 500 table main priority 100
PostDown = ip rule del sport 500 table main priority 100
যদি NetworkManager, কোনো ডিস্ট্রিবিউশন হুক বা কন্টেইনার এন্ট্রিপয়েন্ট ইন্টারফেসের মালিক হয়, তাহলে জোড়াটি হাতে সম্পাদিত ফাইলে নয়, ওই মালিকের মধ্যেই থাকা উচিত। পুনঃসংযোগের পরে কার্যকর নিয়মগুলো পরীক্ষা করুন, কেবল প্রথম শুরু করার পরেই নয়, কারণ প্রথম শুরুটি এমন ক্ষেত্র যা সবসময় কাজ করে।
বিকল্পগুলো সৎভাবে তুলনা করুন
সোর্স-পোর্ট নিয়ম চারটি পথের একটি, আর এগুলোর মধ্যে সবচেয়ে সংকীর্ণ। এর সুবিধা হলো এটি টানেল নীতিতে একেবারেই হাত দেয় না, তাই পরের পরিবর্তনগুলোতে সাধারণত টিকে থাকে। সংকীর্ণ সমাধান প্রয়োগ বন্ধ হলে জোরে ব্যর্থ হয়, আর বিস্তৃত ব্যতিক্রম তার কারণ অদৃশ্য হওয়ার অনেক পরেও চুপচাপ কাজ চালিয়ে যায়। দুই বছর পর যখন বাক্সটির মালিক অন্য কেউ, তখন এই পার্থক্যটিই মার্জিত ভাবের চেয়ে বেশি জরুরি।
| Approach | What it costs | Where it breaks |
|---|---|---|
| Source-port policy rule | One rule per exposed port | Anything B forwards rather than originates |
| Destination exception route | A route pinned to specific client addresses | Clients whose address changes |
| Stop full-tunnelling on B | Loses the catch-all path toward C | Designs that depend on it |
| Split into two tunnels | More interfaces and more policy | Nothing, at the cost of complexity |
বেছে নেওয়ার পর দুই প্রান্ত থেকেই যাচাই করুন। A থেকে B-র পোর্টে একটি সংযোগ শুরু করুন এবং কিছুক্ষণ এটি ব্যস্ত রাখুন। B-তে কার্নেলকে ip route get <address-of-A> sport 500-এর মতো কিছু দিয়ে উত্তরপথটি ন্যায্যতা দেখাতে বলুন, আর নিশ্চিত করুন এটি টানেল নয় বরং WAN ইন্টারফেসের নাম বলে। এরপর পরীক্ষা করুন C-র পেছনের কিছু এখনও শৃঙ্খল দিয়ে উত্তর দিচ্ছে, যা প্রমাণ করে ব্যতিক্রমটি বাইপাসে পরিণত না হয়ে সংকীর্ণই থেকেছে। সবশেষে পোর্টগুলো ডিজাইন নোটে লিখে রাখুন, নইলে পরের অপারেটর এটি অন্য একটি পরিষেবায় আবার আবিষ্কার করবে।