Kedua klien berada di laptop yang sama, melewati tunnel yang sama, dan hanya salah satunya yang terhubung. Perbandingan itu terasa seperti bukti bahwa VPN bersikap selektif, padahal penjelasan yang jauh lebih umum adalah bahwa kedua klien menuju tujuan yang berbeda. GUI menyimpan host, port, peran, dan pengaturan TLS-nya sendiri lalu diam-diam membangun penerusan SSH saat membutuhkannya, sementara psql menyusun koneksi dari nilai bawaan libpq yang mungkin sudah diatur oleh shell Anda. Mereproduksi koneksi yang berhasil adalah soal membaca pengaturan GUI, bukan memasang ulang tunnel.

Mitos: satu klien yang berhasil membuktikan jalurnya

Jika GUI terhubung, tunnel membawa lalu lintas, dan itulah satu-satunya yang dibuktikan GUI. GUI tidak mengatakan apa pun tentang alamat mana yang diresolusikan psql, peran apa yang dipakai untuk mengautentikasi, atau apakah soket yang dibukanya pernah keluar dari mesin. Jalurnya sama; parameternya tidak.

Penerusan lokal memperlebar perbedaan. GUI mungkin terhubung ke 127.0.0.1 pada port yang diteruskannya lewat SSH, dan pendengar itu hanya ada selama sesi GUI berlangsung. psql yang diarahkan ke localhost tanpa penerusan mendapat koneksi ditolak yang tidak ada hubungannya dengan VPN.

Baca endpoint yang benar-benar dipakai GUI

Buka properti koneksi dan salin empat nilai: host, port, basis data, dan peran. Lalu cari tab tunnel, karena penerusan SSH mengubah alamat privat menjadi port lokal dan mengubah apa yang harus diberitahukan ke 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

Setiap baris gagal di lapisan berbeda, dan pesan yang Anda terima menyebut lapisan itu. Menempelkan nama ramah profil tersimpan ke psql tidak membawa satu pun nilai di atas, dan nama layanan diresolusikan melalui berkas yang mungkin tidak pernah dibaca terminal.

Apa yang diwarisi libpq dari shell Anda

psql adalah klien tipis di atas libpq, dan libpq membaca lingkungan sebelum membaca apa pun yang lain. Variabel seperti PGHOST, PGHOSTADDR, PGPORT, PGDATABASE, PGUSER, PGSERVICE, dan PGSSLMODE masing-masing dapat mengalihkan sebagian koneksi. Variabel-variabel itu diwarisi, bukan diketik, jadi tidak ada satu pun yang tampak dalam perintah yang Anda jalankan. PGSSLMODE yang diekspor juga dapat mengubah apa yang diterima klien tanpa sepatah kata di baris perintah.

Dua dari variabel itu paling patut dicurigai. PGHOSTADDR memasok tujuan numerik yang mengalahkan resolusi nama sementara nama host masih menentukan identitas sertifikat, dan PGSERVICE menarik host, basis data, serta pilihan TLS dari berkas layanan. Membuang seluruh lingkungan untuk menelusuri ini kebiasaan buruk, karena bisa berisi kata sandi dan token yang tidak berkaitan; pilih saja variabel yang Anda pedulikan.

Menghilangkan host dan hostaddr sekaligus memilih soket domain Unix, bukan alamat jaringan. Panggilan psql tanpa -h karena itu bisa berhasil secara lokal, atau gagal dengan galat soket, tanpa pernah menyentuh rute yang dipakai GUI.

Kirim parameter yang sama dengan tangan

Dengan nilai GUI di tangan, berikan secara eksplisit dan lewati berkas awal yang bisa menambahkan penimpaan. String koneksi di bawah ini bersifat ilustratif: ganti endpoint, port, basis data, dan peran dengan nilai yang disetujui administrator Anda, lalu pertahankan konfigurasi kepercayaan yang sudah bekerja.

psql -X "host=db.internal.example port=6432 dbname=orders user=report_ro sslmode=verify-full connect_timeout=5"

Tiga perincian dalam perintah itu disengaja. -X menekan berkas awal psql, meski tidak menekan lingkungan libpq atau definisi layanan. connect_timeout=5 mencegah rute yang buntu menggantungkan terminal selama beberapa menit. sslmode=verify-full menjaga pemeriksaan sertifikat dan nama host tetap aktif, dan itulah bagian yang biasanya dimatikan orang saat galat TLS muncul.

Jika endpoint yang disetujui berada di belakang pooler, port 6432 dan port 5432 dapat mencapai data yang sama melalui identitas server yang berbeda, dan verifikasi bisa gagal pada nama pooler, bukan nama basis data. Perbaiki nama di string koneksi daripada melemahkan mode.

Biarkan pesan galat memilih langkah berikutnya

Teks kegagalan menyebutkan sejauh mana upaya itu berjalan, dan itu mengalahkan dugaan apa pun tentang tunnel. Nama yang tidak dapat diresolusikan gagal sebelum soket ada, waktu habis berarti rute atau firewall menjatuhkan paket, penolakan berarti ada sesuatu yang menjawab dan menolak, dan galat autentikasi berarti jaringannya sudah bekerja.

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

Bandingkan keluaran \conninfo dengan sesi langsung GUI: host sama, port sama, peran sama, status TLS sama. Ketika keempatnya cocok, VPN tidak punya apa pun lagi untuk dijelaskan. Sampai keempatnya cocok, setiap perubahan tunnel tambahan adalah dugaan tentang koneksi yang tidak pernah dibuat terminal.

Artikel terkait