PostgreSQL 安全加固是数据库防护体系的关键环节,本文从访问控制、认证方式、传输加密、权限管理与审计日志五个维度,提供一套可直接复制的 PostgreSQL 安全加固配置方案,帮助企业抵御未授权访问、数据泄露与越权操作风险。
适用场景
- PostgreSQL 生产库上线前的安全基线配置
- 数据库被扫描爆破或发现未授权访问风险后的整改
- 等保测评中数据库安全审计与访问控制项加固
- 多租户或多人共库环境下的最小权限隔离
前置条件
- 已安装 PostgreSQL 的 Linux 服务器(本教程以 PostgreSQL 15 + Ubuntu 22.04 为例)
- 具备 postgres 系统用户或超级用户权限
- 修改配置后需重启或 reload PostgreSQL 生效
原理说明
PostgreSQL 的安全模型分为三层:pg_hba.conf 负责客户端认证(规定谁能连、用什么认证方式);角色权限体系控制登录后能做什么;SSL 加密保护传输中的数据。攻击者最常见的入侵路径是:数据库监听在公网 + 弱口令 + 使用已废弃的 md5/trust 认证。因此加固的核心是:收紧监听地址、强制 scram-sha-256 强认证、启用 SSL、按最小权限拆分角色、并开启审计日志记录所有 SQL 操作。
操作步骤
1. 收紧监听地址与端口
编辑 /etc/postgresql/15/main/postgresql.conf:
# 只监听本机回环地址(如有内网应用,改为内网 IP,切勿用 0.0.0.0)
listen_addresses = '127.0.0.1'
port = 5432
若业务必须允许远程访问,务必在云安全组/防火墙层面仅放行应用服务器 IP,并将监听地址限定为该内网 IP。
2. 强制 scram-sha-256 强认证
编辑 /etc/postgresql/15/main/pg_hba.conf,将认证方式统一改为 scram-sha-256:
# TYPE DATABASE USER ADDRESS METHOD
local all postgres peer
local all all scram-sha-256
host all all 127.0.0.1/32 scram-sha-256
host all all ::1/128 scram-sha-256
# 内网应用访问(按需,替换为实际网段)
host all app_user 10.0.0.0/8 scram-sha-256
将现有用户密码迁移到 scram 认证:
# 以 postgres 用户进入
sudo -u postgres psql
ALTER USER app_user WITH PASSWORD '强密码';
# 检查用户密码加密方式(应为 SCRAM-SHA-256)
SELECT usename, substring(passwd from 1 for 20) FROM pg_shadow;
pg_shadow 中 passwd 字段以 SCRAM-SHA-256$ 开头即表示已使用强认证。
3. 启用 SSL 加密传输
# 生成自签名证书(生产环境建议使用受信任 CA 签发的证书)
sudo openssl req -new -x509 -days 365 -nodes -text -out /etc/postgresql/15/main/server.crt -keyout /etc/postgresql/15/main/server.key -subj "/CN=db.example.com"
sudo chmod 600 /etc/postgresql/15/main/server.key
sudo chown postgres:postgres /etc/postgresql/15/main/server.key
# 在 postgresql.conf 中启用 SSL
ssl = on
ssl_cert_file = 'server.crt'
ssl_key_file = 'server.key'
同时将 pg_hba.conf 中的远程条目加 hostssl 前缀(仅允许 SSL 连接),并禁用非 SSL:
hostssl all app_user 10.0.0.0/8 scram-sha-256
4. 最小权限:拆分角色
sudo -u postgres psql
-- 创建只读账号
CREATE ROLE readonly LOGIN PASSWORD '只读密码';
GRANT CONNECT ON DATABASE appdb TO readonly;
GRANT USAGE ON SCHEMA public TO readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly;
-- 限制只读账号登录来源(pg_hba.conf 中单独指定)
-- hostssl appdb readonly 10.0.0.5/32 scram-sha-256
删除不再使用的超级用户角色,业务账号一律使用最小权限的非超级用户:
-- 检查超级用户
SELECT rolname FROM pg_roles WHERE rolsuper = true;
-- 回收权限示例
REVOKE ALL ON DATABASE appdb FROM PUBLIC;
5. 开启审计日志
编辑 postgresql.conf:
# 开启 SQL 语句日志(生产环境可只记 DDL/DDL 与失败登录)
log_statement = 'ddl' # none | ddl | mod | all
log_duration = on
log_connections = on
log_disconnections = on
log_min_duration_statement = 1000 # 记录超过 1 秒的慢 SQL
log_directory = 'log'
log_filename = 'postgresql-%a.log'
log_line_prefix = '%m [%p] %u@%d ' # 时间、进程、用户、数据库
重启数据库使所有配置生效:
sudo systemctl restart postgresql
sudo systemctl status postgresql
配置验证
从四个方面验证加固效果:
- 强认证:
SELECT substring(passwd from 1 for 20) FROM pg_shadow;输出以 SCRAM-SHA-256 开头 - SSL 生效:客户端连接加
sslmode=require,psql "host=10.0.0.x dbname=appdb user=app_user sslmode=require"连接成功后执行SELECT ssl FROM pg_stat_ssl;返回t - 权限隔离:用 readonly 账号尝试
INSERT应报permission denied - 审计日志:执行一条 DDL 后
tail /var/log/postgresql/postgresql-*.log能看到对应的语句与用户名
常见问题
FAQ 1:修改 pg_hba.conf 后远程连接报 “no pg_hba.conf entry”?
说明连接请求没有匹配到任何 pg_hba.conf 规则。按从上到下、首条匹配生效的原则检查:确认连接来源 IP 与规则的网段一致(可用 SELECT client_addr FROM pg_stat_activity; 查看实际来源);确认规则放在 host 类型且方法为 scram-sha-256;确认 PostgreSQL 已 reload(SELECT pg_reload_conf();)。若使用 hostssl 而客户端未启用 SSL,也会不匹配,需在连接串加 sslmode=require。
FAQ 2:开启 log_statement=all 后日志暴涨怎么办?
全量 SQL 日志在生产环境会占用大量磁盘并拖慢性能。建议改为 log_statement = 'ddl' 记录结构变更,配合 log_min_duration_statement 只记录慢查询;对于安全审计需求,可结合扩展 pgAudit(pgaudit.log = 'write,ddl')按角色精细化记录,并通过 log_rotation_age(如 1d)与 log_truncate_on_rotation 控制日志轮转,防止磁盘写满。
总结
PostgreSQL 安全加固的核心动作可概括为五步:监听地址收紧到内网、pg_hba.conf 统一 scram-sha-256 强认证、启用 SSL 加密传输、按最小权限拆分只读/读写角色、开启审计日志。这套配置能有效阻断弱口令爆破、明文传输窃听与越权访问三类主要风险。建议将配置纳入标准部署流程,并定期用 pg_shadow 密码策略检查与权限复核确认加固持续有效。