Beide clients staan op dezelfde laptop, gaan door dezelfde tunnel, en slechts één van hen maakt verbinding. Die vergelijking voelt als bewijs dat de VPN selectief is, terwijl de veel waarschijnlijkere verklaring is dat de twee clients verschillende bestemmingen kiezen. Een GUI houdt zijn eigen host, poort, rol en TLS-instellingen bij en bouwt stilletjes een SSH-doorstuur op wanneer dat nodig is, terwijl psql een verbinding samenstelt uit libpq-standaardwaarden die je shell misschien al heeft gezet. De werkende verbinding reproduceren is een kwestie van de instellingen van de GUI lezen, niet van de tunnel opnieuw installeren.

De mythe: één werkende client bewijst het pad

Als de GUI verbinding maakt, draagt de tunnel verkeer, en dat is het enige wat de GUI bewijst. Hij zegt niets over welk adres psql oplost, met welke rol hij authenticeert, of de socket die hij opent ooit de machine verlaat. Het pad is gedeeld; de parameters niet.

Een lokale doorstuur vergroot de kloof. De GUI kan verbinding maken met 127.0.0.1 op een poort die hij via SSH heeft doorgestuurd, en die luisteraar bestaat alleen zolang de GUI-sessie duurt. psql dat naar localhost wijst zonder de doorstuur krijgt een geweigerde verbinding die niets met de VPN te maken heeft.

Lees het eindpunt dat de GUI echt gebruikt

Open de eigenschappen van de verbinding en kopieer vier waarden: host, poort, database en rol. Zoek daarna een tunneltab, want een SSH-doorstuur maakt van een privéadres een lokale poort en verandert wat psql moet worden verteld.

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

Elke rij faalt in een andere laag, en het bericht dat je krijgt noemt die laag. De vriendelijke naam van het opgeslagen profiel in psql plakken draagt geen van de bovenstaande waarden over, en een dienstnaam wordt opgelost via een bestand dat de terminal misschien nooit leest.

Wat libpq van je shell erft

psql is een dunne client boven libpq, en libpq leest de omgeving voordat het iets anders leest. Variabelen zoals PGHOST, PGHOSTADDR, PGPORT, PGDATABASE, PGUSER, PGSERVICE en PGSSLMODE kunnen elk een deel van de verbinding omleiden. Ze worden geërfd in plaats van getypt, dus niets in de opdracht die je uitvoerde toont ze. Een geëxporteerde PGSSLMODE kan ook veranderen wat de client accepteert zonder een woord op de opdrachtregel.

Twee van die variabelen verdienen eerst argwaan. PGHOSTADDR levert een numerieke bestemming die naamresolutie overschrijft terwijl de hostnaam nog steeds de certificaatidentiteit bepaalt, en PGSERVICE haalt host, database en TLS-keuzes uit een dienstbestand. De hele omgeving dumpen om dit te debuggen is een slechte gewoonte, want er kunnen wachtwoorden en ongerelateerde tokens in staan; kies in plaats daarvan de variabelen die je belangrijk vindt.

Zowel host als hostaddr weglaten kiest een Unix-domeinsocket in plaats van een netwerkadres. Een psql-aanroep zonder -h kan dus lokaal slagen, of falen met een socketfout, zonder ooit de route aan te raken die de GUI gebruikt.

Stuur dezelfde parameters met de hand

Met de waarden van de GUI in de hand, geef ze expliciet door en sla het opstartbestand over dat overschrijvingen kan toevoegen. De verbindingsreeks hieronder is illustratief: vervang het eindpunt, de poort, de database en de rol door de waarden die je beheerder heeft goedgekeurd, en houd de vertrouwensconfiguratie die al werkt.

psql -X "host=db.internal.example port=6432 dbname=orders user=report_ro sslmode=verify-full connect_timeout=5"

Drie details in die opdracht zijn bewust. -X onderdrukt het opstartbestand van psql, hoewel het de omgeving van libpq of een dienstdefinitie niet onderdrukt. connect_timeout=5 voorkomt dat een zwart-gat-route de terminal minutenlang laat hangen. sslmode=verify-full houdt certificaat- en hostnaamcontroles aan, wat precies het deel is dat mensen uitzetten wanneer er een TLS-fout verschijnt.

Als het goedgekeurde eindpunt achter een pooler zit, kunnen poort 6432 en poort 5432 dezelfde gegevens bereiken via verschillende serveridentiteiten, en kan de verificatie mislukken op de naam van de pooler in plaats van die van de database. Corrigeer de naam in de verbindingsreeks in plaats van de modus te verzwakken.

Laat het foutbericht de volgende stap kiezen

De fouttekst zegt hoe ver de poging kwam, en dat wint van elke gok over de tunnel. Een naam die niet oplost faalt voordat er een socket bestaat, een time-out betekent dat de route of een firewall pakketten heeft laten vallen, een weigering betekent dat iets antwoordde en weigerde, en een authenticatiefout betekent dat het netwerk al werkte.

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

Vergelijk de uitvoer van \conninfo met de live sessie van de GUI: dezelfde host, dezelfde poort, dezelfde rol, dezelfde TLS-status. Als die vier overeenkomen, heeft de VPN niets meer uit te leggen. Tot ze overeenkomen is elke extra tunnelwijziging een gok over een verbinding die de terminal nooit heeft gemaakt.

Gerelateerde artikelen