mitmproxy, DevTools, Gradle: VPN के पीछे तीन परतें
loopback कभी सुरंग में नहीं जाता। लक्षण को श्रोता, ट्रस्ट स्टोर या पैकेट फ़िल्टर के रूप में वर्गीकृत करें और जो परत वास्तव में विफल हुई उसकी मरम्मत करें।
VPN जुड़ता है, और तीन असंबंधित औज़ार तीन अलग तरह से विफल होते हैं उसी दोपहर। mitmproxy अनुरोध देखना बंद कर देता है, Chrome डीबगर को अस्वीकार करता है, और Gradle BindException स्थानीय सॉकेट बाइंड करते समय फेंकता है। साझा शंका यह है कि सुरंग localhost को अवरुद्ध करती है। यह ऐसा नहीं कर सकती: 127.0.0.1 कर्नेल के अंदर संभाला जाता है और कभी अडैप्टर तक नहीं पहुँचता, गेटवे की तो बात ही छोड़िए।
तीन परतें, तीन अलग खराबियाँ
क्लाइंट के साथ जो बदला वह loopback का रास्ता नहीं है। वे स्थानीय प्रॉक्सी, मशीन का ट्रस्ट स्टोर और पैकेट फ़िल्टर हैं, और हर एक डेवलपर के कार्यप्रवाह का अलग हिस्सा तोड़ता है। लक्षण को सही पंक्ति में रखना ही निदान का बड़ा हिस्सा है:
| Symptom | Layer | First check |
|---|---|---|
| Proxy sees no traffic | Local proxy or listener | ss -lntp, or netstat -ano on Windows |
| TLS error in one tool only | Trust store | Which CA bundle does that runtime read? |
| Local bind or connect refused | Packet filter or port owner | Who holds the port, and what rule drops it? |
इस तरह की लगभग हर रिपोर्ट आखिरी पंक्ति से शुरू होकर ऊपर जाती है, जो उल्टा है। सुरंग ही एकमात्र परत है जो सिद्ध रूप से loopback ट्रैफ़िक नहीं देख सकती, इसलिए उसे सबसे कम शंका मिलनी चाहिए। इससे शुरू करें कि प्रक्रिया ने क्या बाइंड किया, फिर पूछें कि वह किन प्रमाणपत्रों पर भरोसा करती है, और उसके बाद ही मशीन पर नीति देखें।
सुरंग से नहीं, श्रोता से शुरू करें
जब 127.0.0.1:8080 पर कोई प्रॉक्सी ट्रैफ़िक लेना बंद कर दे, तो तीन में से एक बात हुई है: वह कभी शुरू ही नहीं हुआ, उसने दूसरा पोर्ट बाइंड किया, या फ़िल्टर ने loopback कनेक्शन गिरा दिया। सुनने वाले सॉकेट की सूची एक ही कमांड में इसका उत्तर देती है, और यह भी दिखाती है कि कौन-सी प्रक्रिया पोर्ट की मालिक है जब दो औज़ार इस पर असहमत हों कि पहले कौन था।
रूट लुकअप में स्थानीय पता दूसरी दिशा से यही बात पुष्ट करता है। ip route get loopback गंतव्य की ओर यह loopback डिवाइस की रिपोर्ट करता है, सुरंग की कभी नहीं, और जब कोई समाधान के तौर पर रूटिंग बदलाव सुझाए तो यह एक उपयोगी वाक्य है।
प्रॉक्सी परत: परिवेश कॉन्फ़िगरेशन नहीं है
कई कॉर्पोरेट क्लाइंट HTTP प्रॉक्सी चलाते हैं और अपेक्षा करते हैं कि एप्लिकेशन उसका उपयोग करें। सेट करना HTTPS_PROXY शेल में उन कमांड-लाइन औज़ारों को ठीक करता है जो उसका सम्मान करते हैं, और ऐसे औज़ार के लिए कुछ नहीं करता जो अपनी सेटिंग्स फ़ाइल पढ़ता है। Gradle, Selenium और gRPC में से हर एक अपना कॉन्फ़िगरेशन देखता है, और एक टर्मिनल में निर्यात की गई प्रॉक्सी IDE द्वारा शुरू किए गए डेमॉन के लिए अदृश्य है।
कंटेनर औज़ार आमतौर पर वह जगह हैं जहाँ यह दिखाई देता है। कंटेनर का loopback उसका अपना होता है, इसलिए 127.0.0.1 कंटेनर के अंदर कभी भी मेज़बान की प्रॉक्सी नहीं होती; मेज़बान का पता या मेज़बान-नेटवर्क सेटिंग ज़रूरी है। जो समाधान शेल में काम करता है और बिल्ड में विफल होता है वह आमतौर पर यही पंक्ति है, सुरंग नहीं।
ट्रस्ट परत: औज़ार दूसरा स्टोर पढ़ता है
इंटरसेप्शन दूसरा बदलाव है, और यह सबसे भ्रामक त्रुटियाँ पैदा करता है। क्लाइंट निरीक्षित कनेक्शनों के लिए अपना प्रमाणपत्र प्रस्तुत करता है, इसलिए जो ब्राउज़र कॉर्पोरेट रूट पर भरोसा करता है वह सफल होता है जबकि बंडल किए गए CA स्टोर वाला औज़ार विफल होता है। certifi के ज़रिए Python requests उत्कृष्ट उदाहरण है: ऑपरेटिंग सिस्टम का स्टोर सही हो सकता है और अनुरोध फिर भी विफल हो सकता है, क्योंकि वह रनटाइम उसे कभी नहीं पढ़ता। त्रुटि पाठ में इंटरसेप्शन का ज़िक्र विरले ही होता है, इसलिए इस पंक्ति का गलत निदान टूटे एंडपॉइंट के रूप में किया जाता है।
एंडपॉइंट वास्तव में क्या प्रस्तुत करता है और औज़ार ने क्या सत्यापित किया, इसकी तुलना करें। openssl s_client सर्वर द्वारा भेजी गई श्रृंखला दिखाता है; औज़ार का अपना सत्यापन आउटपुट दिखाता है कि उसने क्या तय किया। जब वे मेल नहीं खाते, REQUESTS_CA_BUNDLE या SSL_CERT_FILE उस रनटाइम के लिए लीवर है, और कॉर्पोरेट रूट उस स्टोर में होना चाहिए जिसे वह रनटाइम पढ़ता है, न कि ऐसी वैश्विक जगह में जिसे केवल कुछ औज़ार सम्मान करते हैं।
SSL त्रुटि ठीक करने वाला संस्करण बदलाव ट्रस्ट और सिफ़र नीति का सबूत है, VPN का नहीं। SOAP क्लाइंट को चलाने वाले Python डाउनग्रेड ने बंडल किया गया CA स्टोर और डिफ़ॉल्ट TLS सेटिंग्स बदल दीं; नेटवर्क पथ नहीं हिला।
फ़िल्टर परत: यह loopback भी गिरा सकती है
तीसरा बदलाव पैकेट फ़िल्टर है, और कुछ उत्पाद ऐसे नियम स्थापित करते हैं जो उस ट्रैफ़िक को गिराते हैं जो सुरंग में नहीं आता। स्थानीय श्रोता भी शामिल हो सकते हैं। यह काम करते सॉकेट को अस्वीकृत या समय-समाप्त कनेक्शन बना देता है, और परिणामी त्रुटि मशीन पर नीति के बजाय एप्लिकेशन में बग जैसी दिखती है।
पोर्ट का स्वामित्व इस परत का दूसरा आधा हिस्सा है। BindException का अर्थ है कि सॉकेट खोला नहीं जा सका, जो कनेक्शन अस्वीकृत होने से अलग विफलता है। फ़िल्टर को दोष देने से पहले जाँचें कि कोई दूसरी प्रक्रिया पोर्ट पहले से रखती है या नहीं, फिर ऐसा नियम खोजें जो स्थानीय ट्रैफ़िक गिराता हो और उत्पाद जो सबसे संकीर्ण अनुमति समर्थित करता है उसे जोड़ें। एक ही डीबग पोर्ट के लिए होड़ करते दो औज़ार नीति-अवरोध जैसा ही संदेश देते हैं, और उनमें से केवल एक ही फ़ायरवॉल बदलाव से ठीक होता है।
Chrome का डीबग पोर्ट उसी परिवार में विफल होता है। ब्राउज़र शुरू होता है, ड्राइवर DevTools एंडपॉइंट तक नहीं पहुँच पाता, और संदेश नेटवर्क के बजाय DevTools का नाम लेता है। अतिरिक्त लॉन्च फ़्लैग और अनावश्यक ड्राइवर मैनेजर बदल देते हैं कि कौन-सी प्रक्रिया पोर्ट की मालिक है, इसलिए उन्हें हटाना कभी-कभी VPN ठीक करने जैसा लगता है।
जो परत विफल हुई उसकी मरम्मत करें
सुरंग की नहीं, जो परत विफल हुई उसकी मरम्मत करें। अगम्य loopback श्रोता के श्रोता या पोर्ट को ठीक करना होता है। अविश्वसनीय प्रमाणपत्र के लिए कॉर्पोरेट रूट वहीं स्थापित होना चाहिए जहाँ वह विशिष्ट रनटाइम देखता है, अपवाद को संकीर्ण रखते हुए। स्थानीय ट्रैफ़िक गिराने वाले फ़िल्टर के लिए बंद फ़िल्टर के बजाय विशिष्ट अनुमति नियम चाहिए, क्योंकि बंद करने से वह सब कुछ भी फिर खुल जाता है जिसकी वह रक्षा कर रहा था।
VPN को फिर से जोड़ना इनमें से किसी भी परत की परीक्षा नहीं करता। यह केवल वही बदलाव फिर चलाता है जिसने उन्हें तोड़ा था, इसलिए वही तीन विफलताएँ हर पुनःकनेक्शन के बाद लौट आती हैं और क्लाइंट को निष्क्रिय छोड़ने वाले हर रीबूट के बाद गायब हो जाती हैं।