VPN, psql को नहीं रोकता: आपका क्लाइंट कहीं और डायल करता है
psql और GUI क्लाइंट एक ही मशीन से अलग-अलग एंडपॉइंट पर डायल कर सकते हैं। VPN को दोष देने से पहले होस्ट, सॉकेट, भूमिका और TLS की तुलना करें।
दोनों क्लाइंट एक ही लैपटॉप पर हैं, एक ही टनल से गुज़रते हैं, और उनमें से सिर्फ़ एक जुड़ता है। यह तुलना ऐसा सबूत लगती है कि VPN चुन-चुनकर काम करता है, जबकि कहीं ज़्यादा आम व्याख्या यह है कि दोनों क्लाइंट अलग-अलग ठिकानों पर डायल करते हैं। एक GUI अपना होस्ट, पोर्ट, भूमिका और TLS सेटिंग्स रखता है और ज़रूरत पड़ने पर चुपचाप एक SSH फ़ॉरवर्ड बनाता है, जबकि psql आपके शेल द्वारा पहले से सेट किए गए libpq डिफ़ॉल्ट से कनेक्शन जोड़ता है। काम करने वाले कनेक्शन को दोहराना GUI की सेटिंग्स पढ़ने का मामला है, टनल दोबारा इंस्टॉल करने का नहीं।
मिथक: एक चलता हुआ क्लाइंट रास्ता साबित करता है
अगर GUI जुड़ता है, तो टनल ट्रैफ़िक ले जाती है, और GUI बस यही साबित करता है। यह नहीं बताता कि psql कौन-सा पता हल करता है, किस भूमिका से प्रमाणित होता है, या वह जो सॉकेट खोलता है वह कभी मशीन से बाहर जाता है या नहीं। रास्ता साझा है; पैरामीटर नहीं।
लोकल फ़ॉरवर्ड अंतर को और बड़ा करता है। GUI किसी ऐसे पोर्ट पर 127.0.0.1 से जुड़ सकता है जिसे उसने SSH के ज़रिए फ़ॉरवर्ड किया है, और वह श्रोता सिर्फ़ GUI सत्र के दौरान मौजूद रहता है। फ़ॉरवर्ड के बिना localhost की ओर इशारा करता psql ऐसा अस्वीकृत कनेक्शन पाता है जिसका VPN से कोई लेना-देना नहीं है।
वह एंडपॉइंट पढ़ें जो GUI वास्तव में इस्तेमाल करता है
कनेक्शन के गुण खोलें और चार मान कॉपी करें: होस्ट, पोर्ट, डेटाबेस और भूमिका। फिर टनल टैब खोजें, क्योंकि SSH फ़ॉरवर्ड एक निजी पते को लोकल पोर्ट में बदल देता है और यह भी बदल देता है कि psql को क्या बताना है।
| Setting | What the GUI holds | What psql uses when the value is absent |
|---|---|---|
| Destination | A saved hostname, sometimes behind a forward | A local Unix socket, not the remote endpoint |
| Port | The direct port or a forwarded local port | 5432, or the port from a service file |
| Role and database | Stored per connection profile | Your operating-system user name |
| TLS identity | Its own CA bundle and verification mode | Whatever PGSSLMODE or the service file says |
| Startup files | Not read at all | Read unless -X is passed |
हर पंक्ति अलग परत पर विफल होती है, और आपको मिलने वाला संदेश उसी परत का नाम लेता है। सहेजी गई प्रोफ़ाइल का दोस्ताना नाम psql में चिपकाने से ऊपर के कोई भी मान नहीं जाते, और सेवा का नाम ऐसी फ़ाइल से हल होता है जिसे टर्मिनल शायद कभी न पढ़े।
libpq आपके शेल से क्या विरासत में लेता है
psql, libpq के ऊपर एक पतला क्लाइंट है, और libpq किसी और चीज़ से पहले पर्यावरण पढ़ता है। PGHOST, PGHOSTADDR, PGPORT, PGDATABASE, PGUSER, PGSERVICE और PGSSLMODE जैसे वेरिएबल में से हर एक कनेक्शन का कोई हिस्सा दूसरी ओर भेज सकता है। ये टाइप किए जाने के बजाय विरासत में मिलते हैं, इसलिए आपके चलाए कमांड में कुछ भी इन्हें नहीं दिखाता। निर्यात किया गया PGSSLMODE भी कमांड लाइन पर एक शब्द कहे बिना बदल सकता है कि क्लाइंट क्या स्वीकार करता है।
इनमें से दो वेरिएबल पहले शक के हक़दार हैं। PGHOSTADDR एक संख्यात्मक गंतव्य देता है जो नाम-हल को दरकिनार करता है जबकि होस्टनाम अब भी प्रमाणपत्र की पहचान तय करता है, और PGSERVICE सेवा फ़ाइल से होस्ट, डेटाबेस और TLS के विकल्प खींच लेता है। इसे डीबग करने के लिए पूरा पर्यावरण डंप करना बुरी आदत है, क्योंकि इसमें पासवर्ड और असंबंधित टोकन हो सकते हैं; इसके बजाय वे वेरिएबल चुनें जिनकी आपको परवाह है।
host और hostaddr दोनों छोड़ देने पर नेटवर्क पते के बजाय Unix-डोमेन सॉकेट चुना जाता है। इसलिए -h के बिना psql कॉल स्थानीय रूप से सफल हो सकता है, या सॉकेट त्रुटि से विफल हो सकता है, GUI जो मार्ग इस्तेमाल करता है उसे कभी छुए बिना।
वही पैरामीटर हाथ से भेजें
GUI के मान हाथ में होने पर उन्हें स्पष्ट रूप से भेजें और वह स्टार्टअप फ़ाइल छोड़ दें जो ओवरराइड जोड़ सकती है। नीचे दी गई कनेक्शन स्ट्रिंग उदाहरण है: एंडपॉइंट, पोर्ट, डेटाबेस और भूमिका को उन मानों से बदलें जिन्हें आपके व्यवस्थापक ने मंज़ूर किया है, और जो ट्रस्ट कॉन्फ़िगरेशन पहले से काम कर रहा है उसे रखें।
psql -X "host=db.internal.example port=6432 dbname=orders user=report_ro sslmode=verify-full connect_timeout=5"उस कमांड में तीन ब्यौरे जानबूझकर हैं। -X psql की स्टार्टअप फ़ाइल दबाता है, हालाँकि libpq का पर्यावरण या सेवा परिभाषा नहीं दबाता। connect_timeout=5 किसी खाली मार्ग को टर्मिनल को मिनटों तक लटकाने से रोकता है। sslmode=verify-full प्रमाणपत्र और होस्टनाम की जाँच चालू रखता है, और TLS त्रुटि दिखने पर लोग ठीक यही हिस्सा बंद करते हैं।
अगर मंज़ूर किया गया एंडपॉइंट किसी पूलर के पीछे है, तो पोर्ट 6432 और पोर्ट 5432 अलग-अलग सर्वर पहचानों से उसी डेटा तक पहुँच सकते हैं, और सत्यापन डेटाबेस के नाम पर नहीं, पूलर के नाम पर विफल हो सकता है। मोड कमज़ोर करने के बजाय कनेक्शन स्ट्रिंग में नाम सुधारें।
अगला कदम त्रुटि संदेश को चुनने दें
विफलता का पाठ बताता है कि प्रयास कितनी दूर गया, और यह टनल के बारे में किसी भी अनुमान से बेहतर है। जो नाम हल नहीं होता वह सॉकेट बनने से पहले विफल होता है, समय-सीमा का मतलब है कि मार्ग या फ़ायरवॉल ने पैकेट गिराए, इनकार का मतलब है कि किसी चीज़ ने जवाब देकर मना किया, और प्रमाणीकरण त्रुटि का मतलब है कि नेटवर्क पहले से काम कर रहा था।
psql -X -w "host=db.internal.example port=6432 dbname=orders user=report_ro sslmode=verify-full connect_timeout=5" -c '\conninfo'
env | grep -E '^PG'
psql --version\conninfo के आउटपुट की GUI के जीवंत सत्र से तुलना करें: वही होस्ट, वही पोर्ट, वही भूमिका, वही TLS स्थिति। जब ये चारों मेल खाते हैं, तो VPN के पास समझाने को कुछ नहीं बचता। जब तक वे नहीं मिलते, टनल में हर अतिरिक्त बदलाव ऐसे कनेक्शन के बारे में अनुमान है जो टर्मिनल ने कभी नहीं बनाया।