配置 SSL/TLS 以保护 PostgreSQL 连接:完整指南
在当今互联的数字环境中,保护传输中的数据至关重要。PostgreSQL 作为一个强大的开源关系数据库,提供了使用 SSL/TLS 加密连接的强大机制。本指南将全面介绍如何配置 PostgreSQL 服务器和客户端以强制执行 SSL/TLS 加密,从而保护敏感信息在不受信任的网络上免遭窃听和中间人攻击。实施这些安全措施对于维护数据完整性、确保符合严格的安全标准以及建立用户信任至关重要。
本文将涵盖必要步骤,从生成或获取 SSL 证书到配置 PostgreSQL 使用它们,最后设置客户端以实现安全连接。我们将深入探讨必要的配置参数,并提供实用的示例,以帮助您有效实施这些安全增强措施。
理解 PostgreSQL 中的 SSL/TLS
SSL/TLS(安全套接层/传输层安全)是一种加密协议,旨在通过计算机网络提供通信安全。当应用于 PostgreSQL 时,它会加密数据库服务器与其客户端之间交换的数据。这可以防止未经授权的第三方截获和读取凭据、财务数据或个人详细信息等敏感信息。
PostgreSQL 支持 SSL/TLS 的两种主要模式:
ssl=on:允许 SSL 连接,但不需要它们。客户端可以使用 SSL 或非 SSL 连接进行连接。ssl=prefer:尝试建立 SSL 连接,但如果失败则退回到非 SSL 连接。ssl=require:要求 SSL 连接。如果无法建立 SSL 连接,客户端连接将被拒绝。
强制执行 ssl=require 是保护传输中数据的最安全选项。
SSL/TLS 配置先决条件
在开始为 PostgreSQL 配置 SSL/TLS 之前,请确保您具备以下条件:
- 安装了 OpenSSL:OpenSSL 工具包对于生成和管理 SSL 证书至关重要。它通常预装在 Linux 和 macOS 系统上。对于 Windows,您可能需要单独下载并安装它。
- 访问 PostgreSQL 配置文件:您需要管理员权限来修改
postgresql.conf和pg_hba.conf文件。 - 了解证书颁发机构 (CA):虽然您可以为测试创建自签名证书,但生产环境理想情况下应使用受信任的证书颁发机构 (CA) 或内部企业 CA 签发的证书。
服务器端 SSL/TLS 配置
服务器端配置涉及启用 SSL、指定 SSL 证书和密钥的位置以及配置客户端身份验证。
1. 生成或获取 SSL 证书和密钥
获取 PostgreSQL 服务器 SSL 证书主要有两种方式:
- 自签名证书(用于测试/开发):这些使用 OpenSSL 创建,默认情况下不被外部客户端信任。它们适用于初始设置和内部测试。
- 来自证书颁发机构 (CA) 的证书(用于生产):从受信任的公共 CA(例如 Let's Encrypt、DigiCert)或内部企业 CA 获取证书。这可确保客户端能够验证服务器的身份。
使用 OpenSSL 创建自签名证书:
这是开发和内部环境的常用方法。在您的 PostgreSQL 服务器或装有 OpenSSL 的机器上执行以下命令:
-
创建证书目录:保持证书井井有条是一个好习惯。
bash sudo mkdir -p /etc/postgresql/ssl sudo chown postgres:postgres /etc/postgresql/ssl cd /etc/postgresql/ssl -
生成服务器私钥:此密钥应保密。
bash sudo openssl genrsa -des3 -out server.key 2048
系统将提示您输入密码。请记住此密码,因为 PostgreSQL 启动时需要它。 -
移除密码(可选,但推荐用于自动重启):为了在不手动输入密码的情况下自动启动,请移除密码。请务必小心,因为任何有权访问此文件的人都可能冒充您的服务器。
bash sudo openssl rsa -in server.key -out server.key -
创建服务器证书签名请求 (CSR):其中包含有关您的服务器的信息。
bash sudo openssl req -new -key server.key -out server.csr
系统将提示您输入国家/地区名称、州/省名称、地区名称、组织名称、通用名称(应为您的服务器主机名或 IP 地址)和电子邮件地址等信息。 -
使用您自己的 CA 签署服务器 CSR(供内部使用):
- 创建根 CA 私钥和证书(如果您还没有):
bash # 生成 CA 私钥 sudo openssl genrsa -des3 -out root.key 2048 # 创建 CA 证书(有效期 3650 天) sudo openssl req -new -x509 -days 3650 -key root.key -out root.crt - 使用 CA 签署服务器 CSR:这将创建受信任的服务器证书。
bash sudo openssl x509 -req -days 365 -in server.csr -CA root.crt -CAkey root.key -set_serial 01 -out server.crt
- 创建根 CA 私钥和证书(如果您还没有):
-
设置权限:确保 PostgreSQL 用户可以读取这些文件。
bash sudo chown postgres:postgres server.key server.crt root.crt sudo chmod 600 server.key sudo chmod 644 server.crt root.crt
使用来自公共/企业 CA 的证书:
如果您从 CA 获得了证书,您通常会收到:
server.crt:您的服务器公有证书。server.key:您的服务器私钥。root.crt(或类似文件):CA 的根证书(以及可能的中间证书)。
将这些文件放在安全目录(例如 /etc/postgresql/ssl/)中,并确保 PostgreSQL 用户具有读取权限。
2. 配置 postgresql.conf
编辑您的 postgresql.conf 文件(通常位于 PostgreSQL 数据目录中),以启用 SSL 并指定证书文件。
#------------------------------------------------------------------------------
# SSL
#------------------------------------------------------------------------------
ssl = on
# 这些都是 PEM 格式,如果未配置服务器密钥/证书,则会被忽略。默认情况下,期望文件位于服务器的数据目录中。或者,可以指定为完整路径。
ssl_cert_file = '/etc/postgresql/ssl/server.crt' # (如果需要,更改文件名)
ssl_key_file = '/etc/postgresql/ssl/server.key' # (如果需要,更改文件名)
ssl_ca_file = '/etc/postgresql/ssl/root.crt' # (可选,用于客户端证书验证)
# 可选:如果需要,指定密码套件列表
#ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL'
# 可选:启用客户端证书验证
# 必须将 ssl_ca_file 设置为包含要信任的 CA 证书的文件
#ssl_crl_file = ''
#ssl_crl_dir = ''
ssl = on:在服务器上启用 SSL 支持。ssl_cert_file:服务器公有证书的路径。ssl_key_file:服务器私钥的路径。ssl_ca_file:CA 证书的路径(如果您想验证客户端证书或服务器证书由自定义 CA 签名时)。
3. 配置 pg_hba.conf 以强制执行 SSL
pg_hba.conf 文件控制客户端身份验证。您需要修改条目以强制执行 SSL 连接。
默认情况下,pg_hba.conf 中的条目如下所示:
# 类型 数据库 用户 地址 方法
local all all peer
# IPv4 本地连接:
host all all 127.0.0.1/32 scram-sha-256
# IPv6 本地连接:
host all all ::1/128 scram-sha-256
要强制执行 SSL,请将 host 条目更改为 hostssl:
# 类型 数据库 用户 地址 方法
local all all peer
# IPv4 本地连接:
hostssl all all 127.0.0.1/32 scram-sha-256
# IPv6 本地连接:
hostssl all all ::1/128 scram-sha-256
# 外部网络访问示例 - 需要 SSL
hostssl all all 0.0.0.0/0 scram-sha-256
hostssl all all ::/0 scram-sha-256
hostssl:此记录类型要求 SSL 连接。任何没有 SSL 的连接尝试都将被拒绝。hostnossl:此记录类型明确禁止 SSL 连接。host:允许 SSL 和非 SSL 连接(这是默认设置,安全性较低)。
4. 重启 PostgreSQL 服务器
修改 postgresql.conf 和 pg_hba.conf 后,必须重启 PostgreSQL 服务才能使更改生效。
# 对于使用 systemd 的系统(大多数现代 Linux 发行版)
sudo systemctl restart postgresql
# 对于使用 init.d 的系统
sudo service postgresql restart
客户端 SSL/TLS 配置
客户端也需要配置为安全连接。这包括指定连接参数、可能提供客户端证书以及验证服务器证书。
1. 连接字符串参数
当通过 psql 或任何 PostgreSQL 客户端库连接时,您可以在连接字符串或作为单独的选项中指定 SSL 参数。
基本 SSL 连接(仅服务器身份验证):
psql "sslmode=require host=your_server_hostname dbname=your_db user=your_user"
sslmode:控制客户端的 SSL 行为。disable:只允许非 SSL 连接。allow:允许非 SSL,但如果服务器支持则优先使用 SSL。prefer(默认值):优先使用 SSL,但如果 SSL 失败则允许非 SSL。require:只允许 SSL 连接。如果服务器不支持 SSL,连接将失败。verify-ca:只允许 SSL 连接,并验证服务器证书是否由受信任的 CA 签名。必须设置sslrootcert参数。verify-full:只允许 SSL 连接,验证服务器证书是否受信任的 CA 签名,并验证服务器主机名是否与证书的通用名称 (CN) 或主题替代名称 (SAN) 匹配。
验证服务器证书(verify-ca 或 verify-full):
为增强安全性,客户端应验证服务器身份。这要求客户端信任签署服务器证书的 CA。
- 获取 CA 证书:获取用于签署服务器证书的
root.crt文件(或相应的 CA 证书)。 - 指定
sslrootcert:告知客户端在哪里可以找到此 CA 证书。
psql "sslmode=verify-full host=your_server_hostname dbname=your_db user=your_user sslrootcert=/path/to/your/root.crt"
2. 客户端证书(相互身份验证)
为了获得更高级别的安全性,您可以实施相互身份验证,即服务器也使用客户端证书验证客户端的身份。
生成客户端证书:
与服务器证书类似,您需要一个客户端私钥和一个由服务器信任的 CA 签名的客户端证书(通常与服务器证书的 CA 相同)。
-
生成客户端私钥:
bash openssl genrsa -des3 -out client.key 2048 -
创建客户端 CSR:
bash openssl req -new -key client.key -out client.csr
提供详细信息,确保通用名称对客户端是唯一的。 -
使用 CA 签署客户端 CSR:
bash sudo openssl x509 -req -days 365 -in client.csr -CA root.crt -CAkey root.key -set_serial <unique_serial> -out client.crt -
设置权限:
bash chmod 600 client.key chmod 644 client.crt
在 pg_hba.conf 中配置客户端证书身份验证:
在服务器上,您需要在 pg_hba.conf 中配置以接受客户端证书身份验证。这通常使用 cert 身份验证方法。
# 类型 数据库 用户 地址 方法
# 为特定用户/数据库要求 SSL 和客户端证书身份验证
hostssl all your_user your_client_ip/32 cert map=your_cert_map
您可能还需要定义一个证书映射文件(cert_map 选项),以便将特定的客户端证书详细信息(如 Subject 或 SubjectAltName)映射到 PostgreSQL 用户。有关详细的 cert 身份验证和证书映射设置,请参阅 PostgreSQL 文档。
配置客户端以使用证书:
更新客户端的连接字符串,以包含其证书和密钥的路径:
psql "sslmode=verify-full host=your_server_hostname dbname=your_db user=your_user \nsslrootcert=/path/to/your/root.crt sslcert=/path/to/your/client.crt sslkey=/path/to/your/client.key"
最佳实践和提示
- 在客户端使用
verify-fullsslmode:始终尽量在客户端使用verify-full,以防止中间人攻击。 - 保护私钥:确保私钥(
.key文件)具有严格的文件权限(例如chmod 600),并且在服务器上仅由 PostgreSQL 用户、在客户端仅由连接用户可读。 - 定期续订证书:证书有有效期。实施流程在证书过期前续订它们,以避免连接中断。
- 集中式证书管理:对于大规模部署,请考虑使用证书管理系统或自动化证书颁发和续订。
- 监控日志:检查 PostgreSQL 日志中启动或连接尝试期间任何与 SSL 相关的错误。
- 文档:查阅官方 PostgreSQL 文档,以获取特定于您的 PostgreSQL 版本的最新参数和高级配置选项。
结论
为 PostgreSQL 连接配置 SSL/TLS 是保护数据库基础设施的关键步骤。通过在服务器上启用 SSL,在 pg_hba.conf 中强制执行 ssl=require 或 hostssl,并在客户端配置适当的 sslmode 设置(理想情况下为 verify-full),您可以显著增强通过网络传输的数据的安全性。使用客户端证书实施相互身份验证又增加了一个强大的安全层。虽然初始设置可能看起来很复杂,但数据保护和合规性的长期好处使其成为任何 PostgreSQL 部署中不可或缺的实践。