你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
在 Azure Database for PostgreSQL 灵活服务器中使用 TLS 和 SSL 的安全连接
适用于: Azure Database for PostgreSQL 灵活服务器
Azure Database for PostgreSQL - 灵活服务器使用传输层安全性 (TLS) 强制将客户端应用程序连接到 Azure Database for PostgreSQL - 灵活服务器。 TLS 是一种行业标准协议,可确保在数据库服务器与客户端应用程序之间实现加密网络连接。 TLS 是安全套接字层 (SSL) 的更新协议。
什么是 TLS?
TLS 是从 Netscape 的 SSL 协议生成的,已定期替换。 SSL 或 TLS/SSL 术语有时仍可互换使用。 TLS 由两个层组成:TLS 记录显示和 TLS 握手显示。 记录显示提供关联安全性。 握手协议使服务器和客户能够相互确认,并在交换任何信息之前协调加密评估和加密密钥。
上图显示了典型的 TLS 1.2 握手序列,其中包括以下步骤:
- 客户端首先发送一个名为
ClientHello
的消息,该消息表示愿意通过 TLS 1.2 使用一组客户端支持的密码套件进行通信 - 服务器收到该消息,回复
ServerHello
,并同意通过 TLS 1.2 使用特定的密码套件与客户端进行通信 - 服务器还会发送其密钥共享。 此密钥共享部分的具体信息会根据所选的密码套件而更改。 要使客户端和服务器就加密密钥达成一致,他们需要接收彼此的部分(也称为共享部分)。
- 服务器会在
ClientHello
和ServerHello
部分中发送证书(由证书颁发机构 [CA] 签名)和签名。 它还包括密钥共享。 这样,客户端就知道它们是真实的。 - 客户端成功接收数据,然后生成自己的密钥共享后,会将其与服务器密钥共享混合,从而生成会话的加密密钥。
- 客户端向服务器发送其密钥共享,启用加密,并发送
Finished
消息。 此消息是到目前为止所发生事件的脚本的哈希。 服务器会执行相同操作。 它会混用密钥共享以获取密钥并发送自己的Finished
消息。 - 现在,可以在连接上加密发送应用程序数据。
证书链
证书链是包含 TLS/SSL 证书和 CA 证书的证书有序列表。 它们使接收方能够验证发送方和所有 CA 是否可信。 链或路径以 TLS/SSL 证书开头。 链中的每个证书都由链中的下一个证书标识的实体签名。
链以根 CA 证书结束。 此证书始终由 CA 本身签名。 必须验证链中所有证书的签名,直至根 CA 证书。
链中位于 TLS/SSL 证书和根 CA 证书之间的任何证书都称为中间证书。
TLS 版本
全球多个政府实体维护有关网络安全的 TLS 准则。 在美国,这些组织包括卫生与公众服务部以及国家标准与技术研究所。 TLS 提供的安全级别受 TLS 协议版本和受支持的密码套件的影响最大。
密码套件是一组算法,其中包括密码、密钥交换算法和哈希算法。 它们一起用于建立安全 TLS 连接。 大多数 TLS 客户端和服务器都支持多种替代方法。 它们必须协商何时建立安全连接,以选择通用 TLS 版本和密码套件。
Azure Database for PostgreSQL 支持 TLS 1.2 版本和更高版本。 在 RFC 8996 中,Internet 工程任务组 (IETF) 明确指出不得使用 TLS 1.0 和 TLS 1.1。 这两个协议在 2019 年底已弃用。
所有使用早期版本 TLS 协议(例如 TLS 1.0 和 TLS 1.1)的传入连接会被默认拒绝。
IETF 于 2018 年 8 月在 RFC 8446 中发布了 TLS 1.3 规范,TLS 1.3 现在是最常用的和推荐使用的 TLS 版本。 TLS 1.3 比 TLS 1.2 更快、更安全。
注意
SSL 和 TLS 证书证明连接受到最先进加密协议的保护。 在线加密连接可以防止对传输中的数据进行未经授权的访问。 我们强烈建议使用最新版本的 TLS 来加密与 Azure Database for PostgreSQL - 灵活服务器的连接。
尽管我们不建议这样做,但如果需要,可以禁用 TLS\SSL 来连接到 Azure Database for PostgreSQL - 灵活服务器。 可以将 require_secure_transport
服务器参数更新为 OFF
。 还可以通过设置 ssl_min_protocol_version
和 ssl_max_protocol_version
服务器参数来设置 TLS 版本。
证书身份验证可使用 SSL 客户端证书进行身份验证来执行。 在此方案中,PostgreSQL 服务器会将提供的客户端证书的公用名 (CN) 属性与请求的数据库用户进行比较。
此时,Azure Database for PostgreSQL - 灵活服务器不支持:
- 基于 SSL 证书的身份验证。
- 自定义 SSL\TLS 证书。
注意
Microsoft 对各种 Azure 服务(包括 Azure Database for PostgreSQL - 灵活服务器)进行了根 CA 更改。 有关详细信息,请参阅 Azure TLS 证书更改和在客户端上配置 SSL 部分。
若要确定当前的 TLS\SSL 连接状态,可以加载 sslinfo 扩展,然后调用 ssl_is_used()
函数来确定是否正在使用 SSL。 如果连接正在使用 SSL,则函数会返回 t
。 否则,它将返回 f
。 还可以使用以下查询按进程、客户端和应用程序收集有关 Azure Database for PostgreSQL 灵活服务器的 SSL 使用情况的所有信息:
SELECT datname as "Database name", usename as "User name", ssl, client_addr, application_name, backend_type
FROM pg_stat_ssl
JOIN pg_stat_activity
ON pg_stat_ssl.pid = pg_stat_activity.pid
ORDER BY ssl;
对于测试,也可以直接使用 openssl
命令:
openssl s_client -starttls postgres -showcerts -connect <your-postgresql-server-name>:5432
此命令会打印低级协议信息,如 TLS 版本和密码。 必须使用 -starttls postgres
选项。 否则,此命令将报告未在使用任何 SSL。 要使用此命令,至少需要具有 OpenSSL 1.1.1。
若要强制实施最新、最安全的 TLS 版本,以保护从客户端到 Azure Database for PostgreSQL - 灵活服务器的连接,请将 ssl_min_protocol_version
设置为 1.3
。 该设置要求连接到 Azure Database for PostgreSQL 灵活服务器的客户端仅使用此版本的协议,以进行安全通信。 旧客户端可能无法与服务器通信,因为它们不支持此版本。
在客户端上配置 SSL
默认情况下,PostgreSQL 不会对服务器证书执行任何验证。 因此,可在客户端不知情的情况下欺骗服务器标识(例如通过修改 DNS 记录或接管服务器 IP 地址)。 所有 SSL 选项都以加密和密钥交换的形式产生了开销,因此在性能和安全性之间进行权衡。
为了防止欺骗,必须在客户端上使用 SSL 证书验证。
有许多连接参数可用来配置用于 SSL 的客户端。 一些重要参数包括:
ssl
:使用 SSL 连接。 此属性不需要与之关联的值。 它的存在就意味着 SSL 连接。 为了与将来的版本兼容,首选值为true
。 在此模式下,正在建立 SSL 连接时,客户端驱动程序会验证服务器的标识,防止中间人攻击。 它会检查服务器证书是否由受信任的颁发机构签名,并且你正在连接到的主机是否与证书中的主机名相同。sslmode
:如果需要加密,并且希望连接在无法加密的情况下失败,请设置sslmode=require
。 此设置可确保服务器配置为接受此主机/IP 地址的 SSL 连接,并且服务器能够识别客户端证书。 如果服务器不接受 SSL 连接,或者无法识别客户端证书,连接将失败。 下表列出了此设置的值:SSL 模式 说明 disable
没有使用加密。 allow
如果 f 服务器设置需要或强制加密,则使用加密。 prefer
如果 f 服务器设置允许加密,则使用加密。 require
使用了加密。 它可确保服务器配置为接受此主机 IP 地址的 SSL 连接,并且服务器能够识别客户端证书。 verify-ca
使用了加密。 根据客户端上存储的证书验证服务器证书签名。 verify-full
使用了加密。 根据客户端上存储的证书验证服务器证书签名和主机名。 基于 libpq 的客户端(例如 psql)和 JDBC 所用的默认
sslmode
模式有所不同。 基于 libpq 的客户端默认为prefer
。 JDBC 客户端默认为verify-full
。sslcert
、sslkey
和sslrootcert
:这些参数可以替代客户端证书、PKCS-8 客户端密钥和根证书的默认位置。 它们分别默认为/defaultdir/postgresql.crt
、/defaultdir/postgresql.pk8
和/defaultdir/root.crt
,其中defaultdir
在 nix systems 中为${user.home}/.postgresql/
,而在 Windows 上为%appdata%/postgresql/
。
CA 是负责颁发证书的机构。 受信任的证书颁发机构是有权验证某人是谁的实体。 为了使此模型正常工作,所有参与者都必须就一组受信任的 CA 达成一致。 所有操作系统和大多数 Web 浏览器都附带了一组受信任的 CA。
使用 verify-ca
和 verify-full
sslmode
配置设置也可以称为证书固定。 在这种情况下,PostgreSQL 服务器上的根 CA 证书必须与客户端上的证书的证书签名、甚至主机名匹配。
当 CA 在 PostgreSQL 服务器证书上更改或过期时,可能需要定期更新客户端存储的证书。 若要确定是否正在固定 CA,请参阅证书固定和 Azure 服务。
若要详细了解客户端上的 SSL\TLS 配置,请参阅 PostgreSQL 文档。
对于使用 verify-ca
和 verify-full
sslmode
配置设置(即证书固定)的客户端,必须将以下三个根 CA 证书部署到客户端证书存储:
- DigiCert 全局根 G2 和 Microsoft RSA 根 CA 2017 根 CA 证书,因为服务将从 Digicert 迁移到 Microsoft CA。
- Digicert 全局根 CA,为了确保兼容旧版。
在证书固定方案中下载根 CA 证书和更新应用程序客户端
若要在证书固定方案中更新客户端应用程序,可以下载证书:
- Microsoft RSA 根 CA 2017
- DigiCert 全局根 G2
- DigiCert 全局根 CA
若要将证书导入客户端证书存储,可能必须在从上述 URI 下载证书文件之后,将证书 .crt 文件转换为 .pem 格式。 可以使用 OpenSSL 实用工具执行这些文件转换:
openssl x509 -inform DER -in certificate.crt -out certificate.pem -outform PEM
有关使用新的根 CA 证书更新客户端应用程序证书存储的信息记录在更新应用程序客户端的客户端 TLS 证书中。
重要
某些 Postgres 客户端库在使用 sslmode=verify-full
设置时,与使用中间证书交叉签名的根 CA 证书的连接可能会失败。 结果是备用信任路径。 在这种情况下,我们建议显式指定 sslrootcert
参数。 或者,将 PGSSLROOTCERT
环境变量设置为本地路径,其中将 Microsoft RSA 根 CA 2017 根 CA 证书放置在 %APPDATA%\postgresql\root.crt
的默认值中。
具有证书固定方案的只读副本
将根 CA 迁移到 Microsoft RSA 根 CA 2017 时,新创建的副本在较新的根 CA 证书上比之前创建的主服务器可行。 对于使用 verify-ca
和 verify-full
sslmode
配置设置(即证书固定)的客户端,必须中断连接才能接受这三个根 CA 证书:
- Microsoft RSA 根 CA 2017
- DigiCert 全局根 G2
- DigiCert 全局根 CA
此时,Azure Database for PostgreSQL - 灵活服务器不支持基于证书的身份验证。
在证书固定方案中通过连接 psql 来测试客户端证书
在证书固定方案中,可以从客户端使用 psql
命令行测试与服务器的连接:
$ psql "host=hostname.postgres.database.azure.com port=5432 user=myuser dbname=mydatabase sslmode=verify-full sslcert=client.crt sslkey=client.key sslrootcert=ca.crt"
有关 SSL 和证书参数的更多信息,请参阅 psql 文档。
测试 TLS/SSL 连接
在尝试从客户端应用程序访问已启用 SSL 的服务器之前,请确保可以通过 psql 访问它。 如果建立了 SSL 连接,应会看到类似于以下示例的输出:
psql (14.5)SSL 连接(协议:TLSv1.2,密码:ECDHE-RSA-AES256-GCM-SHA384,位:256,压缩:关闭)键入“help”以获取帮助。
还可以加载 sslinfo 扩展,然后调用 ssl_is_used()
函数来确定是否正在使用 SSL。 如果连接正在使用 SSL,则函数会返回 t
。 否则,它将返回 f
。
密码套件
密码套件是一组加密算法。 TLS/SSL 协议使用密码套件中的算法来创建密钥并对信息加密。
密码套件显示为看似随机信息的长字符串,但该字符串的每个段都包含重要信息。 通常,此数据字符串包含几个关键组件:
- 协议(即 TLS 1.2 或 TLS 1.3)
- 密钥交换或协议算法
- 数字签名(身份验证)算法
- 批量加密算法
- 消息验证码算法 (MAC)
不同版本的 TLS/SSL 支持不同的密码套件。 TLS 1.2 密码套件无法与 TLS 1.3 连接协商,反之亦然。
目前,Azure Database for PostgreSQL - 灵活服务器支持采用 TLS 1.2 协议版本并属于 HIGH:!aNULL 类别的许多密码套件。
排查 TLS/SSL 连接错误故障
排查 TLS/SSL 协议版本兼容性问题的第一步是确定你或你的客户在尝试从客户端访问 TLS 加密的 Azure Database for PostgreSQL 灵活服务器时看到的错误消息。 根据应用程序和平台的不同,错误消息可能会有所不同。 在许多情况下,它们指向根本问题。
若要确定 TLS/SSL 协议版本兼容性,请检查数据库服务器和应用程序客户端的 TLS/SSL 配置,确保它们支持兼容的版本和密码套件。
分析数据库服务器和客户端的 TLS/SSL 版本与密码套件之间的任何差异或差距。 尝试通过启用或禁用某些选项、升级或降级软件或者更改证书或密钥来解决它们。 例如,可能需要根据安全性和兼容性要求在服务器或客户端上启用或禁用特定的 TLS/SSL 版本。 例如,可能需要禁用 TLS 1.0 和 TLS 1.1,这些 TLS 被视为不安全和已弃用,并启用 TLS 1.2 和 TLS 1.3(更安全且更新式)。
由 Microsoft RSA 根 CA 2017 颁发的最新证书在链中具有由 Digicert 全局根 G2 CA 交叉签名的中间证书。 某些 Postgres 客户端库在使用
sslmode=verify-full
或sslmode=verify-ca
设置时,与使用中间证书交叉签名的根 CA 证书的连接可能会失败。 结果是备用信任路径。若要解决这些问题,请将所有三个必需的证书添加到客户端证书存储或显式指定
sslrootcert
参数。 或者,将PGSSLROOTCERT
环境变量设置为本地路径,其中将 Microsoft RSA 根 CA 2017 根 CA 证书放置在%APPDATA%\postgresql\root.crt
的默认值中。