PostgreSQL 原生地支持使用SSL连接来加密客户端/服务器通信,以提高安全性。这要求在客户端和服务器系统上安装 OpenSSL,并在构建时启用 PostgreSQL 中的支持(参见 第 17 章)。
这些术语SSL和TLS常常可以互换使用,表示使用TLS协议的加密安全连接。SSL协议是TLS协议的前身,而术语SSL仍然用于加密连接,即使SSL协议不再受支持。SSL与搭配使用TLS在 PostgreSQL 中。
借助SSL在编译时包含的支持,可以使用TLS开启的参数 ssl 在 postgresql.conf
中将其设置为 on
来启用加密连接支持,启动 PostgreSQL 服务器。服务器将侦听相同 TCP 端口上的普通和SSL连接,并与任何连接的客户端协商是否使用SSL。默认情况下,在客户端选项中;请参见 第 20.1 节,了解如何设置服务器以需要使用SSL与部分或所有连接。
为在SSL模式下启动,必须存在包含服务器证书和私钥的文件。默认情况下,这些文件预期被分别命名为 server.crt
和 server.key
,在服务器的数据目录中,但可以使用配置参数 ssl_cert_file 和 ssl_key_file 指定其他名称和位置。
在 Unix 系统上,server.key
的权限不得授予任何人访问组或全局;通过命令 chmod 0600 server.key
实现此目的。或者,该文件可由 root 拥有并具有组的读取权限(即,0640
权限)。该设置适用于由操作系统管理证书和密钥文件的情况。运行 PostgreSQL 服务器的用户应成为具有访问那些证书和密钥文件的权限的组的成员。
如果数据目录允许组的读取权限,则证书文件可能需要位于数据目录外面以符合上述安全要求。通常,为了允许非特权用户备份数据库,因而启用了组的访问权限,在这种情况下,备份软件将无法读取证书文件并很可能出错。
如果私钥受密码短语保护,服务器将提示输入密码短语,并且在输入前不会启动。默认情况下,使用密码短语将禁用在不重新启动服务器的情况下更改服务器的 SSL 配置的功能,但请参阅 ssl_passphrase_command_supports_reload。此外,在 Windows 上根本无法使用受密码短语保护的私钥。
server.crt
中的第一个证书必须是服务器证书,因为它必须与服务器的私钥匹配。
可以将 “中间” 证书颁发机构的证书附加到该文件。这样做可以避免在客户端上存储中间证书的必要性,假设根证书和中间证书是使用 v3_ca
扩展创建的。(这将证书的基本 CA
约束设置为 true
。)这允许更轻松地使中间证书过期。
server.crt
。相反,客户端必须具有服务器证书链的根证书。18.9.2. OpenSSL 配置 #
PostgreSQL 读取系统范围的 OpenSSL 配置文件。默认情况下,此文件名为 openssl.cnf
,并位于 openssl version -d
报告的目录中。可以通过将环境变量 OPENSSL_CONF
设置为所需配置文件的名称来覆盖此默认设置。
postgresql.conf
中的 ssl_ciphers 来指定专门供数据库服务器使用的密码。注意
NULL-SHA
或 NULL-MD5
密码实现无加密开销的身份验证。但是,中间人可以读取和传递客户端和服务器之间的通信。此外,与身份验证开销相比,加密开销很小。由于这些原因,不建议使用 NULL 密码。18.9.3. 使用客户端证书 #若要要求客户端提供受信任的证书,请放置根证书颁发机构的证书 ()在数据目录中您信任的文件中,将参数 ssl_ca_file 在 postgresql.conf
中设置为新文件名,并将认证选项 clientcert=verify-ca
或 clientcert=verify-full
添加到 pg_hba.conf
中相应的 hostssl
行。然后将在 SSL 连接启动过程中从客户端请求证书。(有关如何在客户端设置证书的说明,请参见 第 32.19 节。)
对于带有 clientcert=verify-ca
的 hostssl
条目,服务器将验证客户端的证书是否由受信任的证书颁发机构之一签署。如果指定 clientcert=verify-full
,服务器不仅会验证证书链,而且还会检查用户名或其映射是否与所提供证书的 cn
(公用名)相匹配。请注意,在使用 cert
认证方法时,始终确保对证书链进行验证(请参见 第 20.12 节)。
如果希望避免将中间证书存储在客户端(假设根证书和中间证书是用 v3_ca
扩展名创建的),中间证书(与现有根证书形成链)也可以出现在 ssl_ca_file 文件中。如果设置参数 ssl_crl_file 或 ssl_crl_dir,还会检查证书吊销列表 (CRL) 条目。
clientcert
认证选项适用于所有认证方法,但仅适用于指定为 hostssl
的 pg_hba.conf
行。如果未指定 clientcert
,当提供了客户端证书且已配置 CA 时,服务器仅根据其 CA 文件对客户端证书进行验证。
有两种方法来强制要求用户在登录期间提供证书。
第一种方法利用了 pg_hba.conf
中 hostssl
条目的 cert
认证方法,这样证书本身可用于认证,同时还提供 ssl 连接安全。有关详细信息,请参见 第 20.12 节。(使用 cert
认证方法时,无需显式指定任何 clientcert
选项。)在这种情况下,证书中提供的 cn
(公用名)将与用户名或适用的映射进行检查。
第二种方法将 hostssl
条目的任何认证方法与通过将 clientcert
认证选项设为 verify-ca
或 verify-full
来验证客户端证书相结合。前者选项仅强制要求证书有效,而后者还确保证书中的 cn
(公用名)与用户名或适用的映射相匹配。
表 18.2 总结了与服务器上的 SSL 设置相关的文件。(所示的文件名是默认名称。本地配置的名称可能不同。)
表 18.2. SSL 服务器文件使用情况
文件 | 内容 | 作用 |
---|---|---|
ssl_cert_file ($PGDATA/server.crt ) |
服务器证书 | 发送给客户端以表明服务器的身份 |
ssl_key_file ($PGDATA/server.key ) |
服务器私钥 | 证明服务器证书是由所有者发送的;并不表明证书所有者是可信的 |
ssl_ca_file | 可信证书颁发机构 | 检查客户端证书是否由可信证书颁发机构签名 |
ssl_crl_file | 由证书颁发机构吊销的证书 | 客户端证书不得在此列表中 |
服务器在服务器启动时和服务器配置重新加载时读取这些文件。在 Windows 系统上,每当为新的客户端连接生成新的后端进程时,也会重新读取这些文件。
如果在服务器启动时检测到这些文件中有错误,服务器将拒绝启动。但如果在配置重新加载期间检测到错误,系统将忽略这些文件,旧的 SSL 配置将继续使用。在 Windows 系统上,如果在后端启动时检测到这些文件中有错误,该后端将无法建立 SSL 连接。在所有这些情况下,错误情况都会在服务器日志中报告。
若要为服务器创建简单的自签名证书(有效期为 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文档。
尽管自签名证书可用于测试,但生产环境中应使用证书颁发机构(若要要求客户端提供受信任的证书,请放置根证书颁发机构的证书 ()签名的证书(通常是企业范围根若要要求客户端提供受信任的证书,请放置根证书颁发机构的证书 ()。
若要创建客户端可以验证其标识的服务器证书,首先创建一个证书签名请求(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.crt
和server.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.crt
和intermediate.crt
应串联到证书文件包中并存储在服务器中。server.key
也应该存储在服务器中。root.crt
应该存储在客户端中,这样客户端就可以验证服务器的叶证书是否是由链接到其受信任的根证书的证书链签名的。root.key
和intermediate.key
应该离线存储,以便在创建未来证书时使用。