PostgreSQL 安全加固(状态审查、网络、TLS、认证、权限、审计、加密)
PostgreSQL难度: 中级耗时: 5 分钟(审查)– 3 小时(完整加固)这不是安装指南:它用于发现并修复一台运行中 PostgreSQL 服务器的安全缺口。先运行只读的 状态审查,按严重程度列出发现项,并指出每一项对应哪张卡片;然后逐个或按顺序全部修复各个方面:监听地址、防火墙和 pg_hba;TLS 以及客户端的 sslmode=verify-full;scram-sha-256 以及禁止 postgres 通过网络登录;角色设计和 PUBLIC 权限;pgaudit 和集中日志;LUKS / pgcrypto;加密备份;操作系统;版本跟踪。最后再次运行审查,已修复的发现项会从列表中消失。
架构: 单台 PostgreSQL 服务器 + 应用服务器(客户端验证);带 replica/Patroni 的环境见注意事项
场景
- 状态审查:我有哪些安全缺口?(只读) — 首先运行的扫描:pg_hba、监听地址、TLS、md5 密码、超级用户、PUBLIC 权限、审计、文件权限和防火墙;不做任何更改。
- 完整加固(按顺序处理所有方面) — 新安装或从未加固的服务器:按安全的顺序应用所有方面;PostgreSQL 需要重启一到两次(需要维护窗口)。
- 网络与连接:谁可以从哪里连接?(listen、防火墙、pg_hba) — PostgreSQL 在所有网络接口上监听,pg_hba 中有 0.0.0.0/0 或 trust,端口对所有人开放。修改 listen_addresses 需要重启。
- 加密连接(TLS、sslmode=verify-full) — ssl = off,或客户端不验证证书;服务器证书、hostssl 以及客户端的 verify-full。只需 reload,无停机。
- 认证与密码(scram-sha-256、postgres 远程登录) — md5/password 认证方法、md5 哈希的密码、postgres 用户可以通过网络登录;迁移到 scram-sha-256 并使用个人 DBA 账户。无停机,需要重新设置密码。
- 最小权限:角色、PUBLIC 和应用账户 — 应用账户是表的属主或超级用户,任何人都能向 public 模式写入;读/写/属主角色以及权限报告。无停机。
- 审计:谁做了什么?(pgaudit、集中日志) — 审计人员或安全团队要求记录 DDL 和角色变更;安装 pgaudit 并将日志发送到集中日志服务器。需要重启一次。
- 加密磁盘上的数据(LUKS / pgcrypto) — 需要防范磁盘或备份被盗。PostgreSQL 没有内置 TDE:可以在磁盘层使用 LUKS(迁移需要停机),或在列级使用 pgcrypto。
- 备份安全(加密备份、权限) — 备份文件未加密,或位于所有人可读的目录中;pgBackRest 仓库加密或 pg_dump + GPG、.pgpass 以及目录权限。无停机。
- 操作系统层面(服务账户、权限、core dump、SELinux) — postgres 账户的密码可用,数据目录权限过宽,SELinux 为 Permissive/Disabled。core dump 设置在下次重启后生效。
- 补丁与版本:我用的是受支持的版本吗? — 检查版本、支持结束日期和待安装的小版本更新;实际应用请转到补丁指南。只读。
开始之前
- PostgreSQL … 正在运行,并且可以在服务器本机以 postgres 用户免密码连接(sudo -iu postgres psql)(pg_hba 中有 local all postgres peer)。如果是按 PostgreSQL 安装指南 安装的,这一点已经满足。
- 数据目录 …,配置目录 …;psql、pg_dump 位于 … 下。它们已在 postgres 用户 login shell 的 PATH 中;以 root 调用时请写完整路径。
- 到服务器打开 两个独立的 SSH 会话:一个用来执行步骤,另一个(保持 sudo -iu postgres psql 打开)用于在错误的规则把您挡在外面时回退。每个限制访问的步骤之后,在 第三个 会话中测试新连接;在看到成功之前不要关闭旧会话。
- 维护窗口:所选的方面会重启 PostgreSQL(listen_addresses、shared_preload_libraries、core dump 限制、磁盘迁移)。已通知应用团队。
- 手头有连接数据库的所有应用列表及其连接信息(服务器 IP、用户、驱动版本)。限制之前,审查步骤会回答 谁从哪里连接;不在列表中的客户端在限制后将无法连接。
- 有一份最新且已验证过恢复的备份(pgBackRest 或 pg_dump)。加固不会触及数据,但角色/权限变更和磁盘迁移可能出现无法撤销的错误。
指南阶段
- 状态审查(只读) — 列出数据库内的发现项 · 列出每个数据库中的模式和函数发现项 · 审查操作系统层面
- 开始之前:回退点 — 备份当前配置和角色 · 启用附加配置目录(conf.d)
- 权限 — 1. 诊断 — 显示角色、属主关系和 PUBLIC 权限
- 权限 — 2. 安全网 — 转储当前权限
- 权限 — 3. 实施 — 创建组角色和登录账户 · 为新登录账户设置密码 · 设置数据库和模式权限 · 将应用账户拥有的对象转移给属主角色 · 权限报告
- 权限 — 4. 验证 — 验证应用账户不能执行 DDL 且能写入数据
- 权限 — 5. 后续 — 将 migration 工具切换到属主角色
- 认证 — 1. 诊断 — 显示密码哈希、认证方法和账户
- 认证 — 2. 安全网 — 检查驱动兼容性
- 认证 — 3. 实施 — 让新密码以 scram-sha-256 存储 · 加载设置并重新设置 md5 账户的密码 · 将 pg_hba 中的 md5/password 方法改为 scram-sha-256 · 禁止 postgres 超级用户通过网络登录 · 创建个人 DBA 账户
- 认证 — 4. 验证 — 验证哈希以及超级用户网络登录被拒绝 · 从应用服务器用 scram 登录,并验证 postgres 被拒绝
- 认证 — 5. 后续 — 审查未使用和已过期的账户
- TLS — 1. 诊断 — 显示当前 SSL 状态和未加密的客户端
- TLS — 2. 安全网 — 准备证书目录
- TLS — 3. 实施 — 创建测试 CA 和服务器证书 · 创建密钥和证书签名请求(CSR) · 放置签名证书和 CA 证书链 · 验证证书、密钥和证书链 · 在服务器上启用 TLS · 加载设置并验证 TLS 已启用 …
- TLS — 4. 验证 — 验证未加密连接被拒绝
- TLS — 5. 后续:证书续期 — 证书续期流程
- 网络 — 1. 诊断:谁从哪里连接? — 显示监听地址、pg_hba 规则和活动客户端
- 网络 — 2. 安全网 — 保持回退会话打开
- 网络 — 3. 实施 — 收窄监听地址 · 以最小访问重写 pg_hba.conf · 检查并加载规则 · 在防火墙中只向允许的网络开放端口 · 为监听地址重启 PostgreSQL
- 网络 — 4. 验证 — 从应用服务器测试允许的连接和被拒绝的连接
- 网络 — 5. 后续 — 监控被拒绝的连接
- 审计 — 1. 诊断 — 显示审计和日志设置
- 审计 — 2. 安全网 — 检查日志磁盘的位置和剩余空间
- 审计 — 3. 实施 — 安装 pgaudit 软件包 · 将 pgaudit 加入预加载库并写入设置 · 重启以激活 pgaudit · 创建 pgaudit 扩展 · 将日志转发到集中服务器(rsyslog) · 本地审计文件的保留期(logrotate) …
- 审计 — 4. 验证 — 执行一次 DDL 和角色变更,并在日志中查看
- 审计 — 5. 后续 — 监控关闭审计的行为
- 备份 — 1. 诊断 — 显示备份的加密状态和权限
- 备份 — 2. 安全网 — 准备加密密钥的存放位置
- 备份 — 3. 实施 — 定义新的加密仓库 · 创建加密仓库并进行首次全量备份 · 将 GPG 公钥导入服务器 · 加密备份脚本 · 备份目录、权限和手工测试 · 定时执行加密备份(cron) …