VPN nie blokuje psql: twój klient łączy się gdzie indziej
psql i klient GUI mogą z jednej maszyny wybierać różne punkty końcowe. Porównaj host, gniazdo, rolę i TLS, zanim obwinisz VPN.
Oba klienci siedzą na tym samym laptopie, przechodzą przez ten sam tunel, a łączy się tylko jeden z nich. To porównanie wygląda jak dowód, że VPN jest wybiórczy, podczas gdy znacznie częstszym wyjaśnieniem jest to, że oba klienci wybierają różne cele. GUI trzyma własny host, port, rolę i ustawienia TLS i po cichu buduje przekierowanie SSH, gdy go potrzebuje, a psql składa połączenie z domyślnych wartości libpq, które twoja powłoka mogła już ustawić. Odtworzenie działającego połączenia to kwestia odczytania ustawień GUI, a nie ponownej instalacji tunelu.
Mit: jeden działający klient dowodzi ścieżki
Jeśli GUI się łączy, tunel przenosi ruch, i to jest jedyne, czego GUI dowodzi. Nie mówi nic o tym, który adres rozwiązuje psql, w jakiej roli się uwierzytelnia, ani czy otwierane przez niego gniazdo kiedykolwiek opuszcza maszynę. Ścieżka jest wspólna; parametry nie.
Lokalne przekierowanie powiększa różnicę. GUI może łączyć się z 127.0.0.1 na porcie, który przekierował przez SSH, a ten nasłuch istnieje tylko przez czas sesji GUI. psql wskazujący na localhost bez przekierowania otrzymuje odrzucone połączenie, które nie ma nic wspólnego z VPN.
Odczytaj punkt końcowy, którego GUI naprawdę używa
Otwórz właściwości połączenia i skopiuj cztery wartości: host, port, bazę danych i rolę. Następnie poszukaj zakładki tunelu, bo przekierowanie SSH zamienia adres prywatny na port lokalny i zmienia to, co trzeba powiedzieć 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 |
Każdy wiersz zawodzi na innej warstwie, a komunikat, który otrzymujesz, nazywa tę warstwę. Wklejenie przyjaznej nazwy zapisanego profilu do psql nie przenosi żadnej z powyższych wartości, a nazwa usługi jest rozwiązywana przez plik, którego terminal może nigdy nie przeczytać.
Co libpq dziedziczy z twojej powłoki
psql to cienki klient nad libpq, a libpq czyta środowisko, zanim przeczyta cokolwiek innego. Zmienne takie jak PGHOST, PGHOSTADDR, PGPORT, PGDATABASE, PGUSER, PGSERVICE i PGSSLMODE mogą każda przekierować część połączenia. Są dziedziczone, a nie wpisywane, więc nic w poleceniu, które uruchomiłeś, ich nie pokazuje. Wyeksportowana PGSSLMODE może też zmienić to, co klient akceptuje, bez słowa w wierszu poleceń.
Dwie z tych zmiennych zasługują na podejrzenie w pierwszej kolejności. PGHOSTADDR dostarcza numeryczny cel, który omija rozwiązywanie nazw, podczas gdy nazwa hosta nadal rządzi tożsamością certyfikatu, a PGSERVICE wyciąga host, bazę danych i wybory TLS z pliku usługi. Zrzucanie całego środowiska do debugowania to zły nawyk, bo może zawierać hasła i niepowiązane tokeny; zamiast tego wybierz zmienne, na których ci zależy.
Pominięcie zarówno host, jak i hostaddr wybiera gniazdo domeny Unix zamiast adresu sieciowego. Wywołanie psql bez -h może więc powieść się lokalnie albo zawieść z błędem gniazda, nie dotykając nigdy trasy używanej przez GUI.
Wyślij te same parametry ręcznie
Mając wartości GUI pod ręką, przekaż je jawnie i pomiń plik startowy, który mógłby dodać nadpisania. Ciąg połączenia poniżej jest ilustracyjny: zastąp punkt końcowy, port, bazę danych i rolę wartościami zatwierdzonymi przez administratora i zachowaj konfigurację zaufania, która już działa.
psql -X "host=db.internal.example port=6432 dbname=orders user=report_ro sslmode=verify-full connect_timeout=5"Trzy szczegóły w tym poleceniu są celowe. -X tłumi plik startowy psql, choć nie tłumi środowiska libpq ani definicji usługi. connect_timeout=5 nie pozwala trasie donikąd zawiesić terminala na minuty. sslmode=verify-full utrzymuje włączone sprawdzanie certyfikatu i nazwy hosta, czyli dokładnie tę część, którą ludzie wyłączają, gdy pojawia się błąd TLS.
Jeśli zatwierdzony punkt końcowy stoi za poolerem, port 6432 i port 5432 mogą docierać do tych samych danych przez różne tożsamości serwera, a weryfikacja może zawieść na nazwie poolera, a nie bazy danych. Popraw nazwę w ciągu połączenia zamiast osłabiać tryb.
Niech komunikat o błędzie wybierze następny krok
Tekst błędu mówi, jak daleko dotarła próba, i to bije każde domysły o tunelu. Nazwa, której nie można rozwiązać, zawodzi, zanim powstanie gniazdo, przekroczenie czasu oznacza, że trasa lub zapora porzuciła pakiety, odmowa oznacza, że coś odpowiedziało i odmówiło, a błąd uwierzytelniania oznacza, że sieć już działała.
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 --versionPorównaj wynik \conninfo z aktywną sesją GUI: ten sam host, ten sam port, ta sama rola, ten sam stan TLS. Gdy te cztery się zgadzają, VPN nie ma już nic do wyjaśnienia. Dopóki się nie zgadzają, każda dodatkowa zmiana tunelu jest domysłem o połączeniu, którego terminal nigdy nie nawiązał.