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.

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

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 --version

Poró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ł.

Powiązane artykuły