Appearance
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
方便开发调试 - 生产环境:使用
peer
或md5
确保安全性 - 备份脚本:使用
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"
原因分析:
- 没有匹配的 pg_hba.conf 条目
- 记录顺序不正确
- 地址范围配置错误
解决方案:
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
安全建议
- 最小权限原则:只授予必要的访问权限
- 强制加密:生产环境使用 SSL 连接
- 定期审查:定期检查和更新 pg_hba.conf 配置
- 监控访问:启用连接日志监控异常访问
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 安全架构的核心组件,正确配置这个文件需要:
- 理解业务需求:明确哪些用户需要从哪些地方访问哪些数据库
- 遵循安全原则:采用最小权限原则,优先使用强认证方法
- 考虑性能影响:避免不必要的 DNS 查找,合理排序规则
- 持续监控维护:定期审查配置,监控访问日志
通过合理配置 pg_hba.conf
文件,可以在保证数据库安全的同时,提供灵活便捷的访问控制机制。
建议在生产环境部署前,先在测试环境充分验证 pg_hba.conf 配置,确保所有预期的连接都能正常工作,同时阻止不当的访问尝试。