Skip to content

pg_hba.conf

概述

pg_hba.conf 文件是 PostgreSQL 数据库系统中控制客户端身份验证的核心配置文件。HBA 代表 "Host-Based Authentication"(基于主机的身份验证),该文件决定了哪些用户可以从哪些主机连接到哪些数据库,以及使用什么样的身份验证方法。

pg_hba.conf 文件是 PostgreSQL 安全体系的第一道防线,正确配置这个文件对于数据库安全至关重要。

文件位置和管理

文件位置

bash
# 默认位置
$PGDATA/pg_hba.conf

# 可通过参数自定义位置
hba_file = '/custom/path/to/pg_hba.conf'

重新加载配置

当修改 pg_hba.conf 文件后,需要重新加载配置才能生效:

bash
# 使用 pg_ctl 重新加载配置
pg_ctl reload -D /var/lib/postgresql/data
sql
-- 在 PostgreSQL 中执行
SELECT pg_reload_conf();
bash
# 发送 SIGHUP 信号给 postmaster 进程
kill -HUP <postmaster_pid>

在 Windows 系统上,pg_hba.conf 文件的更改会立即应用于后续的新连接。

配置验证

可以使用系统视图来检查配置文件的正确性:

sql
-- 查看 pg_hba.conf 规则和潜在错误
SELECT line_number, type, database, user_name, address, netmask, auth_method, options, error
FROM pg_hba_file_rules
WHERE error IS NOT NULL;

文件格式和语法

基本语法规则

ini
# 这是注释行,以 # 开头
# 空行会被忽略

# 基本格式:TYPE DATABASE USER ADDRESS METHOD [OPTIONS]
local   all         all                     trust
host    all         all     127.0.0.1/32    md5

# 行延续:使用反斜杠可以将记录延续到下一行
host    mydb        myuser  192.168.1.0/24  \
                                            scram-sha-256

# 引号字段:包含空格的字段可以用双引号引起来
host    "my database"   "my user"   127.0.0.1/32   md5

记录类型

pg_hba.conf 支持以下几种记录类型:

连接类型详解

1. local - Unix 域套接字连接

应用场景:本地应用程序直接连接到数据库服务器

ini
# 语法格式
local   database  user  auth-method [auth-options]

# 示例:允许本地所有用户通过 Unix 套接字连接
local   all       all   trust

# 示例:本地连接需要密码验证
local   all       all   md5

# 示例:特定数据库的本地连接配置
local   myapp     myuser    scram-sha-256
local   postgres  postgres  peer

使用场景分析

  • 开发环境:使用 trust 方便开发调试
  • 生产环境:使用 peermd5 确保安全性
  • 备份脚本:使用 peer 允许系统用户执行备份

2. host - TCP/IP 连接

应用场景:远程客户端或应用程序通过网络连接

ini
# 语法格式
host    database  user  address     auth-method  [auth-options]
host    database  user  IP-address  IP-mask      auth-method  [auth-options]

# 示例:允许本地回环连接
host    all       all   127.0.0.1/32            trust
host    all       all   ::1/128                 trust

# 示例:允许内网连接
host    all       all   192.168.1.0/24          md5
host    all       all   10.0.0.0/8              scram-sha-256

# 示例:允许特定主机连接
host    myapp     appuser   192.168.1.100/32    scram-sha-256

3. hostssl - SSL 加密连接

应用场景:需要加密传输的安全连接

ini
# 示例:强制使用 SSL 连接
hostssl all       all   0.0.0.0/0               scram-sha-256

# 示例:内网可以不加密,外网必须加密
host    all       all   192.168.0.0/16          md5
hostssl all       all   0.0.0.0/0               scram-sha-256

# 示例:结合客户端证书验证
hostssl all       all   0.0.0.0/0               cert clientcert=verify-full

使用 hostssl 前必须先配置 SSL,设置 `ssl = on` 参数并准备好证书文件。

4. hostnossl - 非 SSL 连接

应用场景:明确禁止 SSL 连接的场景

ini
# 示例:内网连接不使用 SSL(性能考虑)
hostnossl all     all   192.168.0.0/16          md5

# 示例:禁止不安全的外网连接
hostnossl all     all   0.0.0.0/0               reject

地址匹配规则

IP 地址范围

ini
# IPv4 地址示例
host    all    all    172.20.143.89/32       md5    # 单个主机
host    all    all    172.20.143.0/24        md5    # 小型网络(256个地址)
host    all    all    10.6.0.0/16            md5    # 大型网络(65536个地址)
host    all    all    0.0.0.0/0              md5    # 所有 IPv4 地址

# IPv6 地址示例
host    all    all    ::1/128                md5    # IPv6 回环地址
host    all    all    fe80::7a31:c1ff:0000:0000/96  md5    # IPv6 网络
host    all    all    ::0/0                  md5    # 所有 IPv6 地址

