স্থানীয় অ্যাপ, VPN নিয়ম: আপনার FORWARD চেইন কেন কখনো কাজ করে না
মেশিনের একটি প্রক্রিয়া OUTPUT ব্যবহার করে, FORWARD নয়। সঠিক namespace-এ hook বেছে নিন, তারপর নির্ধারণ করুন mark যথেষ্ট কি না।
আপনি FORWARD চেইনে VPN ট্রাফিকের জন্য একটি নিয়ম যোগ করেন, একই Linux বাক্স থেকে অনুরোধ চালান, আর কাউন্টার শূন্যেই থাকে। নিয়মটি সম্ভবত ঠিক আছে। প্যাকেট কখনো সেই পথে যায়নি, কারণ মেশিনেই তৈরি হওয়া অনুরোধ এটি ফরওয়ার্ড করে না। সকেট থেকে তার পর্যন্ত প্যাকেটের জীবন অনুসরণ করলে বোঝা যায় কেন এমন হয়, আর নিয়মটি বরং কোথায় রাখা উচিত।
প্যাকেট কোথায় জন্মেছে তা খুঁজুন
Netfilter-এর hook ক্রম তিনটি ক্ষেত্রে ভাগ করে, আর তাদের মধ্যে কেবল একটিতেই FORWARD থাকে:
| Origin | Path | Hook that sees it |
|---|---|---|
| Local process | OUTPUT then POSTROUTING | OUTPUT, POSTROUTING |
| Addressed to a local service | PREROUTING then INPUT | PREROUTING, INPUT |
| Received for another host | PREROUTING, FORWARD, POSTROUTING | FORWARD |
স্থানীয় অ্যাপ্লিকেশন OUTPUT পথে শুরু হয়, কারণ কার্নেল ইতিমধ্যে নির্ধারণ করেছে যে প্যাকেট এখানেই উৎপন্ন এবং এটি কখনো ফরওয়ার্ডের প্রার্থী নয়। টানেল তৈরি করলে সেই শ্রেণিবিন্যাস বদলায় না; টানেল এমন একটি ডিভাইস যার মধ্য দিয়ে প্যাকেট বের হতে পারে, স্থানীয় আউটপুটকে ট্রানজিটে পরিণত করার কোনো ধাপ নয়।
দুটি প্যাকেট, একই গল্প
টানেল চালু হলে অ্যাপের ভেতরের প্যাকেট ও এনক্রিপ্ট করা বাইরের প্যাকেট দুইটি আলাদা বস্তু। ভেতরের প্যাকেটে অ্যাপের বেছে নেওয়া গন্তব্য ও পেলোড থাকে। বাইরের প্যাকেটে পিয়ারের ঠিকানা ও পোর্টে সাইফারটেক্সট থাকে, আর প্রকৃতপক্ষে ভৌত ইন্টারফেস পার হয় এটিই।
আপনার নীতি তাদের একটিকে নিয়ে, আর ভুলটি বেছে নেওয়া একটি সাধারণ কারণ যাতে নিয়মটি কিছুই করছে না বলে মনে হয়। পিয়ারের বাইরের ঠিকানার সঙ্গে মেলা নিয়ম প্রতিটি টানেল প্যাকেটকে সমানভাবে দেখে, ভেতরের অ্যাপ কী করছে তা নির্বিশেষে। ভেতরের গন্তব্যের সঙ্গে মেলা নিয়ম আপনার দরকারের ট্রাফিক দেখে, এবং তা কেবল তখনই কাজ করবে যখন সেই প্যাকেট আপনার বসানো hook-এ পৌঁছাবে।
namespace সীমা সরিয়ে দেয়
কনটেইনার নীতিটি না বদলেই এটি কঠিন করে তোলে। অ্যাপের অনুরোধ কনটেইনারের নেটওয়ার্ক namespace-এর ভেতরে স্থানীয় আউটপুট। হোস্ট সেই ট্রাফিক একটি ভার্চুয়াল Ethernet ইন্টারফেসে পায় এবং তা ফরওয়ার্ড করতে পারে, তাই হোস্টে FORWARD নিয়ম অর্থবহ হতে পারে, যদিও অনুরোধ তৈরি করা প্রক্রিয়া হোস্টের OUTPUT চেইন কখনো স্পর্শ করেনি।
hook বেছে নেওয়ার আগে নির্ধারণ করুন নিয়মসমূহ ও টানেল আসলে কোথায় থাকে। কনটেইনারের ভেতরে টানেল, হোস্টে টানেল ও কনটেইনারকে তা দিয়ে রুট করা, এবং আলাদা namespace-এ টানেল — এই তিনটি ভিন্ন টপোলজি ও তিনটি ভিন্ন নিয়ম-স্থাপন। যে namespace ডিভাইসটির মালিক তার ভেতরের নিয়ম পড়ুন, কেবল ডিফল্টটির নয়।
প্রথমে জিজ্ঞাসা করুন mark আদৌ দরকার কি না
যদি লক্ষ্য হয় একটি গন্তব্য প্রিফিক্স টানেল দিয়ে পাঠানো, সেই প্রিফিক্সের জন্য একটি রুটই যথেষ্ট হতে পারে। আগে কার্যকর রুটগুলো দেখুন, সার্ভার যা কিছু ঠেলে দিয়েছে তা সহ: পুনঃনির্দেশিত ডিফল্ট আপনার ভাবা সংকীর্ণ নীতির চেয়ে অনেক বেশি ট্রাফিক VPN দিয়ে পাঠায়, আর যতই mark দেওয়া হোক ফলটি উদ্দেশ্যের সঙ্গে মিলবে না।
শ্রেণিবিন্যাস দরকার যখন সিদ্ধান্ত এমন কিছুতে নির্ভর করে যা রুট প্রকাশ করতে পারে না, যেমন উৎস, ব্যবহারকারী বা প্রক্রিয়া। গ্রহণ করা ট্রাফিকের জন্য PREROUTING-এ mark কাজ করে। স্থানীয় ট্রাফিকের জন্য mark এমন আউটপুট ধাপে হতে হবে যা mark বসানোর পর নতুন রুট অনুসন্ধান চালু করতে পারে। nftables-এ সেটি আউটপুট hook-এ route ধরনের চেইন; সাধারণ আউটপুট ফিল্টার চেইন মানটি বসিয়ে রুট অপরিবর্তিত রাখবে।
iptables-এ সমতুল্য জিনিস mangle OUTPUT বিন্যাসে থাকে, এবং একই শর্ত প্রযোজ্য: mark থাকার পর রাউটিং সিদ্ধান্ত আবার দেখা দরকার। তারপর একটি নীতি-নিয়মকে mark ব্যবহার করতে হবে এবং ব্যবহারযোগ্য রুট ধারণ করা টেবিলের দিকে নির্দেশ করতে হবে। conntrack mark বসানো তৃতীয়, আলাদা কাজ; এটি ফ্লোতে একটি মান জমা রাখে এবং নিজে থেকে সেই মান বর্তমান প্যাকেটে বসিয়ে রাউটিংকে পড়তে দেয় না।
অনুসন্ধান ও কাউন্টার একসঙ্গে যাচাই করুন
nft list ruleset
ip route get 198.51.100.25
ip route get 198.51.100.25 mark 0x1
ঠিকানা ও mark কেবল উদাহরণ, আর দুইটি রুট কোয়েরি দুইটি আলাদা প্রশ্নের উত্তর দেয়। দ্বিতীয়টি জিজ্ঞাসা করে প্যাকেটে সেই mark থাকলে কার্নেল কী করত; এটি প্রমাণ করে না যে আপনার নিয়মসমূহ mark বরাদ্দ করে। এটিকে প্রকল্পনা-পরীক্ষা হিসেবে ধরুন, নীতিটি কাজ করে তার প্রমাণ হিসেবে নয়।
তারপর একটি নিরীহ অনুরোধ চালান এবং একসঙ্গে দুইটি জিনিস দেখুন: আপনার বেছে নেওয়া hook-এর কাউন্টার, এবং প্যাকেট প্রকৃতপক্ষে যে নির্গমনপথ নিয়েছে। কাউন্টার বাড়লে আর প্যাকেট অন্যত্র বেরোলে, mark বা টেবিল ভুল। কোনোটিই না বাড়লে প্যাকেটটি ওই hook-এ পৌঁছায়ই না, আর পরের প্রশ্ন হলো namespace বা পথ।
শেষে, পরীক্ষাটি যন্ত্রটি যা প্রকাশ করতে পারে তার মধ্যেই সীমিত রাখুন। একটি ঠিকানার জন্য একটি রুট, ঠিকানা বদলায় এমন সেবার জন্য স্থায়ী নীতি হয়ে যায় না। আগে প্যাকেটের পরিসর ঠিক করুন, তারপর দেখুন রাউটিং ও mark নকশা পুনঃসংযোগের পরও সেই পরিসর ধরে রাখতে পারে কি না।