使用 SSL/TLS 配置保护 PostgreSQL 连接:完整指南

了解如何使用 SSL/TLS 加密保护 PostgreSQL 连接。这份综合指南涵盖服务器端和客户端配置,包括生成证书、修改 `postgresql.conf` 和 `pg_hba.conf`,以及设置客户端以实现安全的加密通信。保护传输中的敏感数据,并确保符合现代安全标准。

99 浏览量

配置 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 之前,请确保您具备以下条件:

  1. 安装了 OpenSSL:OpenSSL 工具包对于生成和管理 SSL 证书至关重要。它通常预装在 Linux 和 macOS 系统上。对于 Windows,您可能需要单独下载并安装它。
  2. 访问 PostgreSQL 配置文件:您需要管理员权限来修改 postgresql.confpg_hba.conf 文件。
  3. 了解证书颁发机构 (CA):虽然您可以为测试创建自签名证书,但生产环境理想情况下应使用受信任的证书颁发机构 (CA) 或内部企业 CA 签发的证书。

服务器端 SSL/TLS 配置

服务器端配置涉及启用 SSL、指定 SSL 证书和密钥的位置以及配置客户端身份验证。

1. 生成或获取 SSL 证书和密钥

获取 PostgreSQL 服务器 SSL 证书主要有两种方式:

  • 自签名证书(用于测试/开发):这些使用 OpenSSL 创建,默认情况下不被外部客户端信任。它们适用于初始设置和内部测试。
  • 来自证书颁发机构 (CA) 的证书(用于生产):从受信任的公共 CA(例如 Let's Encrypt、DigiCert)或内部企业 CA 获取证书。这可确保客户端能够验证服务器的身份。

使用 OpenSSL 创建自签名证书:

这是开发和内部环境的常用方法。在您的 PostgreSQL 服务器或装有 OpenSSL 的机器上执行以下命令:

  1. 创建证书目录:保持证书井井有条是一个好习惯。
    bash sudo mkdir -p /etc/postgresql/ssl sudo chown postgres:postgres /etc/postgresql/ssl cd /etc/postgresql/ssl

  2. 生成服务器私钥:此密钥应保密。
    bash sudo openssl genrsa -des3 -out server.key 2048
    系统将提示您输入密码。请记住此密码,因为 PostgreSQL 启动时需要它。

  3. 移除密码(可选,但推荐用于自动重启):为了在不手动输入密码的情况下自动启动,请移除密码。请务必小心,因为任何有权访问此文件的人都可能冒充您的服务器。
    bash sudo openssl rsa -in server.key -out server.key

  4. 创建服务器证书签名请求 (CSR):其中包含有关您的服务器的信息。
    bash sudo openssl req -new -key server.key -out server.csr
    系统将提示您输入国家/地区名称、州/省名称、地区名称、组织名称、通用名称(应为您的服务器主机名或 IP 地址)和电子邮件地址等信息。

  5. 使用您自己的 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
  6. 设置权限:确保 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.confpg_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-caverify-full

为增强安全性,客户端应验证服务器身份。这要求客户端信任签署服务器证书的 CA。

  1. 获取 CA 证书:获取用于签署服务器证书的 root.crt 文件(或相应的 CA 证书)。
  2. 指定 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 相同)。

  1. 生成客户端私钥
    bash openssl genrsa -des3 -out client.key 2048

  2. 创建客户端 CSR
    bash openssl req -new -key client.key -out client.csr
    提供详细信息,确保通用名称对客户端是唯一的。

  3. 使用 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

  4. 设置权限
    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 选项),以便将特定的客户端证书详细信息(如 SubjectSubjectAltName)映射到 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-full sslmode:始终尽量在客户端使用 verify-full,以防止中间人攻击。
  • 保护私钥:确保私钥(.key 文件)具有严格的文件权限(例如 chmod 600),并且在服务器上仅由 PostgreSQL 用户、在客户端仅由连接用户可读。
  • 定期续订证书:证书有有效期。实施流程在证书过期前续订它们,以避免连接中断。
  • 集中式证书管理:对于大规模部署,请考虑使用证书管理系统或自动化证书颁发和续订。
  • 监控日志:检查 PostgreSQL 日志中启动或连接尝试期间任何与 SSL 相关的错误。
  • 文档:查阅官方 PostgreSQL 文档,以获取特定于您的 PostgreSQL 版本的最新参数和高级配置选项。

结论

为 PostgreSQL 连接配置 SSL/TLS 是保护数据库基础设施的关键步骤。通过在服务器上启用 SSL,在 pg_hba.conf 中强制执行 ssl=requirehostssl,并在客户端配置适当的 sslmode 设置(理想情况下为 verify-full),您可以显著增强通过网络传输的数据的安全性。使用客户端证书实施相互身份验证又增加了一个强大的安全层。虽然初始设置可能看起来很复杂,但数据保护和合规性的长期好处使其成为任何 PostgreSQL 部署中不可或缺的实践。