PostgreSQL远程管理:通过SSH隧道连接
需要在自己电脑上查看服务器里的 PostgreSQL,可以通过 SSH 转发连接。本例适用于Ubuntu 24.04、PostgreSQL 16,且 SSH 与数据库位于同一台服务器:数据库保留本机监听,无需把 5432 放到公网。
先准备可用的 SSH 登录资料、数据库名和数据库角色密码。下文的 serveradmin是 Linux 账号,appuser是数据库角色,appdb是数据库名;都要换成自己的实际值。尚未安装数据库时,先看PostgreSQL 安装教程。
先在服务器本机验证数据库连接
通过SSH 登录服务器,检查 5432 的监听,再进入管理员会话。已自定义端口或管理员认证方式时,使用现有的有效连接资料,不要为登录临时改成免密认证:
sudo ss -lntp 'sport = :5432'
sudo -u postgres psql -X -p 5432 -d postgres
在 postgres=#提示符中执行:
SHOW server_version;
SHOW port;
SHOW listen_addresses;
SHOW hba_file;
本例需要能通过 127.0.0.1:5432连接数据库;listen_addresses=localhost即可,不需要改为 *。如果当前只启用了 Unix 套接字,先由管理员安排本机 TCP 监听;修改监听地址需要重启数据库,不要在业务运行中贸然重启。
输入 \q退出 psql,在服务器的 Linux 命令行测试业务角色。密码在提示时输入,不放进命令或截图。已有严格 TLS 校验时,改用下文的 verify-full 写法,并把端口改为 5432;不要降低校验级别。
psql -X -h 127.0.0.1 -p 5432 -U appuser -d appdb -W
能登录后输入 \q退出。本机这一步失败,先处理数据库认证;在电脑上反复建隧道不会解决它。数据库密码与 Linux 登录密码分别设置,不能混用。
回到自己的电脑建立隧道
在电脑的 PowerShell、终端或其他已安装 OpenSSH 客户端的命令行执行下面一整行。203.0.113.10是示例地址,必须替换。首次连接先核对 SSH 主机指纹,非默认 SSH 端口将 -p 22改为实际值:
ssh -N -T -p 22 -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -L 127.0.0.1:15432:127.0.0.1:5432 serveradmin@203.0.113.10
认证成功后,窗口没有返回命令提示符通常是正常现象,保留它。前一个 127.0.0.1:15432是你电脑上的入口,后一个 127.0.0.1:5432是服务器本机的数据库。不要在服务器终端里执行这一条,也不要把本地绑定地址改成 0.0.0.0。
ExitOnForwardFailure能让本地端口绑定失败时及时退出,但不能证明远端数据库已经可用,仍需下一步实际登录。
数据库工具连接本地15432端口
新开一个本地窗口,使用已安装的 PostgreSQL 客户端。没有另行规定 TLS 校验参数时,可用:
psql -X -h 127.0.0.1 -p 15432 -U appuser -d appdb -W
如果数据库要求 verify-full,直接拿 127.0.0.1 校验证书可能出现名称不匹配。psql 使用 libpq,可把连接地址与证书名称分别指定:
psql -X -W "host=db.example.com hostaddr=127.0.0.1 port=15432 dbname=appdb user=appuser sslmode=verify-full sslrootcert=/absolute/path/root-ca.crt"
hostaddr指向本地隧道,host保留证书中的数据库名称。将示例域名换成证书匹配的真实名称,CA 路径换成管理员提供的可信证书文件路径;已有的客户端证书等要求也要保留。
图形化工具可参考下表。严格校验证书时,工具须支持分别指定连接地址和证书名称;不支持就换用支持的客户端,不能关闭名称或证书校验。已经通过外部 SSH 窗口建立隧道,就不要再建第二条。
| 字段 | 本例填写 |
|---|---|
| 连接地址、端口 | 127.0.0.1、15432;严格 TLS 另填证书名称 |
| 数据库、用户名 | 实际数据库名、数据库角色;不是 Linux 账号 |
| 密码 | 该数据库角色的密码 |
| SSL | 沿用现有 TLS 与证书校验要求;SSH 隧道不替代它们 |
连接后执行一条只读查询,确认不是误连到电脑上另一套数据库:
SELECT current_database(), current_user,
inet_client_addr(), inet_server_addr(), inet_server_port();
本例应返回实际数据库和角色,服务端地址为 127.0.0.1、端口为 5432。返回的服务端端口不是 15432,这正是转发后的结果。
密码明明正确,为什么仍被拒绝?
服务器上的 sudo -u postgres psql通常走 Unix 套接字,可能使用 peer核对系统身份;隧道到达数据库时是本机 TCP 连接,按是否使用 TLS 匹配 host、hostssl等规则。前一种能进,并不代表业务角色密码正确。
由数据库管理员在 psql 中查看规则及语法错误:
SELECT rule_number, file_name, line_number, type,
database, user_name, address, auth_method, error
FROM pg_hba_file_rules
ORDER BY rule_number NULLS LAST, file_name, line_number;
规则从上往下匹配,命中后认证失败不会继续尝试后面的规则。若现有策略确实缺少这组访问权限,先备份 SHOW hba_file返回的文件,再由管理员在合适位置加入精确规则。下面的 host示例仅适用于现有策略允许不使用 TLS 的本机 TCP 连接:
host appdb appuser 127.0.0.1/32 scram-sha-256
已有强制 TLS 策略时沿用 hostssl,保留原有证书等限制,不能用上述 host规则覆盖或绕过它。不要机械加到末尾或全部替换。角色必须允许 LOGIN、拥有该库的 CONNECT 权限,并已设置可用于 SCRAM 的密码。已在使用的业务密码不要为排错随意重置。
文件中 error列均为空后,管理员执行:
SELECT pg_reload_conf();
该函数返回 true 只表示重载信号已发出;规则视图显示的也只是磁盘文件内容。还要查看当前数据库日志,并新建一次连接验证,不能用旧会话仍然在线判断修改成功。
| 报错 | 检查位置 |
|---|---|
| Address already in use | 电脑上的 15432 被占用。换一个空闲端口,SSH 命令和数据库工具同步修改。 |
| Connection refused | 查看 SSH 窗口的转发错误,并核对远端 PostgreSQL 是否在正确的本机端口监听。 |
| administratively prohibited | SSH 服务的转发权限或 PermitOpen 限制,不是数据库密码问题;由管理员核对授权范围。 |
| Peer authentication failed | 核对是否遗漏 -h 127.0.0.1,误走了本机 Unix 套接字。 |
| password authentication failed | 核对数据库角色、密码和第一条匹配的 HBA 规则;不要改成 trust 规避。 |
使用完先关闭数据库工具,再回到 SSH 隧道窗口按 Ctrl+C 结束转发。电脑休眠或网络切换后,应重新建立隧道,再新建数据库连接。