特殊关键字

ini
# all:匹配任何 IP 地址
host    all    all    all                    md5

# samehost:匹配服务器自身的任何 IP 地址
host    all    all    samehost               trust

# samenet:匹配服务器直接连接的任何子网
host    all    all    samenet                md5

主机名匹配

ini
# 主机名匹配(需要 DNS 解析)
host    all    all    database.example.com   md5

# 域名后缀匹配
host    all    all    .example.com           md5    # 匹配 *.example.com

# 注意:主机名匹配会进行双向 DNS 查找
# 1. 客户端 IP -> 主机名(反向查找)
# 2. 主机名 -> IP 地址(正向查找)
# 只有两个方向都匹配才允许连接

主机名匹配可能较慢,建议在高并发环境中使用 IP 地址匹配,或配置本地 DNS 缓存。

数据库和用户匹配

数据库字段

ini
# 特殊值
local   all          all                     md5    # 匹配所有数据库
local   sameuser     all                     md5    # 数据库名与用户名相同
local   samerole     all                     md5    # 用户是同名角色的成员
local   replication  replicator              md5    # 物理复制连接

# 具体数据库
local   myapp        myuser                  md5    # 指定数据库
local   db1,db2      all                     md5    # 多个数据库

# 正则表达式匹配(以 / 开头)
local   "/^test.*"   all                     md5    # 匹配 test 开头的数据库
local   "/^db\d{2,4}$"  all                  md5    # 匹配 db + 2-4位数字

# 从文件读取数据库列表(以 @ 开头)
local   @/etc/postgresql/databases  all      md5

用户字段

ini
# 特殊值
host    all    all              127.0.0.1/32    md5    # 匹配所有用户

# 具体用户
host    all    alice            127.0.0.1/32    md5    # 指定用户
host    all    alice,bob        127.0.0.1/32    md5    # 多个用户

# 组/角色匹配(以 + 开头)
host    all    +admin           127.0.0.1/32    md5    # admin 组成员
host    all    +developers      127.0.0.1/32    md5    # developers 组成员

# 正则表达式匹配
host    all    "/^.*admin$"     127.0.0.1/32    md5    # 以 admin 结尾的用户

# 从文件读取用户列表
host    all    @/etc/postgresql/users  127.0.0.1/32    md5

身份验证方法

1. trust - 无条件信任

ini
# 语法
local   all    all                     trust
host    all    all    127.0.0.1/32     trust

# 使用场景
# ✓ 开发和测试环境
# ✓ 本地管理连接
# ✗ 生产环境(安全风险)

实际应用示例

ini
# 开发环境配置:方便开发人员本地调试
local   all    all                     trust
host    all    all    127.0.0.1/32     trust
host    all    all    ::1/128          trust

# 限制信任范围:只对本地连接使用 trust
local   all           postgres         trust    # 本地 postgres 用户
host    postgres      postgres   127.0.0.1/32  trust    # 本地管理连接
host    all           all        192.168.1.0/24 md5     # 网络连接需要密码

2. reject - 无条件拒绝

ini
# 语法
host    all    all    192.168.54.1/32    reject

# 使用场景:黑名单机制
host    all    all    10.0.0.100/32      reject    # 拒绝特定主机
host    test   all    0.0.0.0/0          reject    # 拒绝连接测试数据库
host    all    guest  0.0.0.0/0          reject    # 拒绝 guest 用户

3. scram-sha-256 - 强密码验证

ini
# 语法
host    all    all    0.0.0.0/0    scram-sha-256

# 推荐的生产环境配置
hostssl  all    all    0.0.0.0/0         scram-sha-256    # 外网连接
host     all    all    192.168.0.0/16    scram-sha-256    # 内网连接

密码设置示例

sql
-- 创建用户并设置 SCRAM-SHA-256 密码
CREATE USER myuser WITH ENCRYPTED PASSWORD 'secure_password';

-- 修改现有用户的密码加密方式
SET password_encryption = 'scram-sha-256';
ALTER USER myuser PASSWORD 'new_secure_password';

4. md5 - 兼容性密码验证

ini
# 语法
host    all    all    192.168.1.0/24    md5

# 兼容性配置:支持旧客户端
host    all    oldapp     192.168.1.100/32    md5              # 旧应用
host    all    all        192.168.1.0/24      scram-sha-256    # 新应用

5. peer - 操作系统用户验证

ini
# 语法(仅适用于 local 连接)
local   all    all    peer

# 实际应用
local   postgres    postgres    peer              # postgres 系统用户
local   all         all         peer map=mymap    # 使用用户映射

用户映射配置(pg_ident.conf):

