选择 打开 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0
历史版本PostgreSQL 9.5 已于 2021 年 2 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本

17.9. 使用 SSL 的安全 TCP/IP 连接 #

PostgreSQL原生支持使用SSL连接来加密客户端与服务器之间的通信,以提高安全性。这要求客户端和服务器系统上都安装了OpenSSL,并且在构建PostgreSQL时启用了该支持(见第 15 章)。

如果构建时启用了 SSL 支持,那么在 postgresql.conf 中将参数 ssl 设为 on,就可以在启动 PostgreSQL 服务器时启用 SSL。服务器会在同一个 TCP 端口上同时监听普通连接和 SSL 连接,并与每个连接进来的客户端协商是否使用 SSL。默认情况下,这由客户端决定;关于如何把服务器配置为要求某些或全部连接必须使用 SSL,请参阅 第 19.1 节

PostgreSQL会读取系统范围的OpenSSL配置文件。默认情况下,该文件名为openssl.cnf,位于openssl version -d报告的目录中。可以通过把环境变量OPENSSL_CONF设为所需配置文件的名称,覆盖这一默认值。

OpenSSL支持种类繁多、强度不一的密码套件和认证算法。虽然可以在OpenSSL配置文件中指定密码套件列表,但你也可以通过修改postgresql.conf中的ssl_ciphers,专门为数据库服务器指定要使用的密码套件。

注意

使用NULL-SHANULL-MD5密码套件,可以在没有加密开销的情况下完成认证。不过,中间人仍然能够读取并转发客户端与服务器之间的通信。此外,与认证的开销相比,加密开销本身很小。基于这些原因,不建议使用 NULL 密码套件。

要以SSL模式启动服务器,必须存在包含服务器证书和私钥的文件。默认情况下,这些文件应分别命名为server.crtserver.key,并放在服务器的数据目录中;不过也可以通过配置参数ssl_cert_filessl_key_file指定其他名称和位置。在 Unix 系统上,server.key的权限必须禁止组和其他用户访问;可以通过chmod 0600 server.key实现。如果私钥受口令保护,服务器会提示输入口令,并在输入之前一直等待,不会启动。

server.crt中的第一个证书必须是服务器证书,因为它必须与服务器私钥相匹配。中间证书颁发机构的证书也可以追加到该文件中。假设根证书和中间证书是使用v3_ca 扩展创建的(这会将证书的 CA 基本约束设为 true),这样做就可以避免在客户端上存储中间证书。同时,这也使中间证书更容易单独过期。

无需把根证书加入server.crt。相反,客户端必须持有服务器证书链对应的根证书。

17.9.1. 使用客户端证书 #

要要求客户端提供受信任的证书,请把你信任的根证书颁发机构(CA)的证书放入数据目录中的某个文件,在 postgresql.conf 中将参数 ssl_ca_file 设为该文件名,并在 pg_hba.conf 中相应的 hostssl 行上添加认证选项 clientcert=1。这样,SSL 连接启动时就会向客户端请求证书。(关于如何在客户端设置证书,请参见 第 31.18 节。)服务器会验证客户端证书是否由某个受信任的证书颁发机构签名。

如果希望避免在客户端上存储中间证书,那么与现有根证书构成链的中间证书也可以出现在 root.crt 文件中(前提是根证书和中间证书使用 v3_ca 扩展创建)。如果设置了参数 ssl_crl_file,还会检查证书吊销列表(CRL)条目。

pg_hba.conf 中的 clientcert 选项适用于所有认证方法,但只适用于指定为 hostssl 的行。未指定 clientcert 或将其设为 0 时,如果配置了 CA 列表,服务器仍会依据该列表验证客户端提供的证书,但不会强制要求客户端提供证书。

如果正在设置客户端证书,可以考虑使用 cert 认证方法,让证书在提供连接安全性的同时也控制用户认证。详情参见 第 19.3.9 节

17.9.2. SSL 服务器文件用法 #

表 17.2 概括了服务器端 SSL 设置相关的文件。(表中显示的是默认或典型文件名;本地实际配置的名称可能不同。)

