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

PostgreSQL 对使用 SSL 连接加密 Client 端/服务器通信以提高安全性提供了本机支持。这要求在 Client 端和服务器系统上都安装 OpenSSL,并在构建时启用 PostgreSQL 中的支持(请参阅Chapter 16)。

18 .9.1. 基本设定

在编译了 SSL 支持的情况下,可以通过在postgresql.conf中将参数ssl设置为on来启用 SSL 来启动 PostgreSQL 服务器。服务器将侦听同一 TCP 端口上的常规连接和 SSL 连接,并将与任何连接的 Client 端协商是否使用 SSL。默认情况下,这是由 Client 选择的。请参阅Section 20.1,了解如何设置服务器以要求对部分或全部连接使用 SSL。

要以 SSL 模式启动,必须存在包含服务器证书和私钥的文件。默认情况下,这些文件在服务器的数据目录中应分别命名为server.crtserver.key,但是可以使用配置参数ssl_cert_filessl_key_file来指定其他名称和位置。

在 Unix 系统上,对server.key的许可必须禁止对世界或组的任何访问。通过命令chmod 0600 server.key实现。或者,该文件可以由 root 拥有,并具有组读取访问权限(即0640权限)。该设置适用于证书和密钥文件由 osManagement 的安装。然后,应该使运行 PostgreSQL 服务器的用户成为有权访问这些证书和密钥文件的组的成员。

如果数据目录允许组读取访问,则证书文件可能需要位于数据目录之外,以符合上述安全要求。通常,启用组访问权限是为了允许非特权用户备份数据库,在这种情况下,备份软件将无法读取证书文件,并且很可能会出错。

如果私钥已使用密码保护,则服务器将提示您 Importing 密码,直到 Importing 密码后服务器才会启动。默认情况下使用密码短语将禁用更改服务器的 SSL 配置而无需重新启动服务器的功能,但请参阅ssl_passphrase_command_supports_reload。此外,受密码保护的私钥根本无法在 Windows 上使用。

server.crt中的第一个证书必须是服务器的证书,因为它必须与服务器的私钥匹配。 “中间”证书颁发机构的证书也可以附加到文件中。这样做可以避免在 Client 端上存储中间证书的情况,假设根证书和中间证书是使用v3_caextensions 创建的。这使得中间证书更容易到期。

无需将根证书添加到server.crt。而是,Client 端必须具有服务器证书链的根证书。

18 .9.2. OpenSSL 配置

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

OpenSSL 支持各种强度不同的密码和身份验证算法。虽然可以在 OpenSSL 配置文件中指定密码列表,但是您可以通过修改postgresql.conf中的ssl_ciphers来指定专门供数据库服务器使用的密码。

Note

通过使用NULL-SHANULL-MD5密码,可以在没有加密开销的情况下进行身份验证。但是,中间人可以读取并通过 Client 端与服务器之间的通信。而且,与身份验证的开销相比,加密开销最小。由于这些原因,不建议使用 NULL 密码。

18 .9.3. 使用 Client 证书

要要求 Client 端提供受信任的证书,请将您信任的根证书颁发机构(CA)的证书放在数据目录中的文件中,将postgresql.conf中的参数ssl_ca_file设置为新文件名,并将身份验证选项clientcert=1添加到pg_hba.conf中适当的hostssl行。然后,在 SSL 连接启动期间将从 Client 端请求证书。 (有关如何在 Client 端上设置证书的说明,请参阅Section 34.18。)服务器将验证 Client 端的证书是否由受信任的证书颁发机构之一签名。

如果您希望避免将链接到现有根证书的中间证书也存储在ssl_ca_file文件中(假设根证书和中间证书是使用v3_caextensions 创建的)。如果设置了参数ssl_crl_file,还将检查证书吊销列表(CRL)条目。 (有关显示 SSL 证书使用的图表,请参见http://h41379.www4.hpe.com/doc/83final/ba554_90007/ch04s02.html。)

clientcert身份验证选项可用于所有身份验证方法,但仅在指定为hostsslpg_hba.conf行中可用。如果未指定clientcert或将clientcert设置为 0,则服务器仍将根据其 CA 文件验证任何提供的 Client 端证书(如果已配置的话),但是它不会坚持要求提供 Client 端证书。

如果要设置 Client 端证书,则可能希望使用cert身份验证方法,以便证书可以控制用户身份验证并提供连接安全性。有关详情,请参见Section 20.12。 (使用cert身份验证方法时,不必显式指定clientcert=1.)

18 .9.4. SSL 服务器文件使用情况

Table 18.2总结了与服务器上的 SSL 设置相关的文件。 (显示的文件名是默认名称.本地配置的名称可以不同.)

表 18.2. SSL 服务器文件使用

FileContentsEffect
ssl_cert_file ( $PGDATA/server.crt )server certificate发送给 Client 端以指示服务器的身份
ssl_key_file ( $PGDATA/server.key )服务器私钥证明服务器证书是由所有者发送的;并不表示证书所有者是可信赖的
ssl_ca_file受信任的证书颁发机构检查 Client 端证书是否由受信任的证书颁发机构签名
ssl_crl_file证书颁发机构吊销的证书Client 证书不能在此列表中

服务器在服务器启动时以及重新加载服务器配置时都会读取这些文件。在 Windows 系统上,每当为新的 Client 端连接产生新的后端进程时,也会重新读取它们。

如果在服务器启动时检测到这些文件中的错误,则服务器将拒绝启动。但是,如果在重新加载配置期间检测到错误,则将忽略文件并 continue 使用旧的 SSL 配置。在 Windows 系统上,如果在后端启动时检测到这些文件中的错误,则该后端将无法构建 SSL 连接。在所有这些情况下,错误情况都会在服务器日志中报告。

18 .9.5. 创建证书

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

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

Then do:

chmod og-rwx server.key

因为如果服务器的权限比此权限更大,服务器将拒绝该文件。有关如何创建服务器私钥和证书的更多详细信息,请参考 OpenSSL 文档。

尽管可以使用自签名证书进行测试,但在 Producing 应使用由证书颁发机构(CA)(通常是企业范围的根 CA)签名的证书。

要创建其身份可以被 Client 端验证的服务器证书,请首先创建一个证书签名请求(CSR)和一个公用/专用密钥文件:

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

然后,使用密钥对请求进行签名以创建根证书颁发机构(使用 Linux 上的默认 OpenSSL 配置文件位置):

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应该存储在 Client 端上,以便 Client 端可以验证服务器的叶证书已由其受信任的根证书签名。 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应该存储在 Client 端上,以便 Client 端可以验证服务器的叶证书是否已由链接到其受信任根证书的证书链签名。 root.keyintermediate.key应该脱机存储,以用于创建将来的证书。