ini
# MAPNAME       SYSTEM-USERNAME    PG-USERNAME
mymap           root               postgres
mymap           backup             postgres
mymap           john               john
mymap           jane               jane

6. ident - 远程身份验证

ini
# 语法
host    all    all    192.168.1.0/24    ident
host    all    all    192.168.1.0/24    ident map=mymap

7. cert - 客户端证书验证

ini
# 语法
hostssl    all    all    0.0.0.0/0    cert
hostssl    all    all    0.0.0.0/0    cert clientcert=verify-full

# 证书配置选项
hostssl    all    all    0.0.0.0/0    cert clientname=DN    # 使用完整 DN
hostssl    all    all    0.0.0.0/0    cert clientname=CN    # 使用 CN(默认)

实际配置示例

典型的生产环境配置

ini
# ===============================================
# PostgreSQL 生产环境 pg_hba.conf 配置示例
# ===============================================

# 1. 本地连接配置
# 允许 postgres 用户本地管理连接
local   all             postgres                     peer

# 应用程序本地连接需要密码
local   all             all                          scram-sha-256

# 2. 本地回环连接
# 本地应用程序通过 TCP 连接
host    all             all         127.0.0.1/32     scram-sha-256
host    all             all         ::1/128          scram-sha-256

# 3. 内网连接配置
# 应用服务器网段
host    myapp           appuser     192.168.10.0/24  scram-sha-256
host    myapp           readonly    192.168.10.0/24  scram-sha-256

# 管理网段
host    all             dba         192.168.100.0/24 scram-sha-256

# 4. 外网连接配置(仅 SSL)
# 拒绝所有非 SSL 外网连接
hostnossl all           all         0.0.0.0/0        reject

# 允许 SSL 加密的外网连接
hostssl   all           all         0.0.0.0/0        scram-sha-256

# 5. 复制连接配置
# 主从复制
host    replication     replicator  192.168.20.0/24  scram-sha-256
hostssl replication     replicator  0.0.0.0/0        cert

# 6. 特殊限制
# 拒绝特定的不安全主机
host    all             all         10.0.0.100/32    reject

# 测试数据库只允许内网访问
host    test_*          all         192.168.0.0/16   scram-sha-256
host    test_*          all         0.0.0.0/0        reject

开发环境配置

ini
# ===============================================
# PostgreSQL 开发环境 pg_hba.conf 配置示例
# ===============================================

# 1. 本地开发便利配置
# 本地连接无需密码(开发便利)
local   all             all                          trust

# 本地 TCP 连接无需密码
host    all             all         127.0.0.1/32     trust
host    all             all         ::1/128          trust

# 2. 开发团队网段
# 允许开发团队网段连接
host    all             all         192.168.1.0/24   md5

# 3. 测试数据库特殊配置
# 测试数据库允许匿名连接
host    test_db         testuser    192.168.1.0/24   trust

# 4. 外网访问限制
# 开发环境也要限制外网访问
host    all             all         0.0.0.0/0        reject

高安全性配置

ini
# ===============================================
# PostgreSQL 高安全性 pg_hba.conf 配置示例
# ===============================================

# 1. 严格的本地访问控制
# 只允许 postgres 用户本地连接
local   postgres        postgres                     peer

# 其他本地用户必须密码验证
local   all             all                          scram-sha-256

# 2. 强制 SSL 连接
# 拒绝所有非 SSL 连接
hostnossl all           all         0.0.0.0/0        reject

# 3. 客户端证书验证
# 管理员连接需要客户端证书
hostssl all             admin       0.0.0.0/0        cert clientcert=verify-full

# 应用程序连接使用强密码
hostssl myapp           appuser     192.168.10.0/24  scram-sha-256

# 4. 严格的网络隔离
# 只允许特定网段访问
hostssl all             all         192.168.10.0/24  scram-sha-256
hostssl all             all         192.168.100.0/24 cert

# 明确拒绝其他所有连接
host    all             all         0.0.0.0/0        reject

常见配置错误和解决方案

错误 1:连接被拒绝

错误信息

FATAL: no pg_hba.conf entry for host "192.168.1.100", user "myuser", database "mydb"

原因分析

  1. 没有匹配的 pg_hba.conf 条目
  2. 记录顺序不正确
  3. 地址范围配置错误

解决方案

ini
# 检查并添加正确的记录
host    mydb    myuser    192.168.1.100/32    scram-sha-256

# 或者使用更宽泛的网段
host    mydb    myuser    192.168.1.0/24      scram-sha-256

错误 2:SSL 连接问题

错误信息

FATAL: SSL connection is required

解决方案

ini
# 确保 SSL 已启用
ssl = on

# 配置 SSL 连接
hostssl    all    all    0.0.0.0/0    scram-sha-256

# 或者允许非 SSL 连接(不推荐)
host       all    all    192.168.1.0/24    scram-sha-256

