अनुरोध हमेशा एक ही वाक्य का रूप होता है: ब्राउज़िंग के लिए VPN रखें, पर SSH या कोई बैकअप कार्य सामान्य कनेक्शन का उपयोग करे. इस बारे में जो सलाह घूमती है, यानी iptables NAT नियमों से पोर्ट फ़ॉरवर्ड करना, वह यह काम नहीं करती। NAT नियम किसी फ़्लो के भीतर पते और पोर्ट फिर से लिखता है; वह कभी नहीं चुनता कि पैकेट किस इंटरफ़ेस से बाहर जाएगा। वह निर्णय राउटिंग लुकअप का है, और राउटिंग लुकअप को पोर्ट देखने के लिए मदद चाहिए।

साधारण रूट पोर्ट से क्यों नहीं मिल सकता

Linux किसी तालिका में गंतव्य पता खोजकर रूट चुनता है, पहले नीति नियमों से उम्मीदवार तालिकाओं को छानने के बाद। वे नियम फ़ायरवॉल मार्क, स्रोत पता, आने वाले इंटरफ़ेस या UID से मेल खा सकते हैं। रूट प्रविष्टि में खुद कोई पोर्ट फ़ील्ड नहीं होता, क्योंकि रूट ट्रांसपोर्ट हेडर के मायने रखने से पहले ही चुना जाता है।

आधुनिक iproute2 और कर्नेल नियम के चयनकर्ता को चौड़ा करते हैं: ipproto, sport और dport स्वीकार किए जाते हैं, इसलिए ip rule add ipproto tcp dport 22 table 100 मंशा एक ही पंक्ति में व्यक्त करता है। वास्तविक होस्ट पर ip rule add help चलाएँ और देखें कि आपका बिल्ड dport सूचीबद्ध करता है या नहीं। अगर करता है, तो एक ही कमांड में काम पूरा; अगर नहीं, तो नीचे दिया मार्क पथ बराबर है।

किसी भी तरह, नियम केवल एक संकेत है। तालिका 100 को अब भी एक रूट चाहिए, और लोग यही हिस्सा भूल जाते हैं।

तीन हिस्से, या एक

आधुनिक रूप ऊपर का अकेला नियम और वैकल्पिक तालिका में एक रूट है। क्लासिक रूप बीच में netfilter जोड़ता है: पैकेट पर मार्क लगाएँ, फिर नियम में मार्क का मिलान करें। दोनों एक ही लुकअप पर समाप्त होते हैं; फ़र्क यह है कि पोर्ट कहाँ पढ़ा जाता है।

मार्क वाला तरीका इसलिए है क्योंकि netfilter ट्रांसपोर्ट हेडर देखता है और राउटिंग कोड ऐतिहासिक रूप से नहीं देखता था। पूरी क्रियाविधि यही है, और यही समझाती है कि विकल्प एक चतुर कमांड नहीं, बल्कि तीन सहयोगी हिस्से क्यों हैं।

तीन हिस्से क्रम में

पहले, जिन फ़्लो को मोड़ना है उन पर मार्क लगाएँ, ऐसी चेन में जो रूट निर्णय से पहले मार्क मौजूद होने के लिए पर्याप्त जल्दी चले:

nft add table inet vpnexempt
nft 'add chain inet vpnexempt out { type route hook output priority mangle; }'
nft add rule inet vpnexempt out tcp dport 22 meta mark set 0x1

दूसरे, मार्क किए पैकेट एक अलग तालिका में भेजें:

ip rule add fwmark 0x1/0x1 table 100

तीसरे, उस तालिका को भौतिक लिंक से होकर डिफ़ॉल्ट रूट दें। पते उदाहरण हैं; अपने पते डालें:

ip route add default via 192.168.1.1 dev wlan0 table 100

तीसरा चरण छोड़ दें तो मार्क किया पैकेट तालिका 100 में कोई रूट नहीं पाता, इसलिए विफल हो जाता है। लक्षण ऐसा लगता है जैसे नियम ने नेटवर्क तोड़ दिया, जबकि वास्तव में उसने पैकेट के पास बचा एकमात्र रास्ता हटा दिया।

