VPN لا يحجب psql: عميلك يتصل بوجهة أخرى
قد يتصل psql وبرنامج GUI بوجهتين مختلفتين من الجهاز نفسه. قارن المضيف والمقبس والدور وTLS قبل أن تلوم VPN.
كلا العميلين موجودان على الحاسوب المحمول نفسه، ويمران عبر النفق نفسه، ومع ذلك لا يتصل إلا أحدهما. تبدو هذه المقارنة دليلاً على أن VPN انتقائي، بينما التفسير الأكثر شيوعاً هو أن العميلين يطلبان وجهتين مختلفتين. يحتفظ GUI بمضيفه ومنفذه ودوره وإعدادات TLS الخاصة به ويبني بصمت نفق SSH عندما يحتاج إليه، بينما يركّب psql اتصالاً من إعدادات libpq الافتراضية التي ربما ضبطتها قوقعته. إعادة إنتاج الاتصال الناجح مسألة قراءة إعدادات GUI، لا إعادة تثبيت النفق.
الأسطورة: عميل واحد ناجح يثبت المسار
إذا اتصل GUI، فإن النفق ينقل حركة المرور، وهذا كل ما يثبته GUI. لا يقول شيئاً عن العنوان الذي يحلّه psql، ولا عن الدور الذي يصادق به، ولا عمّا إذا كان المقبس الذي يفتحه يغادر الجهاز أصلاً. المسار مشترك؛ أما المعاملات فليست كذلك.
النفق المحلي يوسّع الفجوة. قد يتصل GUI بـ 127.0.0.1 على منفذ نفّذه عبر SSH، وهذا المستمع لا يوجد إلا ما دامت جلسة GUI. أما psql الموجّه إلى localhost دون ذلك النفق فيحصل على اتصال مرفوض لا علاقة له بـ 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 بدلاً من عنوان شبكة. لذلك قد ينجح استدعاء psql بدون -h محلياً، أو يفشل بخطأ مقبس، دون أن يمس المسار الذي يستخدمه 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 ما يفسّره. وإلى أن تتفق، فإن كل تغيير إضافي في النفق تخمين حول اتصال لم تُجريه الطرفية أبداً.