错误 3:认证失败

错误信息

FATAL: password authentication failed for user "myuser"

检查步骤

sql
-- 1. 检查用户是否存在
SELECT usename, usecreatedb, usesuper
FROM pg_user
WHERE usename = 'myuser';

-- 2. 检查密码加密方式
SELECT rolname, rolpassword
FROM pg_authid
WHERE rolname = 'myuser';

-- 3. 重置密码
ALTER USER myuser PASSWORD 'new_password';

性能优化和最佳实践

1. 记录顺序优化

ini
# ✓ 正确:从具体到一般
host    myapp    appuser    192.168.10.100/32    trust         # 最具体
host    myapp    appuser    192.168.10.0/24      scram-sha-256 # 较具体
host    all      all        192.168.0.0/16       md5           # 一般
host    all      all        0.0.0.0/0            reject        # 最一般

# ✗ 错误:一般的规则会阻止具体规则生效
host    all      all        0.0.0.0/0            reject        # 这条会阻止后续规则
host    myapp    appuser    192.168.10.100/32    trust         # 永远不会匹配

2. 性能考虑

ini
# ✓ 推荐:使用 IP 地址避免 DNS 查找
host    all    all    192.168.1.0/24    scram-sha-256

# ✗ 避免:主机名查找可能较慢
host    all    all    .example.com      scram-sha-256

# ✓ 推荐:限制连接范围
host    myapp  appuser  192.168.10.0/24  scram-sha-256  # 只允许应用网段

# ✗ 避免:过于宽泛的权限
host    all    all      0.0.0.0/0        trust          # 安全风险

3. 安全性最佳实践

WARNING

安全建议

  1. 最小权限原则:只授予必要的访问权限
  2. 强制加密:生产环境使用 SSL 连接
  3. 定期审查:定期检查和更新 pg_hba.conf 配置
  4. 监控访问:启用连接日志监控异常访问
ini
# 安全配置模板
# 1. 严格的本地访问
local   postgres    postgres    peer
local   all         all         scram-sha-256

# 2. 内网访问控制
host    myapp       appuser     192.168.10.0/24    scram-sha-256
host    monitoring  monitor     192.168.100.0/24   scram-sha-256

# 3. 强制外网 SSL
hostnossl all       all         0.0.0.0/0          reject
hostssl   all       all         0.0.0.0/0          scram-sha-256

# 4. 明确拒绝
host      all       all         0.0.0.0/0          reject

监控和调试

连接日志配置

sql
-- 启用连接日志
SET log_connections = on;
SET log_disconnections = on;
SET log_line_prefix = '%t [%p-%l] %q%u@%d ';

-- 查看连接日志
SHOW log_connections;
SHOW log_line_prefix;

实时监控连接

sql
-- 查看当前连接
SELECT
    pid,
    usename,
    application_name,
    client_addr,
    client_hostname,
    client_port,
    backend_start,
    state
FROM pg_stat_activity
WHERE state = 'active';

-- 查看连接统计
SELECT
    datname,
    usename,
    client_addr,
    count(*) as connection_count
FROM pg_stat_activity
GROUP BY datname, usename, client_addr
ORDER BY connection_count DESC;

配置验证脚本

bash
#!/bin/bash
# pg_hba_check.sh - 验证 pg_hba.conf 配置

echo "=== PostgreSQL pg_hba.conf 配置检查 ==="

# 1. 检查配置文件语法
echo "1. 检查配置文件语法..."
sudo -u postgres psql -c "SELECT * FROM pg_hba_file_rules WHERE error IS NOT NULL;"

# 2. 测试连接
echo "2. 测试本地连接..."
sudo -u postgres psql -c "\conninfo"

# 3. 检查 SSL 状态
echo "3. 检查 SSL 配置..."
sudo -u postgres psql -c "SHOW ssl;"

# 4. 查看当前连接
echo "4. 当前活动连接..."
sudo -u postgres psql -c "SELECT usename, client_addr, state FROM pg_stat_activity WHERE state = 'active';"

echo "=== 检查完成 ==="

总结

pg_hba.conf 文件是 PostgreSQL 安全架构的核心组件,正确配置这个文件需要:

  1. 理解业务需求:明确哪些用户需要从哪些地方访问哪些数据库
  2. 遵循安全原则:采用最小权限原则,优先使用强认证方法
  3. 考虑性能影响:避免不必要的 DNS 查找,合理排序规则
  4. 持续监控维护:定期审查配置,监控访问日志

通过合理配置 pg_hba.conf 文件,可以在保证数据库安全的同时,提供灵活便捷的访问控制机制。

建议在生产环境部署前,先在测试环境充分验证 pg_hba.conf 配置,确保所有预期的连接都能正常工作,同时阻止不当的访问尝试。