PostgreSQL 报 no pg_hba.conf entry?认证配置 pg_hba.conf 一次讲透
环境:PostgreSQL 16--18 通用 · 机制各版本一致 · 附生产模板
perl
FATAL: no pg_hba.conf entry for host "192.168.1.23", user "app", database "postgres"
先说结论:这个报错和密码对不对没有关系------PostgreSQL 根本没打算让你进门。守门的那个文件,就是 pg_hba.conf。
它是数据库的第一道门,管三件事:谁能连、从哪连、怎么证明是自己。这篇把它的字段格式、匹配顺序、认证方法、生效机制一次讲透,最后给一份可以直接抄的生产模板。以 PostgreSQL 16--18 为例,机制各版本一致。
一、它在哪,管什么
文件在数据目录里,initdb 初始化时自动生成:
ini
SHOW hba_file;
想放到别的位置,改 hba_file 参数(改它要重启)。
先划清管辖边界,很多人连不上时在这三个机制里来回打转:
- 网络层 :
listen_addresses(进程听哪个网卡)+ 防火墙/安全组------决定「包能不能到门口」; - 认证层 :
pg_hba.conf------决定「到了门口放不放行、怎么核验身份」; - 权限层:角色与 GRANT------决定「进门之后能干什么」。
pg_hba.conf 只管中间那层。三层各有各的报错长相,第六节给对照表。
二、一条规则,五段式
sql
# TYPE DATABASE USER ADDRESS METHOD
host all all 192.168.1.0/24 scram-sha-256
TYPE :连接类型。local 匹配 Unix 域套接字(本机 psql 默认走它),host 匹配 TCP/IP(含 SSL 与非 SSL);要按是否加密再细分,用 hostssl / hostnossl。
DATABASE :all(全部)、具体库名(逗号分隔可写多个)、sameuser(库名=用户名)、samerole(角色成员)、replication(物理复制专用,见坑 7)、/ 开头的正则、@文件(从文件读列表)。
USER :all、具体用户、+组名(匹配该角色的直接和间接成员)、正则、@文件。
ADDRESS :客户端来源,两种等价写法------CIDR 一段式(192.168.1.0/24),或 IP+掩码两列式(192.168.1.0 255.255.255.0)。单主机是 /32;0.0.0.0/0 匹配全部 IPv4;还有 all / samehost / samenet 三个关键字。local 行没有这一段。
METHOD:认证方法,下一节单独讲。
顺带 :@文件、正则、逗号列表这些写法,在规则多的库上比手写十几行 all 好维护得多------规则是给人读的,不是给机器读的。
三、第一匹配原则:顺序比规则本身更重要
整个文件最容易被低估的一条性质,官方文档写得干脆:每条连接尝试自上而下 扫描,第一条 TYPE、库、用户、地址都匹配的规则生效;没有「回落」------选中一条之后认证失败,后面的规则不会再被考虑;一条都不匹配,直接拒绝。
两个直接推论:
- 具体规则在前,宽泛规则在后。 官方示例就是「127.0.0.1/32 用 trust、大网段用密码」的排法------窄的先匹配,宽的兜后面。
reject是合法的卡口。 先用一行 reject 拒掉某个具体 IP,再放行它所在的网段,就能实现「网段放行、但排除一台」。
经典翻车现场:
错误顺序
css
host all all 0.0.0.0/0 md5
host all all 192.168.1.0/24 scram-sha-256 ← 永远轮不到
第一行匹配一切来源,第二行永远不会被执行------它不是备胎,门禁没有备胎。
python
# 正确顺序:窄在前,宽在后
host all all 192.168.1.0/24 scram-sha-256
host all all 0.0.0.0/0 md5
反过来同理:把 trust 的宽规则写在前面的任何位置,都等于把那之后的全部规则变成注释。
四、认证方法怎么选
| 方法 | 行为 | 适用 |
|---|---|---|
trust |
无条件放行,不问密码 | 仅本机调试;生产禁用 |
reject |
无条件拒绝 | 显式卡口、收尾兜底 |
scram-sha-256 |
SCRAM 挑战应答校验密码 | 首选;PG 14 起密码默认加密格式 |
md5 |
按密码存储格式自动走 SCRAM 或 MD5 | 只为兼容老客户端保留 |
password |
明文传输密码 | 不可信网络禁用 |
peer |
核对操作系统用户名(仅 local) | 本机运维常用 |
cert / ldap / gss / sspi |
外部认证体系 | 有对应基础设施时 |
md5 别再选了:官方已明确 MD5 密码支持会在未来版本移除,PG 19 起对 MD5 密码登录直接告警。还在用 md5 行的库,趁早把密码重存成 SCRAM(见坑 6,直接改方法会把老用户锁在门外)。
五、改完怎么生效:reload 三式 + 一个 Windows 特例
文件的读取时机:启动时 ,以及主进程收到 SIGHUP 信号时。所以改完文件要触发一次重读,三种方式任选:
csharp
pg_ctl reload # 命令行
SELECT pg_reload_conf(); -- psql 里一行 SQL
kill -HUP <postmaster主进程PID> # 信号直接给
reload 不中断现有连接,只有后续新连接按新规则走------这就是 pg_hba.conf 改动不需要 restart 的原因(对比:listen_addresses 是 postmaster 级参数,必须 restart)。
Windows 特例 :官方文档明说,Windows 上 pg_hba.conf 的改动会立即作用于后续新连接,不需要手动 reload。Windows 装机用户常以为「改配置必须重启服务」,其实是平台差异。
上线前先查再放流量------系统视图 pg_hba_file_rules 就是给预检用的,error 列非空即有问题行:
vbnet
SELECT line_number, type, database, user_name, error
FROM pg_hba_file_rules
WHERE error IS NOT NULL;
规则条数多的库,PG 16 起支持 include / include_dir 拆文件管理,按文件名顺序合并进主文件------按业务分文件,比一整个大文件好审得多。
六、远程连不上:先分层,再动手
「连不上」是三种完全不同的病,报错长相就是分诊台:
| 报错 | 卡在哪层 | 查什么 |
|---|---|---|
| connection timed out / refused | 网络层,包没到门口 | listen_addresses(默认只听 localhost,改它必须 restart)→ 防火墙 → 云安全组 |
| no pg_hba.conf entry | 认证层,到了门没放行 | 规则是否匹配:顺序、地址段、库名、用户名 → 改完 reload |
| password authentication failed | 认证层,放行了但核验没过 | 密码本身,或方法与密码存储格式不匹配(坑 6) |
见过太多人拿着 no pg_hba.conf entry 的报错去反复改防火墙,也见过反过来拿着 timeout 去改 pg_hba------先看报错分层,再动手,一步都不浪费。
七、8 个生产坑
- 顺序坑:宽规则写在窄规则前面,第一匹配、无回落,窄规则永远不生效。
- 裸奔坑 :
0.0.0.0/0+trust上生产等于整库开门------任何能路由到这台机器的人都能以任意用户身份进入。 - 生效坑:改完不 reload 等于没改(Windows 除外,改动立即生效)。
- 层级坑 :只盯 pg_hba,漏了
listen_addresses(要 restart 才生效)和防火墙/云安全组------三层各管一段,报错长相不同,先分层。 - IPv6 坑 :只写
127.0.0.1/32,本机走::1的连接照样被拒。补一行::1/128,或地址列写主机名localhost(可同时覆盖 v4/v6)。 - 存储格式坑 :把方法改成
scram-sha-256后,密码仍以 MD5 旧格式存储的用户会立即登录失败------要给这些用户重设一次密码 ,让它以 SCRAM 格式重新存储。反方向兼容:存储已是 SCRAM、方法写md5,会自动按 SCRAM 校验,不受影响。 - 复制坑 :
replication只匹配物理复制连接;逻辑复制按数据库名走普通规则。流复制起不来、却只写了普通库规则,先查这一行。 - DNS 坑:地址写主机名,每次连接要做反向+正向两次解析,DNS 慢或不规范会直接拖累连接建立------生产环境建议一律写 CIDR。
八、一份可以直接抄的生产模板
python
# 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 all all 10.0.1.0/24 scram-sha-256
# 物理复制专用:单独用户 + 单主机
host replication replicator 10.0.1.15/32 scram-sha-256
# 收尾:显式拒绝其余全部(无匹配本就拒绝,写出来是给人看的)
host all all 0.0.0.0/0 reject
三个要点:窄前宽后;复制单独一行单独用户;结尾显式 reject 让拒绝意图可见。
最后一个容易忽略的配合关系:pg_hba 管「能不能进门」,进门后能连哪个库还要看 CONNECT 权限。按人限库,用 GRANT/REVOKE CONNECT 比往 pg_hba 里堆规则好维护------这也是官方的建议。
小结
pg_hba.conf 的心智模型一句话:一张自上而下、第一条匹配就定终身的门禁表。顺序即语义,reload 才生效(Windows 立即),连不上先分层。
后面会继续更 pg_dump 备份恢复、慢 SQL 优化、Patroni 高可用这些实战,有认证配置问题可以评论区聊。
参考:PostgreSQL 官方文档 20.1 The pg_hba.conf File --- postgresql.org/docs/current/auth-pg-hba-conf.html
关键词:pg_hba.conf、PostgreSQL认证、no pg_hba.conf entry、scram-sha-256、PostgreSQL远程连接