Le VPN ne bloque pas psql : votre client joint une autre destination
psql et un client GUI peuvent joindre des extrémités différentes depuis une même machine. Comparez hôte, socket, rôle et TLS avant d’accuser le VPN.
Les deux clients sont sur le même ordinateur portable, traversent le même tunnel, et un seul d’entre eux se connecte. Cette comparaison ressemble à une preuve que le VPN est sélectif, alors que l’explication bien plus courante est que les deux clients joignent des destinations différentes. Une GUI conserve son propre hôte, port, rôle et réglages TLS et construit discrètement une redirection SSH quand elle en a besoin, tandis que psql assemble une connexion à partir des valeurs par défaut de libpq que votre shell a peut-être déjà définies. Reproduire la connexion qui fonctionne, c’est lire les réglages de la GUI, pas réinstaller le tunnel.
Le mythe : un client qui fonctionne prouve le chemin
Si la GUI se connecte, le tunnel transporte du trafic, et c’est la seule chose que la GUI prouve. Elle ne dit rien sur l’adresse que psql résout, sur le rôle avec lequel il s’authentifie, ni sur la question de savoir si la socket qu’il ouvre quitte un jour la machine. Le chemin est partagé ; les paramètres ne le sont pas.
Une redirection locale creuse l’écart. La GUI peut se connecter à 127.0.0.1 sur un port qu’elle a redirigé via SSH, et cet écouteur n’existe que le temps de la session de la GUI. psql pointé vers localhost sans la redirection reçoit une connexion refusée qui n’a rien à voir avec le VPN.
Lisez l’extrémité que la GUI utilise réellement
Ouvrez les propriétés de la connexion et copiez quatre valeurs : hôte, port, base de données et rôle. Cherchez ensuite un onglet tunnel, car une redirection SSH transforme une adresse privée en port local et change ce qu’il faut dire à 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 |
Chaque ligne échoue à une couche différente, et le message que vous recevez nomme cette couche. Coller le nom convivial du profil enregistré dans psql ne transporte aucune des valeurs ci-dessus, et un nom de service se résout via un fichier que le terminal ne lira peut-être jamais.
Ce que libpq hérite de votre shell
psql est un client léger au-dessus de libpq, et libpq lit l’environnement avant de lire quoi que ce soit d’autre. Des variables comme PGHOST, PGHOSTADDR, PGPORT, PGDATABASE, PGUSER, PGSERVICE et PGSSLMODE peuvent chacune rediriger une partie de la connexion. Elles sont héritées plutôt que saisies, donc rien dans la commande que vous avez lancée ne les montre. Une PGSSLMODE exportée peut aussi changer ce que le client accepte sans un mot sur la ligne de commande.
Deux de ces variables méritent d’abord la suspicion. PGHOSTADDR fournit une destination numérique qui écrase la résolution de noms tandis que le nom d’hôte régit encore l’identité du certificat, et PGSERVICE tire l’hôte, la base de données et les choix TLS d’un fichier de service. Vider tout l’environnement pour déboguer est une mauvaise habitude, car il peut contenir des mots de passe et des jetons sans rapport ; sélectionnez plutôt les variables qui vous intéressent.
Omettre à la fois host et hostaddr sélectionne une socket de domaine Unix plutôt qu’une adresse réseau. Un appel psql sans -h peut donc réussir localement, ou échouer sur une erreur de socket, sans jamais toucher la route qu’utilise la GUI.
Envoyez les mêmes paramètres à la main
Les valeurs de la GUI en main, passez-les explicitement et sautez le fichier de démarrage qui pourrait ajouter des substitutions. La chaîne de connexion ci-dessous est illustrative : remplacez l’extrémité, le port, la base de données et le rôle par les valeurs approuvées par votre administrateur, et gardez la configuration de confiance qui fonctionne déjà.
psql -X "host=db.internal.example port=6432 dbname=orders user=report_ro sslmode=verify-full connect_timeout=5"Trois détails de cette commande sont délibérés. -X supprime le fichier de démarrage de psql, mais ne supprime ni l’environnement de libpq ni une définition de service. connect_timeout=5 empêche une route sans issue de bloquer le terminal pendant des minutes. sslmode=verify-full maintient les vérifications de certificat et de nom d’hôte activées, ce qui est exactement la partie que les gens désactivent quand une erreur TLS apparaît.
Si l’extrémité approuvée se trouve derrière un pooler, le port 6432 et le port 5432 peuvent atteindre les mêmes données via des identités de serveur différentes, et la vérification peut échouer sur le nom du pooler plutôt que sur celui de la base de données. Corrigez le nom dans la chaîne de connexion au lieu d’affaiblir le mode.
Laissez le message d’erreur choisir l’étape suivante
Le texte de l’échec dit jusqu’où la tentative est allée, et cela vaut mieux que toute supposition sur le tunnel. Un nom qui ne se résout pas échoue avant qu’une socket existe, un délai dépassé signifie que la route ou un pare-feu a jeté des paquets, un refus signifie que quelque chose a répondu et décliné, et une erreur d’authentification signifie que le réseau fonctionnait déjà.
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 --versionComparez la sortie de \conninfo avec la session active de la GUI : même hôte, même port, même rôle, même état TLS. Quand ces quatre éléments concordent, le VPN n’a plus rien à expliquer. Jusqu’à ce qu’ils concordent, chaque changement supplémentaire du tunnel est une supposition sur une connexion que le terminal n’a jamais faite.