PostgreSQL在默认安装后只能通过localhost连接,很多刚接触的人会发现远程机器怎么都连不上,或者明明密码输对了却依然提示认证失败。这类问题几乎都不是数据库本身坏了,而是连接参数和认证规则没有配置到位。理解PostgreSQL的连接建立流程和认证机制,是排查这类问题的第一步,也是做安全加固的基础。

PostgreSQL连接是如何建立的
一次完整的连接要经过几个环节。客户端先根据目标地址和端口发起TCP请求,PostgreSQL的postmaster主进程在监听到请求后,会fork一个后端进程来服务这个连接,然后进入认证阶段。认证阶段会读取pg_hba.conf文件,根据客户端IP、数据库名、用户名逐条匹配规则,找到第一条命中的记录后,按该记录指定的认证方法进行校验。
监听地址由postgresql.conf中的listen_addresses参数控制,默认值是localhost,表示只监听本机回环地址。如果想允许外部连接,需要改成具体IP或者星号:
# postgresql.conf listen_addresses = '*' # 监听所有网卡 port = 5432 # 默认端口,可自定义 max_connections = 100 # 最大连接数,按需调整
改完后需要重启数据库才能生效,这一点和pg_hba.conf不同,后者用pg_ctl reload重新加载即可。另外别忘了防火墙层面也要放行5432端口,很多人的第一道坎其实是出在系统防火墙而不是PostgreSQL本身。
客户端连接时常用的参数包括主机、端口、用户名、数据库名,如果是编程语言驱动,一般还会有连接超时、SSL模式等选项。以libpq风格的连接串为例:
psql "host=192.168.1.100 port=5432 dbname=appdb user=appuser password=xxx sslmode=require connect_timeout=5"
pg_hba.conf认证方式详解与对比
pg_hba.conf是PostgreSQL访问控制的核心文件,每条记录的格式是:类型、数据库、用户、地址、认证方法。匹配是从上到下进行的,命中第一条就停止,所以规则顺序非常关键,把宽泛的规则放在前面会导致后面的严格规则形同虚设。
# TYPE DATABASE USER ADDRESS METHOD local all all peer host all all 127.0.0.1/32 scram-sha-256 host all all ::1/128 scram-sha-256 host appdb appuser 192.168.1.0/24 scram-sha-256 host all all 0.0.0.0/0 scram-sha-256
几种常见认证方法的原理和差异需要分清楚。trust表示完全信任,不做任何密码校验,只要网络能通就能连上,仅适合本机调试或受控的初始化场景,生产环境绝对不要用。password虽然要密码,但是明文传输,中间链路上密码可被直接截获,除非强制走SSL通道,否则不建议使用。md5是老牌的挑战应答式加密认证,密码不会明文传输,但md5算法本身已经不够安全,容易被离线碰撞破解。
从PostgreSQL 10开始推荐使用scram-sha-256,它基于SCRAM协议,安全强度远高于md5,并且能防范多种中间人攻击。要注意的是,认证方式必须和用户密码的存储格式匹配,密码的加密形式由password_encryption参数决定。如果用户的密码是按md5存的,而pg_hba.conf里配置了scram-sha-256,认证就会失败,这是升级迁移时最典型的坑。可以先在postgresql.conf中设置password_encryption = 'scram-sha-256',再执行ALTER USER ... WITH PASSWORD '...'让所有用户重置一遍密码。
还有两类针对特殊场景的方法。peer只用于local类型的本地连接,通过操作系统用户名做映射,要求数据库用户名和系统用户名一致,或者在pg_ident.conf里配置映射关系。cert基于客户端SSL证书认证,安全性最高,适合对安全要求严格的内部系统,但证书的签发和轮换维护成本也最高。reject用于显式拒绝某段地址,常放在规则末尾之前做黑名单处理。
| 认证方式 | 是否需要密码 | 传输安全 | 适用场景 |
|---|---|---|---|
| trust | 否 | 无 | 本机初始化调试 |
| password | 是 | 明文,需配合SSL | 基本不推荐 |
| md5 | 是 | 挑战应答,算法偏弱 | 旧版本兼容 |
| scram-sha-256 | 是 | 安全性高 | 10及以上版本首选 |
| cert | 证书 | 高 | 高安全内网或专线 |
常见踩坑场景与避坑建议
第一个高频坑是密码对了却报password authentication failed。排查思路是先确认客户端实际来源IP,因为经过NAT或代理后,服务端看到的地址可能不是客户端本机地址,导致命中的规则和预期不符。可以用ss -tnp | grep 5432在服务端查看连接来源,再对照pg_hba.conf逐条检查。其次是密码存储格式和认证方法不匹配的问题,上面已经提到,升级到scram-sha-256时务必让全量用户重设密码。
第二个坑是规则顺序写反。比如有人为了省事先写一条host all all 0.0.0.0/0 trust在最顶上,后面再写精细的规则,结果所有地址都命中第一条,等于把数据库裸奔在网络上。正确做法是把最具体的规则放在前面,宽泛的规则放在后面,最后可以用host all all 0.0.0.0/0 reject兜底拒绝。公网暴露时要格外谨慎,最好通过防火墙白名单、SSL强制(hostssl类型)加上scram-sha-256三重防护,有条件的话走SSH隧道或VPN,不要直接把5432端口暴露在公网。
第三个坑是连接数管理。应用侧使用连接池(如PgBouncer)时要注意pool_mode与认证的配合,尤其是transaction模式下某些认证特性表现不同。同时检查max_connections与实际业务并发的关系,连接数打满会报FATAL: sorry, too many clients already,此时除了调大参数,更合理的做法是引入连接池降低直连数量。
最后分享一个排查小技巧:修改pg_hba.conf后先执行pg_ctl reload,如果还是连不上,查看日志文件中每次连接失败都会打印命中的pg_hba.conf行号和失败原因,日志是定位认证问题最直接的信息来源。生产环境的密码不要写在脚本或配置文件里明文存放,可以借助.pgpass文件并严格控制文件权限为600,或者使用云平台的密钥管理服务来托管凭据。
PostgreSQL连接pg_hba.conf认证方式修改时间:2026-09-09 10:47:34