表 17.2. SSL 服务器文件用法

文件 内容 效果
ssl_cert_file ($PGDATA/server.crt) 服务器证书 发送给客户端,用于表明服务器身份
ssl_key_file ($PGDATA/server.key) 服务器私钥 证明服务器证书是其所有者发送的,并不说明证书所有者是值得信任的
ssl_ca_file ($PGDATA/root.crt) 可信的证书颁发机构 检查客户端证书是由一个可信的证书颁发机构签名的
ssl_crl_file ($PGDATA/root.crl) 被证书颁发机构吊销的证书 客户端证书不能出现在这个列表上

文件server.keyserver.crtroot.crtroot.crl(或它们配置的替代名称)只在服务器启动期间检查;因此要让这些文件中的变更生效,必须重启服务器。

17.9.3. 创建证书 #

要为服务器创建一个有效期为 365 天的简单自签名证书,可以使用下面的OpenSSL命令,并将dbhost.yourdomain.com替换为服务器主机名:

openssl req -new -x509 -days 365 -nodes -text -out server.crt \
  -keyout server.key -subj "/CN=dbhost.yourdomain.com"

然后执行:

chmod og-rwx server.key

如果该文件权限比这更宽松,服务器会拒绝使用它。关于如何创建服务器私钥和证书的更多细节,请参阅OpenSSL文档。

虽然自签名证书可用于测试,但在生产环境中应使用由证书颁发机构(CA,通常是企业范围内的根 CA)签名的证书。

要创建一个可由客户端验证其身份的服务器证书,首先要创建证书签名请求(CSR)以及公钥/私钥文件:

openssl req -new -nodes -text -out root.csr \
  -keyout root.key -subj "/CN=root.yourdomain.com"
chmod og-rwx root.key

然后,使用该密钥对请求进行签名,以创建一个根证书颁发机构(这里使用的是LinuxOpenSSL配置文件的默认位置):

openssl x509 -req -in root.csr -text -days 3650 \
  -extfile /etc/ssl/openssl.cnf -extensions v3_ca \
  -signkey root.key -out root.crt

最后,创建一个由新根证书颁发机构签名的服务器证书:

openssl req -new -nodes -text -out server.csr \
  -keyout server.key -subj "/CN=dbhost.yourdomain.com"
chmod og-rwx server.key

openssl x509 -req -in server.csr -text -days 365 \
  -CA root.crt -CAkey root.key -CAcreateserial \
  -out server.crt

server.crtserver.key应存放在服务器上,而root.crt应存放在客户端上,以便客户端能够验证服务器的叶子证书是否由其受信任的根证书签名。root.key应离线保存,以供将来签发证书时使用。

也可以创建包含中间证书的信任链:

# root
openssl req -new -nodes -text -out root.csr \
  -keyout root.key -subj "/CN=root.yourdomain.com"
chmod og-rwx root.key
openssl x509 -req -in root.csr -text -days 3650 \
  -extfile /etc/ssl/openssl.cnf -extensions v3_ca \
  -signkey root.key -out root.crt

# intermediate
openssl req -new -nodes -text -out intermediate.csr \
  -keyout intermediate.key -subj "/CN=intermediate.yourdomain.com"
chmod og-rwx intermediate.key
openssl x509 -req -in intermediate.csr -text -days 1825 \
  -extfile /etc/ssl/openssl.cnf -extensions v3_ca \
  -CA root.crt -CAkey root.key -CAcreateserial \
  -out intermediate.crt

# leaf
openssl req -new -nodes -text -out server.csr \
  -keyout server.key -subj "/CN=dbhost.yourdomain.com"
chmod og-rwx server.key
openssl x509 -req -in server.csr -text -days 365 \
  -CA intermediate.crt -CAkey intermediate.key -CAcreateserial \
  -out server.crt

server.crtintermediate.crt应拼接为一个证书文件包并存放在服务器上。server.key也应存放在服务器上。root.crt应存放在客户端上,以便客户端验证服务器的叶子证书是否由一条可追溯到其受信任根证书的证书链签名。root.keyintermediate.key应离线保存,以供将来签发证书时使用。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。