Das VPN blockiert psql nicht: Dein Client wählt ein anderes Ziel
psql und ein GUI-Client können von einer Maschine aus unterschiedliche Endpunkte anwählen. Vergleiche Host, Socket, Rolle und TLS, bevor du das VPN verantwortlich machst.
Beide Clients sitzen auf demselben Laptop, durchqueren denselben Tunnel, und nur einer von ihnen verbindet sich. Dieser Vergleich wirkt wie ein Beweis, dass das VPN wählerisch ist, während die weit häufigere Erklärung lautet, dass die beiden Clients unterschiedliche Ziele anwählen. Eine GUI behält ihren eigenen Host, Port, ihre Rolle und ihre TLS-Einstellungen und baut bei Bedarf still eine SSH-Weiterleitung auf, während psql eine Verbindung aus libpq-Standardwerten zusammensetzt, die deine Shell vielleicht schon gesetzt hat. Die funktionierende Verbindung nachzubauen bedeutet, die Einstellungen der GUI zu lesen, nicht den Tunnel neu zu installieren.
Der Mythos: Ein funktionierender Client beweist den Pfad
Wenn sich die GUI verbindet, überträgt der Tunnel Verkehr, und das ist das Einzige, was die GUI beweist. Sie sagt nichts darüber aus, welche Adresse psql auflöst, mit welcher Rolle es sich authentifiziert oder ob der Socket, den es öffnet, die Maschine überhaupt verlässt. Der Pfad ist gemeinsam; die Parameter nicht.
Eine lokale Weiterleitung vergrößert die Lücke. Die GUI kann sich mit 127.0.0.1 auf einem Port verbinden, den sie über SSH weitergeleitet hat, und dieser Listener existiert nur, solange die GUI-Sitzung dauert. psql, ohne die Weiterleitung auf localhost gerichtet, bekommt eine abgelehnte Verbindung, die nichts mit dem VPN zu tun hat.
Lies den Endpunkt, den die GUI tatsächlich nutzt
Öffne die Eigenschaften der Verbindung und kopiere vier Werte: Host, Port, Datenbank und Rolle. Suche dann einen Tunnel-Tab, denn eine SSH-Weiterleitung verwandelt eine private Adresse in einen lokalen Port und ändert, was psql gesagt werden muss.
| 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 |
Jede Zeile scheitert auf einer anderen Ebene, und die Meldung, die du bekommst, benennt diese Ebene. Den freundlichen Namen des gespeicherten Profils in psql einzufügen, überträgt keinen der obigen Werte, und ein Dienstname wird über eine Datei aufgelöst, die das Terminal vielleicht nie liest.
Was libpq von deiner Shell erbt
psql ist ein dünner Client über libpq, und libpq liest die Umgebung, bevor es irgendetwas anderes liest. Variablen wie PGHOST, PGHOSTADDR, PGPORT, PGDATABASE, PGUSER, PGSERVICE und PGSSLMODE können jeweils einen Teil der Verbindung umleiten. Sie werden geerbt statt getippt, also zeigt nichts in dem Befehl, den du ausgeführt hast, sie an. Ein exportiertes PGSSLMODE kann ebenfalls ändern, was der Client akzeptiert, ohne ein Wort auf der Kommandozeile.
Zwei dieser Variablen verdienen zuerst Verdacht. PGHOSTADDR liefert ein numerisches Ziel, das die Namensauflösung überschreibt, während der Hostname weiterhin die Zertifikatsidentität bestimmt, und PGSERVICE zieht Host, Datenbank und TLS-Auswahl aus einer Dienstdatei. Die gesamte Umgebung zum Debuggen auszugeben ist eine schlechte Angewohnheit, da sie Passwörter und unabhängige Token enthalten kann; wähle stattdessen die Variablen aus, die dich interessieren.
Das Weglassen von host und hostaddr wählt einen Unix-Domain-Socket statt einer Netzwerkadresse. Ein psql-Aufruf ohne -h kann daher lokal gelingen oder mit einem Socket-Fehler scheitern, ohne jemals die Route zu berühren, die die GUI nutzt.
Sende dieselben Parameter von Hand
Mit den Werten der GUI zur Hand, übergib sie ausdrücklich und überspringe die Startdatei, die Überschreibungen hinzufügen könnte. Die Verbindungszeichenfolge unten ist illustrativ: Ersetze Endpunkt, Port, Datenbank und Rolle durch die von deinem Administrator genehmigten Werte und behalte die Vertrauenskonfiguration, die bereits funktioniert.
psql -X "host=db.internal.example port=6432 dbname=orders user=report_ro sslmode=verify-full connect_timeout=5"Drei Details in diesem Befehl sind beabsichtigt. -X unterdrückt die Startdatei von psql, allerdings nicht die Umgebung von libpq oder eine Dienstdefinition. connect_timeout=5 verhindert, dass eine Route ins Leere das Terminal minutenlang hängen lässt. sslmode=verify-full hält Zertifikats- und Hostnamenprüfungen eingeschaltet, was genau der Teil ist, den Leute abschalten, wenn ein TLS-Fehler auftaucht.
Wenn der genehmigte Endpunkt hinter einem Pooler liegt, können Port 6432 und Port 5432 dieselben Daten über unterschiedliche Serveridentitäten erreichen, und die Verifikation kann am Namen des Poolers statt an dem der Datenbank scheitern. Korrigiere den Namen in der Verbindungszeichenfolge, statt den Modus abzuschwächen.
Lass die Fehlermeldung den nächsten Schritt wählen
Der Fehlertext sagt, wie weit der Versuch gekommen ist, und das schlägt jede Vermutung über den Tunnel. Ein Name, der sich nicht auflösen lässt, scheitert, bevor ein Socket existiert, ein Timeout bedeutet, dass die Route oder eine Firewall Pakete verworfen hat, eine Ablehnung bedeutet, dass etwas geantwortet und abgelehnt hat, und ein Authentifizierungsfehler bedeutet, dass das Netzwerk bereits funktioniert hat.
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 --versionVergleiche die Ausgabe von \conninfo mit der laufenden Sitzung der GUI: derselbe Host, derselbe Port, dieselbe Rolle, derselbe TLS-Zustand. Wenn diese vier übereinstimmen, hat das VPN nichts mehr zu erklären. Bis sie übereinstimmen, ist jede weitere Tunneländerung eine Vermutung über eine Verbindung, die das Terminal nie aufgebaut hat.