هر دو کلاینت روی یک لپ‌تاپ هستند، از یک تونل می‌گذرند و تنها یکی از آن‌ها وصل می‌شود. این مقایسه شبیه مدرکی است که VPN را انتخابی نشان می‌دهد، در حالی که توضیح بسیار رایج‌تر این است که دو کلاینت مقصدهای متفاوتی را می‌طلبند. یک GUI میزبان، درگاه، نقش و تنظیمات TLS خودش را نگه می‌دارد و وقتی لازم باشد بی‌صدا یک هدایت SSH می‌سازد، در حالی که psql اتصالی از پیش‌فرض‌های libpq می‌سازد که پوسته شما ممکن است قبلاً تنظیم کرده باشد. بازتولید اتصالِ کارآمد به معنای خواندن تنظیمات GUI است، نه نصب دوباره تونل.

افسانه: یک کلاینتِ کارآمد مسیر را اثبات می‌کند

اگر GUI وصل شود، تونل ترافیک را حمل می‌کند و این تنها چیزی است که GUI اثبات می‌کند. درباره این که psql کدام نشانی را حل می‌کند، با کدام نقش احراز هویت می‌کند یا سوکتی که باز می‌کند هرگز از دستگاه خارج می‌شود یا نه، چیزی نمی‌گوید. مسیر مشترک است؛ پارامترها نه.

یک هدایت محلی شکاف را بزرگ‌تر می‌کند. GUI ممکن است به 127.0.0.1 روی درگاهی که از طریق SSH هدایت کرده وصل شود، و آن شنونده فقط تا زمانی که نشست GUI ادامه دارد وجود دارد. psql که بدون هدایت به localhost اشاره می‌کند، اتصال ردشده‌ای می‌گیرد که هیچ ربطی به VPN ندارد.

مقصدی را بخوانید که GUI واقعاً استفاده می‌کند

ویژگی‌های اتصال را باز کنید و چهار مقدار را کپی کنید: میزبان، درگاه، پایگاه داده و نقش. سپس سراغ زبانه تونل بروید، چون هدایت SSH یک نشانی خصوصی را به درگاه محلی تبدیل می‌کند و چیزی را که باید به psql گفت تغییر می‌دهد.

SettingWhat the GUI holdsWhat psql uses when the value is absent
DestinationA saved hostname, sometimes behind a forwardA local Unix socket, not the remote endpoint
PortThe direct port or a forwarded local port5432, or the port from a service file
Role and databaseStored per connection profileYour operating-system user name
TLS identityIts own CA bundle and verification modeWhatever PGSSLMODE or the service file says
Startup filesNot read at allRead unless -X is passed

هر سطر در لایه متفاوتی شکست می‌خورد و پیامی که می‌گیرید نام آن لایه را می‌برد. چسباندن نام دوستانه پروفایل ذخیره‌شده در psql هیچ‌یک از مقادیر بالا را حمل نمی‌کند، و نام سرویس از طریق فایلی حل می‌شود که ترمینال ممکن است هرگز نخواند.

libpq چه چیزی از پوسته شما به ارث می‌برد

psql کلاینت نازکی روی libpq است و libpq پیش از هر چیز دیگری محیط را می‌خواند. متغیرهایی مانند PGHOST، PGHOSTADDR، PGPORT، PGDATABASE، PGUSER، PGSERVICE و PGSSLMODE هر کدام می‌توانند بخشی از اتصال را تغییر مسیر دهند. آن‌ها ارث برده می‌شوند نه تایپ، بنابراین هیچ‌چیز در فرمانی که اجرا کردید آن‌ها را نشان نمی‌دهد. یک PGSSLMODE صادرشده هم می‌تواند بدون یک کلمه در خط فرمان تغییر دهد که کلاینت چه چیزی را می‌پذیرد.

دو مورد از این متغیرها اول از همه مشکوک هستند. PGHOSTADDR مقصد عددی‌ای فراهم می‌کند که حل نام را نادیده می‌گیرد در حالی که نام میزبان هنوز هویت گواهی را تعیین می‌کند، و PGSERVICE میزبان، پایگاه داده و انتخاب‌های TLS را از یک فایل سرویس بیرون می‌کشد. ریختن کل محیط برای اشکال‌زدایی عادت بدی است، چون ممکن است گذرواژه‌ها و توکن‌های نامرتبط داشته باشد؛ در عوض متغیرهایی را که برایتان مهم است انتخاب کنید.

حذف هم host و هم hostaddr یک سوکت دامنه یونیکس را به جای نشانی شبکه انتخاب می‌کند. بنابراین فراخوانی 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 ظاهر می‌شود خاموش می‌کنند.

اگر مقصد تأییدشده پشت یک pooler باشد، درگاه 6432 و درگاه 5432 ممکن است از طریق هویت‌های مختلف سرور به همان داده برسند و تأیید می‌تواند به نام pooler شکست بخورد نه نام پایگاه داده. نام را در رشته اتصال اصلاح کنید نه این که حالت را ضعیف کنید.

بگذارید پیام خطا گام بعدی را انتخاب کند

متن شکست می‌گوید تلاش تا کجا پیش رفته و این از هر حدسی درباره تونل بهتر است. نامی که حل نمی‌شود پیش از وجود سوکت شکست می‌خورد، پایان مهلت یعنی مسیر یا دیوار آتش بسته‌ها را انداخته، رد شدن یعنی چیزی پاسخ داده و امتناع کرده، و خطای احراز هویت یعنی شبکه از قبل کار می‌کرده است.

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 چیزی برای توضیح باقی نمی‌گذارد. تا وقتی توافق ندارند، هر تغییر اضافی در تونل حدسی است درباره اتصالی که ترمینال هرگز نساخته است.

مقالات مرتبط