直接答案:PostgreSQL 远程连接失败要先按错误文本分层:超时通常在路由、安全组或防火墙;connection refused 多为地址/端口没有监听;no pg_hba.conf entry 表示已到数据库但没有匹配允许规则;密码错误则进入角色与认证方法。要同时配置 listen_addresses 和 pg_hba.conf,但只允许明确客户端 CIDR,优先 SCRAM 与 TLS;不要把 listen_addresses='*'、5432 全网开放和 trust 组合。
本文适合自建 PostgreSQL 单机或容器。托管数据库还可能有白名单、私网、代理端点和证书要求,应以平台控制台和官方端点为准。
本文按 2026 年 9 月可查的官方文档核对。示例命令以只读取证为主;凡涉及删除、覆盖、重启、权限、网络或数据库参数的动作,都应先确认操作对象、备份、维护窗口和带外恢复入口。不同发行版与软件版本的路径可能不同,必须先查询实际配置再改。
先用证据判断故障在哪一层
| 现象或检查点 | 它能说明什么 | 直接证据 | 不要误判为 |
|---|---|---|---|
| 连接超时 | 数据包未到或返回路径受阻 | 客户端探测、安全组与防火墙日志 | 数据库密码错 |
| connection refused | 目标IP可达但端口无监听或被主动拒绝 | ss、服务状态与容器映射 | pg_hba拒绝 |
| no pg_hba.conf entry | TCP已到PostgreSQL但规则未匹配 | 服务器日志、客户端IP与HBA顺序 | 端口未开放 |
| password authentication failed | 角色、密码、数据库或认证方法问题 | 角色LOGIN、SCRAM与日志 | DNS故障 |
| SSL error/certificate verify failed | TLS模式、CA或主机名验证问题 | sslmode、证书链与端点名称 | HBA CIDR |
这张表的用法不是“看到一个关键词就改一个参数”,而是把客户端、DNS或边缘、Web 代理、应用、数据层依次分开。至少保留故障时间、完整 URL、状态码、关键响应头、同一时刻的服务日志和一份正常样本。只有时间能够对齐,才能判断两个现象是否属于同一次故障。
六步排查与修复顺序
1. 记录完整错误与连接目标
保存客户端时间、主机名、解析出的 IP、端口、数据库、用户名、sslmode 和错误全文,但不记录明文密码。确认连接串没有指向旧 IP、IPv6、只读副本或错误容器。
2. 先验证 TCP 路径
从真实客户端测试 5432 TCP,并在服务器查安全组、系统防火墙和日志。不要用 ping 成功替代端口验证;也不要为测试把 5432 永久向全网开放。
3. 确认PostgreSQL监听地址
在数据库主机用 ss 和 SHOW listen_addresses 查看实际监听。参数变更需要重启而非只 reload;容器还要核对宿主端口发布和应用是否连容器网络名。
4. 按顺序检查 pg_hba.conf
HBA 使用第一条匹配规则,没有回退。用 SHOW hba_file 找实际文件,用 pg_hba_file_rules 检查解析错误和顺序;客户端地址应是数据库看到的 NAT 后地址,不一定是用户电脑私网地址。
5. 核对角色、数据库与TLS
确认角色有 LOGIN 和目标数据库 CONNECT 权限,密码格式与客户端支持 SCRAM。公网或不可信网络应使用 hostssl、服务器证书和客户端 verify-full,证书主机名应匹配连接端点。
6. 最小放行并做负例验收
添加精确 CIDR/用户/数据库规则,reload HBA 后从允许客户端连接并执行只读查询;再从未授权来源验证仍被拒绝。记录日志中的 client_addr、user 和 SSL 信息,监控暴力尝试。
可复制的只读取证命令
以下命令中的域名、服务名、路径和时间范围要替换为自己的真实值。先执行查询命令并保存原始输出;不要把“命令能运行”误当成“业务已恢复”。
text
getent ahosts db.your-domain.tld
nc -vz db.your-domain.tld 5432
ss -lntp | grep ':5432'
sudo -u postgres psql -Atc "SHOW listen_addresses; SHOW port; SHOW hba_file;"
sudo -u postgres psql -x -c "SELECT line_number,type,database,user_name,address,auth_method,error FROM pg_hba_file_rules ORDER BY line_number;"
getent ahosts db.your-domain.tld:确认客户端解析到的IPv4/IPv6目标nc -vz db.your-domain.tld 5432:从真实客户端测试TCP端口;成功不代表认证通过ss -lntp | grep ':5432':在服务器确认监听地址和进程sudo -u postgres psql -Atc "SHOW listen_addresses; SHOW port; SHOW hba_file;":读取实际运行参数和HBA文件路径sudo -u postgres psql -x -c "SELECT line_number,type,database,user_name,address,auth_method,error FROM pg_hba_file_rules ORDER BY line_number;":检查HBA顺序和解析错误,不显示密码
如命令输出包含公网 IP、用户名、Cookie、令牌、数据库连接串或客户数据,分享工单前先脱敏。对比时保留时间戳、时区和命令本身,否则后来无法复现同一观察条件。
五个最容易扩大故障的误区
- 5432向0.0.0.0/0开放:数据库暴露面急剧扩大,应使用精确来源、私网或隧道。
- 在pg_hba使用trust:连接者可冒充数据库用户,不能用于不可信网络。
- 只改listen_addresses:服务监听了但HBA和防火墙仍可拒绝;反之亦然。
- 把规则加在后面不看顺序:HBA第一条匹配生效,前面的reject或其他认证方法会先命中。
- 用IP连接却要求verify-full:证书通常签给主机名,IP与SAN不匹配会验证失败。
变更、回滚与数据边界
保存 postgresql.conf、pg_hba.conf、当前参数和防火墙规则。若新增监听或HBA导致异常登录、扫描或应用失败,恢复原文件/规则,reload HBA;listen_addresses 回滚需要维护窗口重启。不要用删除日志掩盖失败尝试。任何凭据变更要同步应用秘密并保留受控旧连接窗口。
如果只能先恢复服务、还不能确认根因,应把措施标记为“临时缓解”,例如限流、摘除单节点、切回上一配置或临时绕过一层代理。恢复后仍要在受控环境复现原因,并验证同类故障不会在下一次重启、发布或高峰重新出现。
统一验收清单
- [ ] 客户端连接目标与DNS结果正确
- [ ] TCP路径仅对授权来源开放
- [ ] PostgreSQL监听地址符合设计
- [ ] pg_hba_file_rules无解析错误
- [ ] 规则顺序、用户、数据库与CIDR精确
- [ ] 使用SCRAM或符合要求的安全认证
- [ ] TLS主机名与CA验证通过
- [ ] 未授权来源负例仍被拒绝并有日志
验收必须同时覆盖机器内部和真实外部路径。首页返回 200 不能证明上传、长连接、登录、数据库写入或移动端都正常;同样,控制台显示“运行中”也不能证明应用已能处理请求。至少选一个正常请求、一个边界请求和一个失败请求,记录预期与实际结果。
相关内容与隔离测试入口
建议先阅读云服务器端口不通、安全组和系统防火墙、API服务器搭建,把本问题放回完整请求链路。若生产环境不适合直接试验,可查看美国弹性云服务器的当前规格与库存,搭建与生产隔离的复现环境;测试机不能替代生产备份,价格、库存和可选配置以实时产品页为准。
常见问题
listen_addresses='*' 是否等于允许所有人?
它只控制监听接口,HBA和网络规则仍决定访问;但暴露范围会扩大,应按需要绑定私网地址。
改 pg_hba.conf 需要重启吗?
多数Unix系统 reload 即可重新读取;listen_addresses 等启动参数需要重启。Windows行为有差异,以官方文档和日志为准。
为什么HBA写了本机IP仍不匹配?
数据库看到的可能是NAT、容器网关或代理地址。查看服务器日志/client_addr,按真实来源设计规则。
可以用SSH隧道代替开放5432吗?
适合少量管理访问,可减少公网暴露;生产应用还要考虑可用性、密钥、监控和连接池,不应临时隧道化长期依赖。
连接成功就代表安全了吗?
不代表。还需最小角色权限、TLS验证、日志、补丁、备份和暴力尝试监控。