কেন আপনার iptables নিয়ম কখনও ব্রিজ করা VPN ট্রাফিক দেখে না
ব্রিজ করা ফ্রেম আপনার নজরে থাকা IP চেইন এড়িয়ে যেতে পারে। আরেকটি নিয়ম যোগ করার আগে নেটিভ ব্রিজ ফ্যামিলিকে পুরোনো br_netfilter-এর সাথে তুলনা করুন।
একই হোস্টে দুটি ভার্চুয়াল মেশিন একটি ব্রিজের মাধ্যমে LAN-এ পৌঁছায়, আর ip forward চেইনে বসানো একটি নিয়ম এমন একটি কাউন্টার দেখায় যা কখনও নড়ে না। ফ্রেমগুলো বাস্তব, ট্রাফিক যাচ্ছে, আর নিয়মটি সহজভাবে তার পথে নেই। Linux ব্রিজ করা ট্রাফিক প্রকাশ করার দুই উপায় তুলনা করলে এই নীরবতার ব্যাখ্যা মেলে, এবং এটিও ব্যাখ্যা করে কেন একটি পুরোনো মডিউল লোড করা যতটা সহজ মনে হয় তার চেয়ে খারাপ উত্তর।
একটি হোস্টের মধ্য দিয়ে দুই পথ
একটি প্যাকেট এই হোস্ট থেকে দুইটি খুব আলাদা উপায়ে বেরিয়ে যেতে পারে, এবং সেই পার্থক্যই ঠিক করে কোন হুকগুলো এটি দেখবে। যদি গন্তব্য একটি ভৌত পোর্টের ওপারে হয় এবং ফ্রেমটি ব্রিজের দুই পোর্টের মধ্যে সুইচ হয়, তাহলে হোস্ট একটি ইথারনেট ফ্রেম ফরওয়ার্ড করে; রাউটিং কোডকে জিজ্ঞাসা করা হয় না, এবং কোনো রাউটেড হপ ঘটে না। যদি গন্তব্য হোস্ট নিজেই হয়, বা টানেল ইন্টারফেস দিয়ে পৌঁছানো কোনো নেটওয়ার্ক হয়, তাহলে প্যাকেটটি রাউট হয় এবং IP স্তরের হুকগুলো সত্যিই প্রযোজ্য হয়। এই দ্বিখণ্ডনটি মনে রাখুন, কারণ চেইন ও ফ্যামিলি নিয়ে পরের প্রতিটি প্রশ্নই নির্ভর করে ফ্রেমটি দুই পথের কোনটি নেয় তার ওপর।
এই পার্থক্যই এমন একটি নিয়মের পেছনের পুরো গল্প যা কিছুই গণনা করে না। veth9a1 থেকে enp3s0 পর্যন্ত একটি ব্রিজ করা ফ্রেম ব্রিজ অতিক্রম করে, IP স্ট্যাক নয়, তাই একটি ip forward চেইন মেলানোর মতো কিছু দেখে না। পুরোনো উদাহরণের ইন্টারফেস নামগুলো ঠিক করে না আপনার কোন পথ আছে, তাই প্রথম ধাপ হলো রুলসেট নয়, টপোলজির দিকে তাকানো।
একটি টানেল তৃতীয় একটি কেস যোগ করে যার নাম দেওয়া উচিত। একটি TUN ডিভাইস হোস্টে IP প্যাকেট পৌঁছে দেয়, তাই সেগুলো রাউট হয় এবং সত্যিই IP চেইন অতিক্রম করে, অন্যদিকে ব্রিজে যুক্ত একটি TAP ডিভাইস ফ্রেম পৌঁছে দেয় এবং ব্রিজ করা কেসের মতো আচরণ করে। ডিভাইসের ধরনই ঠিক করে, পণ্যের নাম নয়।
ব্রিজ করা ফ্রেম দেখতে পারে এমন দুই ফ্যামিলি তুলনা করুন
Linux nftables-এর bridge ফ্যামিলির মাধ্যমে নেটিভ ব্রিজ ফিল্টারিং সমর্থন করে, এবং চলমান ফ্রেম পরীক্ষা করে ফেলে দেওয়ার জন্য এর কোনো পুরোনো মডিউল দরকার নেই। কার্নেলের নিজের ব্রিজ ডকুমেন্টেশন সরাসরি এই সুপারিশ করে, যা কোনো সার্চ ফলাফল আপনাকে মডিউল লোড করতে বলার আগে জানা দরকার।
| Observation point | What it sees | What it costs |
|---|---|---|
nftables bridge family chains | Ethernet frames forwarded between bridge ports, in both directions | Rules must be written in bridge syntax with link-layer matches |
Legacy br_netfilter plus an ip chain | Bridged IPv4 and IPv6 packets, re-exposed through IP-layer hooks | Existing host rules may begin matching traffic they never saw before |
inet chain for routed traffic | Packets the host routes, including traffic arriving from a TUN device | No visibility into purely switched frames |
iptables-এর বদলে nft কমান্ড ব্যবহার করা নিজে থেকে নিয়মটিকে সঠিক ফ্যামিলিতে বসায় না। bridge ফ্যামিলিতে ঘোষণা করা চেইন ফ্রেম দেখে; ip, ip6 বা inet-এ ঘোষণা করা চেইন দেখে না, যে বাইনারিই এটি তৈরি করুক। ফ্যামিলি হলো চেইনের বৈশিষ্ট্য, এটি টাইপ করা টুলের নয়।
পুরোনো পথটি অন্যভাবে কাজ করে এবং এজন্যই অভ্যাসবশত পক্ষ নেওয়ার বদলে তুলনা করা উচিত। br_netfilter লোড করে bridge-nf-call সেটিংস চালু করলে ব্রিজ করা IPv4 ও IPv6 ট্রাফিক আবার IP স্তরের হুকগুলোর মাধ্যমে প্রকাশ পায়, ফলে একটি সাধারণ iptables নিয়ম অবশেষে এটির সাথে মিলতে পারে। ফ্রেম বদলায় না; তারা যে হুকগুলোর মধ্য দিয়ে যায় সেই সেটটাই বদলায়, যার মানে প্রতিটি বিদ্যমান হোস্ট নিয়মের এখন নতুন শ্রোতা আছে।
নিয়ম যোগ করার আগে কার্যকর পথ পড়ুন
তিনটি কমান্ড ঠিক করে আপনি কোথায় আছেন: ব্রিজটি কীসের সাথে যুক্ত, পুরোনো মডিউল সক্রিয় কি না, এবং bridge ফ্যামিলিতে ইতিমধ্যে কোন চেইন আছে। কিছু লেখার আগেই সেগুলো চালান, কারণ উত্তরই ঠিক করে আপনি দুই ডিজাইনের কোনটি সম্প্রসারিত করছেন। এই ধাপ বাদ দেওয়াই এমনভাবে একটি সঠিক নিয়মকে এমন চেইনে ফেলায় যার মধ্য দিয়ে কিছুই যায় না।
bridge link show
lsmod | grep br_netfilter
nft list ruleset | grep -A4 "chain forward"
আউটপুট কেসগুলো পরিষ্কারভাবে আলাদা করে। ব্রিজের নিচে তালিকাভুক্ত পোর্টগুলো বলে দেয় কোন ইন্টারফেস সুইচ হচ্ছে; খালি lsmod ফলাফল মানে ব্রিজ করা ফ্রেমের IP স্তরে কোনো দৃশ্যমানতাই নেই; বিদ্যমান bridge ফ্যামিলি forward চেইন মানে নীতির মালিক ইতিমধ্যে আছেন এবং আপনার নিয়মটি নিজের নতুন চেইনে নয়, সেখানেই যায়।
তারপর সহজে ফিরে পড়া যায় এমন একটি নিয়ম যোগ করুন, একটি কাউন্টারসহ এবং ভের্ডিক্ট না বদলে, এবং একটি প্রতিনিধিত্বমূলক ফ্লো ব্রিজের মধ্য দিয়ে পাঠান। নড়াচড়া করা কাউন্টার প্রমাণ করে ফ্রেমটি নিয়মে পৌঁছেছে। এটুকুই এটি প্রমাণ করে, তাই অস্বীকৃত পথটিও এর পরে পরীক্ষা করুন, কারণ সবকিছু গ্রহণ করা নীতিও নড়াচড়া করা কাউন্টার তৈরি করে।
nft add rule bridge filter forward iifname "veth9a1" oifname "enp3s0" counter acceptকোথায় পুরোনো মডিউল আচরণ বদলায়
চালু ব্রিজে পুরোনো পথ চালু করা দৃশ্যমানতা যোগ করার নিরপেক্ষ কাজ নয়। আগে ব্রিজ করা ট্রাফিকের জন্য অগম্য নিয়মগুলো গম্য হয়ে ওঠে, এর মধ্যে অন্য ইন্টারফেসের জন্য লেখা হোস্ট নিয়মও থাকে, এবং ip forward চেইনের ডিফল্ট drop নীতি হঠাৎ এমন ফ্রেমেও প্রযোজ্য হতে পারে যা আগে অপরিবর্তিতভাবে পার হতো। যে হোস্ট সেই ব্রিজ দিয়ে পরিচালিত হয়, সেখানে ফলাফল হলো কনসোল ছাড়া লকআউট। এটি কোনো কল্পিত ব্যর্থতার মোড নয়; এটি এমন একটি মেশিনে হুকের সেট প্রশস্ত করার স্বাভাবিক পরিণতি যা আপনি সবে প্রশস্ত করা পথ দিয়েই পৌঁছান।
আরও নিরাপদ ক্রম হলো কোন ফ্যামিলি নীতির মালিক তা ঠিক করা, নিয়মগুলো সেখানেই লেখা, এবং কোনো sysctl বদলানোর আগে একটি স্বাধীন পুনরুদ্ধার পথ রাখা। যদি দুই ফ্যামিলিই নিয়ম ধরে রাখে, কোনটি কর্তৃত্বপূর্ণ তা নথিভুক্ত করুন; দুইটি ওভারল্যাপিং নীতি হলো সেভাবেই একটি প্যাকেট এক জায়গায় গ্রহণ ও অন্য জায়গায় বাতিল হওয়ার কারণ, যেখানে পড়ার মতো একটিও ফাইল নেই।
বিচ্ছিন্নতার নিজেরই এখনও পূর্ণ নকশা দরকার। একটি উৎসকে একটি গন্তব্যে অনুমতি দেওয়া কেবল প্রমাণ করে যে একটি ফ্লো কাজ করে, অথচ চাহিদা সাধারণত হলো একটি VM তার প্রতিবেশী বা হোস্টে পৌঁছাতে পারবে না। অস্বীকারের নিয়মের কাউন্টারগুলো গ্রহণের নিয়মের কাউন্টারের চেয়ে বেশি গুরুত্বপূর্ণ, কারণ গ্রহণের কাউন্টারটিই সেটি যা নড়বে বলে আপনি আগেই আশা করেছিলেন।
শেষে, হোস্ট-ইনপুট কেসটি আলাদা রাখুন। ব্রিজের নিজের IP-তে সম্বোধন করা ট্রাফিক input-এ পৌঁছায়, forward-এ নয়, এবং forward-এর একটি নিয়ম আপনি যে ফ্যামিলিই বাছুন না কেন এটি কখনও দেখবে না। তিন কেস, দুই ফ্যামিলি, এক শিক্ষা: পথই হুক ঠিক করে, আর হুকই ঠিক করে আপনার নিয়ম আদৌ আছে কি না।