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 більше нічого пояснювати. Доки вони не збігаються, кожна додаткова зміна тунелю — це здогад про з'єднання, якого термінал ніколи не встановлював.