Port-Share क्यों हर वेबसाइट आगंतुक को localhost जैसा दिखाता है
बैकएंड फ़ॉरवर्डिंग हॉप देखता है, ब्राउज़र नहीं। जाँचें कि स्रोत पता कहाँ खो जाता है, फिर तय करें कि कौन-सा घटक उसकी गारंटी ले सकता है।
एक्सेस लॉग की हर पंक्ति वही loopback पता दिखाती है, जबकि पृष्ठ स्वयं लोड होता है और प्रमाणपत्र ठीक से सत्यापित होता है। अनुपलब्धता के अर्थ में कुछ टूटा नहीं है, और इसीलिए यह स्थिति महीनों तक बनी रहती है। जो टूटा है वह एट्रिब्यूशन है: वेब बैकएंड उस हॉप का पता दर्ज करता है जिसने कनेक्शन आगे भेजा, और लॉग पर भरोसा करने वाले हर आगे के निर्णय को वही गलत उत्तर विरासत में मिला।
नीचे दी गई जाँचें तार से भीतर की ओर चलती हैं। उस पहली जाँच पर रुकें जो आपके देखे हुए मान को समझाती है, क्योंकि हर बाद का चरण मानता है कि पिछले चरण पहले से सही हैं। इनमें से कोई भी फ़्रंट-एंड कॉन्फ़िगरेशन का अनुमान लगाने की माँग नहीं करती।
लॉग पंक्ति नहीं, दोनों कनेक्शनों का पीछा करें
Port-Share एक TCP श्रोता पर दो प्रोटोकॉल मल्टीप्लेक्स करता है। OpenVPN आने वाले कनेक्शन के पहले बाइट जाँचता है, जब वह अपने प्रोटोकॉल जैसा दिखता है तो उसे रख लेता है, और बाकी सब कुछ दूसरे गंतव्य को सौंप देता है। वह गंतव्य आमतौर पर उसी होस्ट पर एक वेब सर्वर होता है, इसलिए वेब सर्वर के स्वीकृत सॉकेट का साथी OpenVPN प्रक्रिया होती है।
ss -ltnp 'sport = :443'
ss -tnp 'dport = :8080'
पहला कमांड दिखाता है कि सार्वजनिक श्रोता किसका है। दूसरा बैकएंड पोर्ट पर आने वाले कनेक्शन दिखाता है, और उनका साथी पता वही है जो एक्सेस लॉग छापेगा। यदि वह साथी loopback है, तो लॉग सटीक है और जानकारी एक परत पहले ही खो गई। लॉग फ़ील्ड का नाम बदलना या क्लाइंट-IP मॉड्यूल सक्षम करना ऐसा पता वापस नहीं लाएगा जो कनेक्शन कभी ले गया ही नहीं।
यही वह जाँच है जो बाकी सब तय करती है। यदि बैकएंड का साथी ब्राउज़र का पता है, तो पोर्ट साझा करना आपकी समस्या नहीं है और लॉग प्रारूप है।
ट्रांसपोर्ट फ़ॉरवर्डिंग हेडर इंजेक्शन नहीं है
फ़ॉरवर्डर बाइट खिसकाता है। वह HTTP पार्स नहीं करता, इसलिए वह उस अनुरोध में हेडर नहीं डाल सकता जिसे वह कभी अनुरोध के रूप में नहीं पढ़ता, और वह उस TLS स्ट्रीम में कुछ नहीं जोड़ सकता जिसे वह बिना छुए पार करता है। प्रॉक्सी हेडर की अपेक्षा रखने वाला मॉड्यूल ऐसे हेडर की प्रतीक्षा करता रहेगा जिसे कोई घटक उत्पन्न नहीं करता।
दो तंत्र मूल पता ले जा सकते हैं, और दोनों को दोनों सिरों पर सहमति चाहिए। PROXY प्रोटोकॉल कनेक्शन के आरंभ में एक छोटा हेडर जोड़ता है, और बैकएंड को उसकी अपेक्षा के लिए कॉन्फ़िगर होना चाहिए; जो बैकएंड उसकी अपेक्षा नहीं करता वह उन बाइट को अनुरोध की शुरुआत मानकर भ्रमित करने वाले ढंग से विफल होगा। X-Forwarded-For जैसे भरोसेमंद प्रॉक्सी हेडर तब काम करते हैं जब HTTP समझने वाला प्रॉक्सी उन्हें सेट करे और बैकएंड को बताया जाए कि कौन-से साथी उनका दावा कर सकते हैं।
इनमें से कोई स्वचालित नहीं है, और कोई भी डिफ़ॉल्ट रूप से सुरक्षित नहीं है। जो बैकएंड हर आने वाले फ़ॉरवर्डेड हेडर पर विश्वास करता है वह क्लाइंट को अपना पता चुनने देता है, जो लॉग की अशुद्धि को एक्सेस-नियंत्रण से बच निकलने का रास्ता बना देता है। उत्पादन पथ पर किसी भी हेडर पर भरोसा करने से पहले एक बार स्टेजिंग होस्ट पर प्रदर्शन चलाएँ।
curl -sS -H 'X-Forwarded-For: 127.0.0.1' https://site.example.com/health
grep -F '127.0.0.1' /var/log/nginx/access.log | tail -n 3
वैकल्पिक स्रोत-मैपिंग निर्देशिका
पोर्ट साझा करने में एक वैकल्पिक निर्देशिका तर्क है जो मूल स्रोत पते और फ़ॉरवर्डिंग कनेक्शन के बीच मैपिंग दर्ज करता है, उन प्लेटफ़ॉर्म पर जहाँ यह सुविधा लागू है। अपेक्षा है कि वेब पक्ष उस मैपिंग से परामर्श करे; यह हेडर नहीं है, और इसे अनुरोध में इंजेक्ट नहीं किया जाता।
वह डिज़ाइन जानने योग्य है क्योंकि यह समझाता है कि कुछ तैनातियाँ वास्तविक पते बताती हैं और कुछ नहीं, दिखने में एक जैसे फ़्रंट-एंड कॉन्फ़िगरेशन के साथ। अंतर प्राप्त करने वाले पक्ष में है, और आमतौर पर वह ऐसे मॉड्यूल या पैच में रहता है जिसे ज़्यादातर पैकेज किए गए वेब सर्वर डिफ़ॉल्ट रूप से सक्षम नहीं करते। अपने वेब सर्वर के दस्तावेज़ में वह सटीक हुक पढ़ें जो वह देता है, और मानने के बजाय पुष्टि करें कि मॉड्यूल लोड हुआ है।
यदि आप यह रास्ता चुनते हैं, तो इसे दो आधों का एकीकरण मानें: फ़ॉरवर्डर द्वारा लिखी गई मैपिंग और बैकएंड द्वारा किया गया लुकअप। दोनों सत्यापित करें, और पुष्टि करें कि निर्देशिका पुनःआरंभ के बाद बनी रहती है और व्यस्त श्रोता पर असीमित नहीं बढ़ती।
तय करें कि कौन-सा घटक पते की गारंटी देता है
कॉन्फ़िगरेशन बदलने से पहले उस घटक को नाम दें जिसे क्लाइंट पता दावा करने की अनुमति है और उन घटकों को जिन्हें उस पर विश्वास करने की अनुमति है। एक लिखित उत्तर सामान्य बहाव रोकता है, जिसमें तीन अलग परतें हर एक अलग स्रोत पर भरोसा करती हैं।
तीन डिज़ाइन ज़्यादातर ज़रूरतें पूरी करते हैं। सार्वजनिक श्रोता और वेब श्रोता को अलग रखें, ताकि वेब सर्वर वास्तविक साथी देखे और एट्रिब्यूशन की कोई समस्या न हो। सामने HTTP समझने वाला रिवर्स प्रॉक्सी रखें, अनुरोध वहीं समाप्त या पार्स करें, और इसे केवल उसी प्रॉक्सी पर भरोसा करने वाले बैकएंड के लिए फ़ॉरवर्डेड हेडर सेट करने दें। या पोर्ट साझा करना रखें और स्वीकारें कि लॉग हॉप दिखाते हैं, एक्सेस नियम पते के बजाय एप्लिकेशन पहचान के विरुद्ध लिखे गए होंगे।
जो काम नहीं करता वह यह है कि फ़ॉरवर्ड किए गए loopback पते को इस प्रमाण के रूप में लें कि अनुरोध इसी मशीन पर उत्पन्न हुआ। यह निष्कर्ष बिल्कुल उलटा है: पता इसलिए मौजूद है क्योंकि किसी स्थानीय घटक ने कनेक्शन बनाया। इस तरह लिखा नियम श्रोता तक पहुँच सकने वाले हर व्यक्ति को स्वीकार कर लेता है।
नियम का परीक्षण करें, पृष्ठ का नहीं
जो पृष्ठ लोड होता है वह सिद्ध करता है कि फ़ॉरवर्डिंग पथ काम करता है और एट्रिब्यूशन के बारे में कुछ नहीं कहता। पते के उपभोक्ता का परीक्षण करें: एक्सेस नियम, दर सीमा, ऑडिट प्रविष्टि, भू-स्थानिक लुकअप।
curl -sS -o /dev/null -w '%{http_code}\n' https://site.example.com/
tail -n 5 /var/log/nginx/access.log
grep -c '' /var/log/nginx/access.log
एक अधिकृत बाह्य अनुरोध की तुलना फ़्रंट-एंड और बैकएंड दोनों के रिकॉर्ड से करें, और पुष्टि करें कि जिस नियम को अस्वीकार करना चाहिए वह अब भी अस्वीकार करता है और जिसे स्वीकार करना चाहिए वह अब भी स्वीकार करता है। यदि लॉग पंक्ति सही है पर नियम अब भी सबको स्थानीय मानकर व्यवहार करता है, तो नियम आपके सुधारे हुए फ़ील्ड से भिन्न फ़ील्ड पढ़ता है।
तैनाती नोट्स में एट्रिब्यूशन श्रृंखला लिखकर समाप्त करें: कौन-सा श्रोता, कौन-सा फ़ॉरवर्डर, कौन-सा हेडर या मैपिंग, और कौन-सा बैकएंड उस पर भरोसा करने के लिए कॉन्फ़िगर है। अगले व्यक्ति को जो लॉग पंक्ति पढ़ेगा उसे चारों की ज़रूरत होगी, और उस नोट का अभाव ही वह कारण है कि वही टिकट एक साल बाद फिर खुलता है। इसे चैट थ्रेड में नहीं, कॉन्फ़िगरेशन के पास रखें।