客户端应用程序和数据库服务器之间的连接始终将加密与行业标准传输层安全性(TLS)配合使用,以前称为安全套接字层(SSL)。
注释
open source PostgreSQL 在其命令、变量和文档中使用旧名称 SSL,以避免中断现有实现。 本文使用首字母缩略词 TLS,而在命令名称和变量中使用 SSL。
Azure Database for PostgreSQL支持使用 TLS 1.2 和 1.3 的加密连接。 服务器拒绝所有尝试使用 TLS 1.0 和 TLS 1.1 加密流量的传入连接。
默认情况下,服务器在客户端和服务器之间强制实施安全连接。 若要禁用此强制,并允许加密和未加密的客户端通信,请将服务器参数 require_secure_transport 更改为 OFF。 还可以通过设置服务器参数来设置 ssl_max_protocol_version TLS 版本。
请勿禁用 Tls。
重要
Microsoft正在更新Azure Database for PostgreSQL的TLS证书,以轮换证书颁发机构和更新的证书链。
如果客户端 配置使用 TLS 的建议配置,则无需执行作。
根证书轮换计划:
- 从 2026 年 3 月 9 日起,针对中国区域的根 CA 证书,将从 DigiCert 全球根 CA (G1) 更新为 DigiCert 全球根 G2。
客户端 TLS 配置
默认情况下,PostgreSQL 不会验证服务器证书。 由于此默认行为,客户端无法检测服务器标识是否被欺骗(例如,如果有人修改 DNS 记录或接管服务器 IP 地址)。 若要防止此类欺骗,请对客户端启用 TLS 证书验证。
可以为客户端的 TLS 设置配置许多连接参数。 一些重要事项包括:
ssl:使用 TLS 进行连接。 此属性不需要值。 它的存在表明是 TLS 连接。 为了与将来的版本兼容,请使用值true。 在此模式下,建立 TLS 连接时,客户端驱动程序会验证服务器的标识,以防止中间人攻击。sslmode:如果需要加密,并且希望连接无法加密时失败,请将此参数设置为require。 此设置可确保服务器配置为接受此主机或 IP 地址的 TLS 连接,并且服务器能够识别客户端证书。 如果服务器不接受 TLS 连接或无法识别客户端证书,则连接将失败。 下表列出了此设置的值:sslmodeExplanation disable不使用加密。 Azure Database for PostgreSQL需要 TLS 连接,因此不要使用此设置。 allow如果服务器设置需要加密或强制执行加密,则使用加密。 Azure Database for PostgreSQL需要 TLS 连接,因此此设置等效于 prefer。prefer如果服务器设置允许加密,则使用加密。 Azure Database for PostgreSQL需要 TLS 连接。 require使用了加密。 它确保服务器配置为接受 TLS 连接。 verify-ca使用了加密。 使用客户端上存储的受信任根证书验证服务器证书。 verify-full使用了加密。 将服务器证书与存储在客户端上的证书进行验证。 它还会验证服务器证书是否使用与连接相同的主机名。 除非私有 DNS 解析器使用不同的名称来引用 Azure Database for PostgreSQL 服务器,否则请使用此设置。
默认sslmode模式在基于libpq的客户端(例如PSQL和JDBC)之间有所不同。 基于 libpq 的客户端默认为 prefer。
JDBC 客户端默认为 verify-full.
-
sslcert、sslkey和sslrootcert:这些参数替代客户端证书的默认位置、PKCS-8 客户端密钥和根证书。 它们默认分别位于/defaultdir/postgresql.crt、/defaultdir/postgresql.pk8和/defaultdir/root.crt,其中在 Linux 系统中为defaultdir,在 Windows 中为${user.home}/.postgresql/。
重要
在使用 sslmode=verify-full 设置和用于交叉签名中间证书的根 CA 证书时,某些 Postgres 客户端库可能无法连接。 此配置会导致替代信任路径。 在这种情况下,显式指定 sslrootcert 参数。 或者,将 PGSSLROOTCERT 环境变量从默认值 %APPDATA%\postgresql\root.crt 修改为存储 Microsoft RSA 根 CA 2017 根 CA 证书的本地路径。
安装受信任的根证书颁发机构(CA)
下载并转换根 CA 证书
对于将系统证书存储用于受信任的根证书的 Windows 客户端,无需执行任何操作,因为 Windows 通过 Windows Update 部署新的根 CA 证书。
对于 Java 客户端、VS Code 扩展和其他不使用系统存储的客户端(例如 PSQLPerl),以及 Linux 上的客户端:需要下载根 CA 证书并将其合并到 PEM 文件中。 至少应包含以下根 CA 证书:
注释
对于中国区域和具有轮换扩展的客户: Digicert Global Root CA(pem 文件) 仍然有效:将其包含在合并的 PEM 文件中。
包括所有Azure根 CA 证书,以便在Azure Database for PostgreSQL使用的根 CA 发生更改时,减少将来对合并文件更新的需求。 可以在 Azure 证书颁发机构详细信息中找到Azure根 CA 证书的列表。
若要将证书导入客户端证书存储,可能需要将任何 CRT 格式证书转换为 PEM 格式,并将 PEM 文件连接成单个文件。 可以使用 OpenSSL X509 实用工具 将 CRT 文件转换为 PEM。
openssl x509 -inform DER -in certificate-filename.crt -out certificate-filename.pem -outform PEM
将根 CA 证书合并到单个 PEM 文件中
对于某些客户端,可以使用任何文本编辑器或命令行工具将所有 PEM 文件连接到单个文件中。
-----BEGIN CERTIFICATE-----
(Root CA1 content: DigiCertGlobalRootG2.crt.pem)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Root CA2 content: Microsoft ECC Root Certificate Authority 2017.crt.pem)
-----END CERTIFICATE-----
对于中国区域和具有轮换扩展的客户:
-----BEGIN CERTIFICATE-----
(Root CA0 content: DigiCertGlobalRootCA.crt.pem)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Root CA1 content: DigiCertGlobalRootG2.crt.pem)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Root CA2 content: Microsoft ECC Root Certificate Authority 2017.crt.pem)
-----END CERTIFICATE-----
合并和更新 Java 应用程序的根 CA 证书
自定义 Java 应用程序使用名为 cacerts的默认密钥存储,其中包含受信任的证书颁发机构 (CA) 证书。
cacerts证书文件驻留在安全属性目录中java.home\lib\security,其中java.home运行时环境目录(jreSDK 中的目录或 Java™ 2 运行时环境的顶级目录)。
若要使用 PostgreSQL 更新客户端证书固定方案的客户端根 CA 证书,请使用以下说明:
cacerts检查 Java 密钥存储,查看它是否已包含所需的证书。 可以使用以下命令列出 Java 密钥存储中的证书:keytool -list -v -keystore ..\lib\security\cacerts > outputfile.txt如果客户端的 Java 密钥存储中不存在必要的证书,您可以在输出中进行检查,请按照以下说明继续操作:
创建自定义密钥存储的备份副本。
下载证书文件,并将其保存在本地,可在其中引用它们。
生成包含所有所需根 CA 证书的组合 CA 证书存储。 以下示例演示如何为 PostgreSQL Java 用户使用 DefaultJavaSSLFactory。
keytool -importcert -alias PostgreSQLServerCACert -file "DigiCertGlobalRootG2.crt.pem" -keystore truststore -storepass password -noprompt keytool -importcert -alias PostgreSQLServerCACert2 -file "Microsoft ECC Root Certificate Authority 2017.crt.pem" -keystore truststore -storepass password -noprompt ...
更新 Azure App 服务中的根 CA 证书
对于连接到Azure Database for PostgreSQL灵活服务器实例的 Azure App 服务,存在两种更新客户端证书的可能方案。 方案取决于您如何在部署到 Azure 应用服务的应用程序中使用 SSL。
- 在 Azure Database for PostgreSQL 灵活服务器实例发生更改之前,请在 App Service 平台级别添加新证书。 如果您在应用程序中使用了App Service平台中包含的SSL证书,则无需执行任何操作。 有关详细信息,请参阅Azure App Service文档中在 Azure App Service 中添加和管理 TLS/SSL 证书。
- 如果在代码中显式包含 SSL 证书文件的路径,则需要下载新证书并更新代码以使用它。
在使用 Azure Kubernetes Service (AKS) 的客户端时,更新根 CA 证书。
如果您尝试使用托管在 Azure Kubernetes 服务(AKS)中的应用程序连接到 Azure Database for PostgreSQL,那么这与从专用客户主机环境进行访问类似。 请参阅 AKS 文档中的详细说明。
在 Windows 上更新 .NET (Npgsql) 用户的根 CA 证书
对于 Windows 上的 .NET(Npgsql)用户,在连接到 Azure Database for PostgreSQL flexible server 实例时,请确保在受信任的根证书颁发机构下的 Windows 证书存储中包含 所有 根 CA 证书。 Windows Update维护标准Azure根证书颁发机构(CA)列表。 如果未包含 建议的配置 中列出的任何证书,请导入缺少的证书。
如何将 TLS 与证书验证配合使用
某些将 PostgreSQL 用于其数据库服务的应用程序框架在安装过程中默认不启用 TLS。 Azure Database for PostgreSQL实例强制实施 TLS 连接,但如果应用程序未针对 TLS 进行配置,则应用程序可能会失败。 请查阅应用程序文档,了解如何启用 TLS 连接。
使用 PSQL
以下示例演示如何使用 PSQL 命令行接口连接到服务器。 使用 sslmode=verify-full 或 sslmode=verify-ca connection string 设置强制实施 TLS 证书验证。 将本地证书文件路径传递给 sslrootcert 参数。
psql "sslmode=verify-full sslrootcert=<path-of-pem-file> host=mydemoserver.postgres.database.chinacloudapi.cn dbname=postgres user=myadmin"
测试 TLS 连接
在尝试从客户端应用程序access已启用 TLS 的服务器之前,请确保可以通过 PSQL 访问它。 如果建立了 TLS 连接,应会看到类似于以下示例的输出:
psql (14.5)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.
还可以加载 sslinfo 扩展 ,然后调用 ssl_is_used() 该函数来确定是否正在使用 TLS。 如果连接使用 TLS,该函数将 t 返回。 否则,它将返回 f。
以编程方式获取 Java 密钥存储中受信任的证书列表
默认情况下,Java 将受信任的证书存储在位于 cacerts 客户端上的 Java 安装文件夹中的特殊文件中。
以下示例读取 cacerts 并将其加载到 KeyStore 对象中:
private KeyStore loadKeyStore() {
String relativeCacertsPath = "/lib/security/cacerts".replace("/", File.separator);
String filename = System.getProperty("java.home") + relativeCacertsPath;
FileInputStream is = new FileInputStream(filename);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
String password = "changeit";
keystore.load(is, password.toCharArray());
return keystore;
}
默认密码 cacerts 是 changeit,但它在实际客户端上应有所不同。 管理员建议在 Java 安装后立即更改密码。
加载 KeyStore 对象后,可以使用 PKIXParameters 类读取存在的证书。
public void whenLoadingCacertsKeyStore_thenCertificatesArePresent() {
KeyStore keyStore = loadKeyStore();
PKIXParameters params = new PKIXParameters(keyStore);
Set<TrustAnchor> trustAnchors = params.getTrustAnchors();
List<Certificate> certificates = trustAnchors.stream()
.map(TrustAnchor::getTrustedCert)
.collect(Collectors.toList());
assertFalse(certificates.isEmpty());
}