रिले के ज़रिये सार्वजनिक SSH दो असंबद्ध सीमाओं पर विफल होता है, और एक को ठीक करने से आम तौर पर दूसरी खुल जाती है। या तो किनारा स्ट्रीम ले जाने के बजाय HTTP प्रतिक्रिया लौटाता है, या रिले आगे ऐसा हेडर जोड़ता है जिसे बैकएंड ने कभी पढ़ने की सहमति नहीं दी। तीन शर्तें तय करती हैं कि आप कौन-सा देख रहे हैं: सार्वजनिक रिकॉर्ड वास्तव में किस ओर इंगित करता है, स्ट्रीम ब्लॉक अपस्ट्रीम को क्या भेजता है, और SSH क्लाइंट कौन-सा नाम सत्यापित करता है। इन्हें उसी क्रम में करें।

दो सीमाएँ, दो लक्षण

किनारे की विफलता ऐसी दिखती है जैसे जहाँ SSH बैनर होना चाहिए वहाँ HTTP स्थिति पृष्ठ आ रहा हो। कनेक्शन TCP स्तर पर पूरा होता है और पहले बाइट वेब सर्वर का पाठ हैं। यह प्रोटोकॉल असंगति है, खोया पैकेट नहीं। यह आपको यह भी बताता है कि किनारा उस नाम के लिए जानबूझकर कुछ और परोस रहा है।

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

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

PROXY हेडर एक संदेश है, कोई स्विच नहीं

स्ट्रीम मॉड्यूल में, proxy_protocol on NGINX को पेलोड से पहले अपस्ट्रीम की ओर PROXY प्रोटोकॉल हेडर लिखने का निर्देश देता है। यह TCP प्रॉक्सी सक्षम नहीं करता, और इसका SSH एन्क्रिप्शन से कोई संबंध नहीं है। यह प्राप्तकर्ता को संबोधित एक टिप्पणी है। यदि प्राप्तकर्ता इसे पढ़ नहीं सकता, तो यह स्ट्रीम की शुरुआत में कचरा बन जाता है।

प्राप्त करने वाली सेवा को वह हेडर जानबूझकर उपभोग करना होगा। सामान्य sshd कनेक्शन पर पहले बाइट के रूप में SSH पहचान-अदला-बदली की अपेक्षा करता है, इसलिए अप्रत्याशित प्रस्तावना हैंडशेक को ऐसे तोड़ देती है जो भ्रष्ट सर्वर जैसा लगता है।

stream {
    server {
        listen 2222;
        proxy_pass 10.77.0.20:22;
    }
}

वह टुकड़ा VPN के ज़रिये पहुँचने योग्य बैकएंड के लिए पूरा काम करने वाला रिले है। कोई PROXY निर्देश नहीं दिखता क्योंकि प्राप्तकर्ता वह प्रोटोकॉल नहीं बोलता, और वह अनुपस्थिति छूट नहीं, एक निर्णय है।

दोनों दिशाओं को भी अलग करें। listen पंक्ति पर proxy_protocol सेट करने का अर्थ है कि NGINX अपेक्षा करता है कि उसका अपना क्लाइंट पहले हेडर भेजे; सामान्य SSH क्लाइंट के लिए इसे सक्षम करना उस समस्या का ठीक उल्टा उत्पन्न करता है जिसे लोग आम तौर पर हल करना चाहते हैं।

सार्वजनिक होस्टनाम वास्तव में कहाँ पहुँचता है

SSH सत्र में HTTP 400 पृष्ठ किनारे के बारे में साक्ष्य है। रास्ते में कुछ HTTP बोलता है, और बैकएंड पर चाबी या खाते का कोई भी काम इसे नहीं बदलेगा। किनारा तय होने तक बैकएंड बदलना बंद करें।

Cloudflare का सामान्य प्रॉक्सी किया गया रिकॉर्ड निर्धारित पोर्ट पर अपना समर्थित HTTP और HTTPS ट्रैफ़िक ले जाता है। होस्टनाम के लिए प्रॉक्सी चालू करना सामान्य TCP रिले नहीं बनाता, और SSH को पोर्ट 443 पर ले जाने से वह HTTPS नहीं बनता।

दो व्यावहारिक दिशाएँ मौजूद हैं। केवल DNS रिकॉर्ड आपके अपने TCP रिले की ओर इंगित कर सकता है, जो जोखिम का निर्णय आपके हाथ में छोड़ता है। वैकल्पिक रूप से, ऐसा उत्पाद उपयोग करें जो SSH वहन का स्पष्ट दस्तावेज़ीकरण करता है, अपने स्वयं के ओरिजिन, क्लाइंट और एक्सेस कॉन्फ़िगरेशन के साथ।

आप जो भी चुनें, रिले को अभी भी बैकएंड तक VPN मार्ग, अनुमत कनेक्शन और वापसी मार्ग चाहिए। मार्ग वैकल्पिक नहीं है क्योंकि सार्वजनिक पक्ष काम करता है।

उपनाम के माध्यम से SSH पहचान स्थिर रखें

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

Host git.example.com
    HostName ssh-entry.example.net
    Port 2222
    User git
    HostKeyAlias git.example.com

HostKeyAlias के बिना, OpenSSH होस्ट कुंजी को उसी नाम के अंतर्गत खोजता है जिससे वह जुड़ता है, इसलिए प्रविष्टि खिसक जाती है और हर उपयोगकर्ता पहले उपयोग पर बदली कुंजी की चेतावनी देखता है। उपनाम सेट करने से known-hosts प्रविष्टियाँ स्थिर रहती हैं जबकि कनेक्शन अभी भी रिले तक जाता है।

यह उपनाम केवल SSH-आधारित रिमोट पर लागू होता है। HTTPS Git URL इसे नहीं देखता, और सामान्य रिमोट URL को उस परिवहन से मेल खाना चाहिए जो आपने वास्तव में तैयार किया है।

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

हर हॉप को अलग से सत्यापित करें

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

हर परिणाम के साथ गंतव्य पता, पोर्ट और पहले प्रोटोकॉल बाइट रखें। यह तिकड़ी किनारे की त्रुटि को VPN रूटिंग समस्या और SSH प्रमाणीकरण विफलता से अलग करती है, और यही मरम्मत और अनुमान के बीच का अंतर है।

अंत में, इच्छित जोखिम का दस्तावेज़ीकरण करें। निजी बैकएंड तक SSH ले जाने वाला TCP रिले सार्वजनिक परिधि में जानबूझकर किया गया द्वार है, और वह किसी भी अन्य आवक सेवा जैसी ही समीक्षा का पात्र है।

संबंधित लेख