एक cgroup से आने वाले ट्रैफ़िक को चिह्नित करना आसान हिस्सा है। एक भी एप्लिकेशन भौतिक इंटरफ़ेस से बाहर जाने से पहले तीन अलग निर्णय मेल खाने चाहिए, जबकि बाकी सब कुछ सुरंग में रहता है: कौन सा socket इस अपवाद का है, चिह्न कौन सी रूटिंग खोज शुरू करता है, और पैकेट निकलते समय कौन सा स्रोत पता ले जाता है। अधिकांश असफल प्रयास पहले को सही करते हैं, दूसरे को आधा करते हैं, और तीसरे की ओर कभी नहीं देखते।

तीन निर्णय, एक नहीं

वर्गीकरण बताता है किसे छूट है। रूटिंग बताती है कि चिह्नित पैकेट इसके बजाय कहाँ जाता है। स्रोत चयन बताता है कि दूर का सिरा क्या देखेगा और उत्तर कहाँ लौटना चाहिए।

ये स्वतंत्र रूप से विफल होते हैं। एक पैकेट वर्गीकृत हो सकता है, भौतिक इंटरफ़ेस पर फिर से रूट हो सकता है, और फिर भी ऐसा निजी पता ले जा सकता है जिसे कोई अपस्ट्रीम राउटर लौटा नहीं सकता, जिससे ऐसा टाइमआउट बनता है जो फ़ायरवॉल ब्लॉक जैसा दिखता है। वर्गीकरण के चरण में कुछ भी इसकी चेतावनी नहीं देता। रूटिंग के चरण में भी नहीं।

क्रम भी मायने रखता है। वर्गीकरण तब होता है जब पैकेट बनता है, रूटिंग उसके बाद होती है, और अनुवाद निकास बिंदु पर होता है।

अगर आप यह नहीं बता सकते कि तीन चरणों में से कौन टूटा है, तो आप डिबग नहीं कर रहे, नियमों को फिर से सजा रहे हैं और उम्मीद कर रहे हैं।

ऐसा cgroup मिलाएँ जो कल भी मौजूद रहेगा

nftables किसी socket की cgroup v2 सदस्यता जाँच सकता है, जो वाकई उपयोगी है क्योंकि यह प्रक्रिया का अनुसरण करता है, गंतव्य का नहीं। पेच पहचानकर्ता में है। मेनू से शुरू किया गया डेस्कटॉप एप्लिकेशन अक्सर एक क्षणिक scope में रहता है जिसका नाम अगली बार शुरू होने पर बदल जाता है।

nft list ruleset
systemctl status session.slice 2>/dev/null
cat /proc/self/cgroup

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

आप कौन सी विधि उपयोग कर रहे हैं, इस पर भी सटीक रहें। cgroup v1 net_cls वर्गीकरण और cgroup v2 socket मिलान अलग चीज़ें हैं, और दस्तावेज़ में समान नाम वाला फ़ील्ड उन्हें विनिमेय नहीं बनाता।

route प्रकार की श्रृंखला ही दूसरी खोज शुरू करती है

स्थानीय रूप से बने ट्रैफ़िक के लिए श्रृंखला का प्रकार तय करता है कि चिह्न लगाने के बाद कुछ होता है या नहीं। filter प्रकार की आउटपुट श्रृंखला पैकेट को चिह्नित कर सकती है और कर्नेल पहले से चुने गए रूट का उपयोग जारी रखेगा। route प्रकार की श्रृंखला वह विधि है जो नई खोज मांगती है।

table inet bypass {
  chain mark {
    type route hook output priority mangle; policy accept;
    socket cgroupv2 level 2 "app.slice" meta mark set 0x1 comment "app bypass"
  }
}
ip rule add fwmark 0x1 lookup 200
ip route add default via 203.0.113.1 dev wlan0 table 200

फिर चिह्न को ऐसे नीति नियम की ज़रूरत होती है जो उसे तालिका में भेजे, और वह तालिका पूरी होनी चाहिए: एक डिफ़ॉल्ट रूट, एप्लिकेशन को अभी भी ज़रूरी कोई भी स्थानीय गंतव्य, और एक अपस्ट्रीम गेटवे जो वास्तव में उत्तर दे।

चिह्न का मान जानबूझकर चुनें। WireGuard बाहरी परिवहन ट्रैफ़िक के लिए अपना fwmark उपयोग करता है, और संयोग से उसी संख्या पर पहुँचना सुरंग के अपने रूटिंग अपवाद में ऐसे हस्तक्षेप कर सकता है जिनका निदान कष्टदायक है।

स्रोत पता रूट का अनुसरण नहीं करता

जो socket पहले ही सुरंग पथ के लिए स्रोत पता चुन चुका है, वह फिर से रूट होने के बाद भी वही पता रखता है। रूटिंग परिवर्तन में कुछ भी उसे फिर से नहीं लिखता, इसलिए पैकेट भौतिक इंटरफ़ेस से ऐसे निजी स्रोत के साथ निकलता है जिसे अपस्ट्रीम नेटवर्क लौटा नहीं सकता।

दिखने वाला लक्षण ऐसा एप्लिकेशन है जो डेटा भेजता प्रतीत होता है और कभी उत्तर नहीं पाता, और एक फ़ायरवॉल लॉग जो कुछ नहीं दिखाता क्योंकि पैकेट कभी लौटा ही नहीं।

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

table inet bypass {
  chain postrouting {
    type nat hook postrouting priority srcnat; policy accept;
    meta mark 0x1 oifname "wlan0" masquerade
  }
}

केवल अपवाद का अनुवाद करें, और कुछ नहीं। एक व्यापक masquerade नियम लक्षण ठीक करता है और यह बताने की आपकी क्षमता नष्ट कर देता है कि कौन सा ट्रैफ़िक कौन सा पथ ले गया। चिह्न, वास्तविक आउटपुट इंटरफ़ेस और यदि संभव हो तो एप्लिकेशन के अपने पते पर मिलान करें। व्यापक नियम लिखना आसान है और बाद में उनका ऑडिट करना लगभग असंभव।

अभी भी अपवाद से क्या बच निकलता है

नाम विश्लेषण किसी दूसरे cgroup में अलग resolver प्रक्रिया से आ सकता है, इसलिए ब्राउज़र के socket को वर्गीकृत करने से उसकी क्वेरी वर्गीकृत नहीं होतीं। यदि resolver की क्वेरी सुरंग में रहती हैं जबकि कनेक्शन उसके बाहर जाता है, तो split-horizon उत्तर पथ से मेल नहीं खा सकते। वह असंगति ऐसी विफलताएँ पैदा करती है जो DNS बग जैसी दिखती हैं और हैं नहीं।

अधिकांश सेटअप में चाइल्ड प्रक्रियाएँ cgroup विरासत में लेती हैं, लेकिन जो helper स्वयं को अपने scope में ले जाता है वह नहीं लेता। मानने के बजाय जाँचें, विशेषकर उन चीज़ों के लिए जो स्वयं को दोबारा चलाती हैं।

अंत में तय करें कि सुरंग बंद होने पर क्या होना चाहिए। जो अपवाद चुपचाप पूर्ण बायपास बन जाता है, वह बंद होकर विफल होने वाले अपवाद से अलग सुरक्षा रुख है, और उनमें से केवल एक ही वह है जो आपका आशय था।

संबंधित लेख