Linux पर किसी एक प्रोग्राम को VPN से बांधना मुख्यतः रूटिंग की समस्या है, और फ़ायरवॉल नियम केवल यह तय करता है कि मार्ग चुनने के बाद क्या होता है। अगर आप टनल के पास डिफ़ॉल्ट मार्ग होने से पहले OUTPUT में प्रोग्राम का UID मिलाते हैं, तो नियम ठीक उसी ट्रैफ़िक को गिरा देता है जिसे आप बचाना चाहते थे। यही नियम उस रिज़ॉल्वर प्रक्रिया को भी नहीं देखता जो प्रोग्राम की DNS पूछताछ का जवाब देती है। क्रम सही करें और बिना विशेषाधिकार वाला एक खाता भरोसेमंद स्प्लिट-टनल चयनकर्ता बन जाता है।

फ़ैसले से पहले खाते को मार्ग दें

मालिक-मिलान एक प्रश्न का उत्तर देता है: क्या इस UID से जुड़े स्थानीय सॉकेट ने पैकेट बनाया? यह इंटरफ़ेस नहीं चुनता और उस ट्रैफ़िक को नहीं हिला सकता जिसे मुख्य तालिका पहले से भौतिक NIC से भेज रही है। इसलिए बिना मेल खाते मार्ग वाला UID नियम प्रोग्राम को मोड़ने के बजाय अवरुद्ध करता है।

खाते को पहले उसकी अपनी तालिका से गुज़ारें, फिर फ़ायरवॉल को परिणाम की पुष्टि करने दें। यह ऐसे होस्ट पर काम करता है जिसका iproute2 uidrange समझता है, जिसकी ip rule help एक पंक्ति में रिपोर्ट करता है। तालिका 100 सुरंग से होकर डिफ़ॉल्ट मार्ग रखती है, और नियम केवल UID 1000 को उस तालिका में भेजता है। बाकी सब मुख्य तालिका पर रहता है और भौतिक कड़ी का उपयोग जारी रखता है।

ip rule add uidrange 1000-1000 table 100
ip route add default dev tun0 table 100

दूसरी सुरंग चाहने वाले दूसरे खाते को तालिका 101 और अपना नियम मिलता है, क्योंकि दो प्रोफ़ाइल एक ही तालिका में डिफ़ॉल्ट मार्ग के मालिक एक साथ नहीं हो सकते। NetworkManager प्रोफ़ाइल सिस्टम-व्यापी हैं, इसलिए यह हिस्सा हाथ से ही रहता है, और रीबूट पर नियम मिट जाते हैं जब तक कोई उन्हें बहाल न करे। तालिकाओं को सुरंग परिभाषा के बगल में बूट स्क्रिप्ट में लिखें, ताकि फिर से जुड़ना किसी खाते को गलत रास्ते पर न छोड़े।

loopback अपवाद सुरंग को क्यों खत्म करता है

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

जब OUTPUT चलता है, कर्नेल पहले ही निकास इंटरफ़ेस चुन चुका होता है, इसलिए -o पैकेट हेडर के बजाय मार्ग के उत्तर से तुलना की जाती है। मालिक-मिलान केवल OUTPUT और POSTROUTING में देखा जाता है, और अग्रेषित पैकेटों में वह पढ़ सके ऐसा कोई सॉकेट नहीं होता। इस संयोजन का अर्थ है कि अपवाद को सुरंग इंटरफ़ेस का नाम देना होगा और उस मिलान को नकारना होगा, loopback को नकारने के बजाय।

loopback अभी भी DROP के ऊपर अपना ACCEPT हकदार है, क्योंकि प्रोग्राम का पहला DNS पैकेट lo से होकर स्थानीय स्टब तक जाता है। दोनों नियमों को इस क्रम में रखें, और खाता स्टब तक पहुँचता है, फिर सुरंग तक, और कहीं और नहीं।

iptables -I OUTPUT 1 -o lo -m owner --uid-owner vpnapp -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner vpnapp ! -o tun0 -j DROP

IPv6 अलग नियम-समुच्चय है, और केवल v4 के लिए बना जोड़ा ip6tables को अछूता छोड़ देता है। AAAA रिकॉर्ड पसंद करने वाला प्रोग्राम तब DROP तक कभी पहुँचे बिना भौतिक कड़ी से बाहर चला जाएगा। दोनों नियमों को ip6tables में दोहराएँ, या होस्ट पर IPv6 बंद करें जब सुरंग कोई v6 पता न ले जाए। हाथ से जोड़े गए नियम भी रीबूट पर मिट जाते हैं, इसलिए उन्हें netfilter-persistent save से सहेजें या उसी तर्क को बूट इकाई द्वारा लोड होने वाली nftables तालिका के रूप में फिर से बनाएँ।

DNS उत्तर दूसरी प्रक्रिया से आते हैं

प्रोग्राम का 127.0.0.53 पर पूछताछ loopback ACCEPT से गुज़रता है, और वहीं UID मिलान रुक जाता है। स्टब रिज़ॉल्वर अपने सेवा खाते से ऊपर की ओर अग्रेषित करता है, इसलिए vpnapp से जुड़ा नियम दूसरी पूछताछ कभी नहीं देखता। अगर रिज़ॉल्वर कड़ी के लिए LAN सर्वर चुनता है, तो उत्तर भौतिक NIC से वापस आते हैं जबकि प्रोग्राम के अपने पैकेट सुरंग में रहते हैं। दिखने वाला परिणाम टूटे नामों वाली काम करती सुरंग है, या ऐसे नाम जिनका जवाब आपने न चुना हो ऐसा सर्वर देता है।

नाम-समाधान सुरंग कड़ी पर ठीक करें, ऐप पर नहीं। सुरंग प्रोफ़ाइल को DNS सर्वर और रूटिंग डोमेन दें, फिर resolvectl query और resolvectl status tun0 से पुष्टि करें कि रिज़ॉल्वर इसे उन नामों के लिए उपयोग करता है जो मायने रखते हैं। नेटवर्क नामस्थान के भीतर समस्या गायब हो जाती है, क्योंकि नामस्थान का रिज़ॉल्वर केवल सुरंग जानता है।

खाते से ही नियम जाँचें

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

ip route get 1.1.1.1 uid 1000
sudo -u vpnapp curl -s https://ifconfig.co

काउंटर दिखाते हैं कि नियम कभी चला या नहीं। चलाएँ iptables -vnL OUTPUT, हर नियम के बगल में पैकेट-गिनती पढ़ें, और असली ट्रैफ़िक के बाद DROP के बगल में शून्य को मिलान की गलती मानें।

अग्रेषित ट्रैफ़िक इस डिज़ाइन से बाहर है। पुल के पीछे का कंटेनर या VM vpnapp के स्वामित्व वाला स्थानीय सॉकेट नहीं रखता, इसलिए मालिक-मिलान कभी नहीं चलता और वे पैकेट FORWARD नीति का पालन करते हैं। अगर उस कार्यभार को कवर करना हो, तो उसे अलग से जाँचें और पुल या कंटेनर-पते से जुड़ी नीति लिखें। डिज़ाइन तब टिकता है जब तालिका, इंटरफ़ेस अपवाद, रिज़ॉल्वर और v6 नियम सभी एक ही दिशा में इशारा करें; इनमें से कोई एक छोड़ दें और खाता या तो लीक होता है या कनेक्टिविटी खो देता है।

संबंधित लेख