पहले पैकेट के बाद भी इसे चालू क्या रखता है

मार्क बाहर जाने वाले पैकेट पर लागू होते हैं। जवाब भौतिक इंटरफ़ेस पर उस पते के साथ आता है जो उस लिंक ने दिया, और मुख्य तालिका उस गंतव्य के लिए अब भी सुरंग को प्राथमिकता दे सकती है। दो क्रियाविधियाँ जवाब का रास्ता सुसंगत रखती हैं: लिंक पते के लिए स्रोत-आधारित नियम, और कनेक्शन ट्रैकिंग जो फ़्लो के पूरे जीवनकाल तक निर्णय सुरक्षित रखती है। मार्क को conntrack में सहेजना और जवाब पर बहाल करना स्थिति-आधारित अपवाद को स्थिर बनाने का सामान्य तरीका है।

रिवर्स-पथ फ़िल्टरिंग दूसरा ख़ामोश हत्यारा है। अगर कर्नेल वापसी पथ की सख़्त जाँच करता है और जवाब ऐसे इंटरफ़ेस पर आता है जिसे मुख्य तालिका नहीं चुनती, तो पैकेट बिना किसी संदेश के गिरा दिया जाता है। rp_filter के डिफ़ॉल्ट मान वितरण के अनुसार और इस पर निर्भर करते हैं कि इंटरफ़ेस आगे भेजा जाता है या नहीं, इसलिए बंद है ऐसा मानने के बजाय प्रभावी मान पढ़ें।

सुरंग के अपने ट्रांसपोर्ट पर मार्क न लगाएँ। WireGuard या UDP OpenVPN सुरंग TCP 22 नहीं है, इसलिए ऊपर का नुस्ख़ा सुरक्षित है, पर सुरंग गंतव्य को छोड़कर सब कुछ के रूप में लिखा अपवाद एन्क्रिप्टेड पैकेट पकड़ सकता है और सुरंग को ऐसे तोड़ सकता है जो राउटिंग लूप जैसा दिखे।

मानने के बजाय जाँचें

कर्नेल से पूछें कि वह कौन सा रास्ता लेगा, गंतव्य और पोर्ट के लिए, फिर असली स्थानांतरण चलाएँ:

ip route get 203.0.113.10
ip rule show
nft list ruleset

अगर मार्क है पर काउंटर कभी नहीं हिलते, तो नियम मेल नहीं खा रहा। काउंटर ही आपके लिखे कॉन्फ़िगरेशन और कर्नेल के लागू किए नीति के बीच का अंतर हैं।

यह गलत औज़ार कब है

पोर्ट-आधारित अपवाद स्वभाव से नाज़ुक होते हैं। सेवाएँ पोर्ट बदलती हैं, HTTP/3 UDP 443 के रूप में आता है, और एक एप्लिकेशन कई अलग-अलग तरह के फ़्लो खोल सकता है। अगर असली ज़रूरत यह है कि यह प्रोग्राम सामान्य लिंक इस्तेमाल करे, तो राउटिंग परत गलत जगह है; नेटवर्क नेमस्पेस या प्रति-एप्लिकेशन प्रॉक्सी अधिक उपयुक्त हैं।

अगर ज़रूरत यह है कि यह सबनेट सामान्य लिंक इस्तेमाल करे, तो मार्क पूरी तरह छोड़ दें और अधिक विशिष्ट रूट जोड़ें। यह आसान है, एक ही तालिका में दिखता है, और अगला व्यक्ति नियम-समूह पढ़े बिना इसका ऑडिट कर सकता है।

फ़ायरवॉल को छूने से पहले लिख लें कि तीन ज़रूरतों में से असल में कौन सी आपके पास है। ऊपर की क्रियाविधि सटीक है, और गलत परत पर लगाई सटीकता बस एक लंबा व्यवधान है।

संबंधित लेख