如何使用 SSL 连接成功连接到我的 Amazon RDS 实例?

上次更新时间:2021 年 10 月 25 日

我想要使用安全套接字层 (SSL) 连接到我的 Amazon Relational Database Service (Amazon RDS) 数据库实例。

简短描述

您可以使用应用程序中的 SSL 或传输层安全性 (TLS) 来加密与运行 MySQL、MariaDB、Microsoft SQL Server、Oracle 或 PostgreSQL 的数据库实例的连接。SSL/TLS 连接通过加密在客户端和数据库实例之间传输的数据来提供一层安全保护。服务器证书通过验证是否正在与 Amazon RDS 数据库实例建立连接来提供额外的安全层。

预置数据库实例时,Amazon RDS 会创建 SSL 证书并在实例上安装该证书。这些证书由证书颁发机构签名。SSL 证书包括数据库实例端点作为 SSL 证书的公用名称,以保护实例免受欺骗攻击。Amazon RDS 创建的 SSL 证书是受信任的根实体,在大多数情况下都可以使用。但是,如果您的应用程序不接受证书链,则证书可能会失败。在这种情况下,您可能需要使用中间证书来连接到您的亚马逊云科技区域。例如,您必须使用中间证书才能使用 SSL 连接到 Amazon GovCloud(美国)区域。

您可以从 Amazon Trusted Services 下载包含所有亚马逊云科技区域的中间证书和根证书的证书捆绑包。如果您的应用程序位于 Microsoft Windows 中并且需要 PKCS7 文件,那么可以从 Amazon Trust Service 中下载 PKCS7 证书捆绑包。此捆绑包包含中间证书和根证书。

解决方法

每个数据库引擎都有自己的实现 SSL/TLS 的过程。要为数据库集群实施 SSL/TLS 连接,请根据您的数据库引擎选择以下选项之一。

Amazon RDS for Oracle

对于 Amazon RDS for Oracle 实例,您可以通过在自定义选项组中添加 SSL 选项来打开 SSL 模式。

Amazon RDS for Oracle 支持传输层安全性 (TLS) 版本 1.0 和 1.2。要使用 Oracle SSL 选项,请使用选项组中的 SQLNET.SSL_VERSION 选项设置。此选项设置允许使用以下值:

  • "1.0" - 客户端只能使用 TLS 1.0 连接到数据库实例。
  • "1.2" - 客户端只能使用 TLS 1.2 连接到数据库实例。
  • “1.2 或 1.0” - 客户端可以使用 TLS 1.2 或 1.0 连接到数据库实例。

对于现有的 Oracle SSL 选项,SQLNET.SSL_VERSION 会自动设置为 "1.0"。如有必要,您可以更改设置。

在连接到使用 Oracle SSL 选项的 Oracle 数据库实例之前,必须将 SQL*Plus 客户端配置为使用 SSL。要通过 JDBC 使用 SSL 连接,您必须创建密钥库,信任 Amazon RDS 根 CA 证书,然后设置 SSL 连接。

使用 JDBC 设置 SSL 连接的示例代码:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
 
public class OracleSslConnectionTest {
    private static final String DB_SERVER_NAME = "example-dns";
    private static final Integer SSL_PORT = "example-ssl-option-port-in-option-group";
    private static final String DB_SID = "example-oracle-sid";
    private static final String DB_USER = "example-username";
    private static final String DB_PASSWORD = "example-password";
    // This key store has only the prod root ca.
    private static final String KEY_STORE_FILE_PATH = "example-file-path-to-keystore";
    private static final String KEY_STORE_PASS = "example-keystore-password";
    public static void main(String[] args) throws SQLException {
        final Properties properties = new Properties();
        final String connectionString = String.format(
                "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCPS)(HOST=%s)(PORT=%d))(CONNECT_DATA=(SID=%s)))",
                DB_SERVER_NAME, SSL_PORT, DB_SID);
        properties.put("example-username", DB_USER);
        properties.put("example-password", DB_PASSWORD);
        properties.put("oracle.jdbc.J2EE13Compliant", "true");
        properties.put("javax.net.ssl.trustStore", KEY_STORE_FILE_PATH);
        properties.put("javax.net.ssl.trustStoreType", "JKS");
        properties.put("javax.net.ssl.trustStorePassword", KEY_STORE_PASS);
        final Connection connection = DriverManager.getConnection(connectionString, properties);
        // If there is no exception, it means that an SSL connection can be opened
    }
}

在使用 SSL 连接到 Amazon RDS for Oracle 实例之前,请确保满足以下条件:

  • RDS 根证书已下载并添加到钱包文件中。此文件存储在由 sqlnet.ora 文件中的 WALLET_LOCATION 参数指定的目录中。
  • 您的 TNS 条目中有正确的 SSL 端口号。
  • Amazon RDS 安全组配置为允许通过 SSL 端口从您的计算机进行入站连接。
  • 防火墙或安全策略已适当配置为允许来自 Amazon RDS 的 SSL 端口上的流量。

Amazon RDS for MariaDB

Amazon RDS for MariaDB 支持 TLS 版本 1.0、1.1、1.2 和 1.3。在单向 TLS 连接中,在没有客户端证书的情况下使用 TLS,并且只能对服务器进行身份验证。因此,只能在一个方向进行身份验证。但是,仍然可以双向加密。通过服务器证书验证,客户端将验证证书是否属于服务器。

要使用 RDS 证书启动 MySQL 5.7 或更高版本,请运行类似于以下内容的命令:

mysql -h myinstance.123456789012.rds-us-east-1.amazonaws.com -u testuser -p --ssl-ca=[full path]global-bundle.pem --ssl-mode=VERIFY_IDENTITY

要使用 RDS 证书启动 MariaDB 客户端,请运行类似于以下内容的命令:

mysql -h myinstance.123456789012.rds-us-east-1.amazonaws.com -u testuser -p --ssl-ca=[full path]global-bundle.pem --ssl-verify-server-cert

要要求特定用户或账户使用 SSL 连接,请根据您的 MariaDB 版本运行以下查询:

ALTER USER 'test'@'%' REQUIRE SSL;

要确认连接是否已加密,请运行以下任一查询:

MariaDB > status;
MariaDB > SHOW VARIABLES LIKE 'have_ssl';

Amazon RDS for MySQL

Amazon RDS for MySQL 支持 TLS 版本 1.0、1.1 和 1.2。

Amazon RDS for MySQL 在以下版本中使用 yassL 进行安全连接:

  • MySQL 版本 5.7.19 和更早的 5.7 版本
  • MySQL 版本 5.6.37 和更早的 5.6 版本

MySQL 在以下版本中使用 OpenSSL 进行安全连接:

  • MySQL 版本 8.0
  • MySQL 版本 5.7.21 及更高版本 5.7 版本
  • MySQL 版本 5.6.39 及更高版本 5.6 版本

默认情况下,如果服务器支持加密连接,MySQL 客户端程序会尝试建立加密连接。要获得与默认加密相关的额外安全性,请使用 —ssl-ca 参数引用包含数据库实例端点作为公用名称的 SSL 证书。SSL 证书可保护实例免受欺骗攻击。

要使用 MySQL 5.7 及更高版本的 —ssl-ca 参数启动客户端,请运行类似于以下内容的命令:

mysql -h myinstance.123456789012.rds-us-east-1.amazonaws.com -u testuser -p --ssl-ca=[full path]global-bundle.pem --ssl-mode=VERIFY_IDENTITY

要要求特定用户或账户使用 SSL 连接,请根据您的 MySQL 版本运行类似于以下内容的查询:

mysql -h myinstance.123456789012.rds-us-east-1.amazonaws.com -u testuser -p --ssl-ca=[full path]global-bundle.pem --ssl-verify-server-cert

对于 MySQL 5.7 及更高版本:

ALTER USER 'testuser'@'%' REQUIRE SSL;

对于 MySQL 5.6 及更低版本:

GRANT USAGE ON *.* TO 'testuser'@'%' REQUIRE SSL;

要确认连接是否已加密,请运行以下任一查询:

mysql> status;
mysql> SHOW VARIABLES LIKE 'have_ssl';

Amazon RDS for Microsoft SQL Server

您可以使用以下方法之一使用 SSL 连接到 SQL Server 数据库实例:

  • 对所有连接强制使用 SSL:使用此方法,连接对客户端是透明的,客户端无需做任何工作即可使用 SSL。要使用此选项,请将 rds.force_ssl 参数设置为 1 (on)。原定设置下,rds.force_ssl 参数设置为 0 (off)。rds.force_ssl 参数是静态的。因此,更改值后,必须重启数据库实例才能使更改生效。
  • 加密特定连接:此方法设置来自特定客户端计算机的 SSL 连接,并且必须对客户端上的连接进行加密。

要加密来自其他 SQL 客户端的连接,请将 cryppt=true 附加到连接字符串中。在 GUI 工具的连接页面上,此字符串可以作为选项或属性使用。

通过运行以下查询来确认您的连接已加密:

SELECT ENCRYPT_OPTION FROM SYS.DM_EXEC_CONNECTIONS WHERE SESSION_ID = @@SPID;

验证查询对于 cryppt_option 是否返回 true

注意:要为使用 JDBC 进行连接的客户端激活 SSL 加密,您可能需要将 Amazon RDS SQL 证书添加到 Java CA 证书 (cacerts) 存储中。你可以通过使用 keytool 实用程序来做到这一点。

Amazon RDS for PostgreSQL

Amazon RDS 支持 PostgreSQL 数据库实例的 SSL 加密。使用 SSL,您可以加密应用程序和 PostgreSQL 数据库实例之间的 PostgreSQL 连接。您还可以强制与 PostgreSQL 数据库实例的所有连接都使用 SSL。Amazon RDS for PostgreSQL 支持 TLS 版本 1.1 和 1.2。

在通过 SSL 连接到 Amazon RDS for PostgreSQL 数据库实例之前,请执行以下操作:

  1. 下载证书。
  2. 将证书导入操作系统。

有关更多信息,请参阅通过 SSL 连接到 PostgreSQL 数据库实例

使用 sslrootcert 参数来引用证书。例如,sslrootcert=rds-ssl-ca-cert.pem。

$ psql "host=myinstance.123456789012.rds-us-east-1.amazonaws.com port=5432 user=testuser dbname=testpg sslmode=verify-full sslrootcert=global-bundle.pem"

您还可以通过在自定义参数组中将 rds.force_ssl 设置为 1 (on),为 PostgreSQL 实例配置到 RDS 的连接使用 SSL。原定设置情况下,此值设置为 0 (off)

当您将 rds.force_ssl 设置为 1 (on) 时,将修改数据库实例的 pg_hba.conf 文件以支持新的 SSL 配置。您可以使用 pg_hba_file_rules 视图查看 pg_hba.conf 文件的内容摘要。

当您将 rds.force_ssl 设置为 0 (off) 时,pg_hba.conf 文件看起来类似于以下内容:

SELECT * FROM pg_hba_file_rules;

 line_number | type  |     database      | user_name  | address  | netmask | auth_method | options | error 
-------------+-------+-------------------+------------+----------+---------+-------------+---------+-------
           4 | local | {all}             | {all}      |          |         | md5         |         | 
          10 | host  | {all}             | {rdsadmin} | samehost |         | md5         |         | 
          11 | host  | {all}             | {rdsadmin} | all      |         | reject      |         | 
          12 | host  | {rdsadmin}        | {all}      | all      |         | reject      |         | 
          13 | host  | {all}             | {all}      | all      |         | md5         |         |
          14 | host  | {replication}     | {all}      | samehost |         | md5         |         | 
          15 | host  | {rds_replication} | {all}      | all      |         | md5         |         | 
(7 rows)

当您将 rds.force_ssl 设置为 1 (on) 时,pg_hba.conf 文件看起来类似于以下内容:

SELECT * FROM pg_hba_file_rules;

line_number |  type   |     database      | user_name  | address  | netmask | auth_method | options | error 
-------------+---------+-------------------+------------+----------+---------+-------------+---------+-------
          4 | local   | {all}             | {all}      |          |         | md5         |         |
         10 | host    | {all}             | {rdsadmin} | samehost |         | md5         |         |
         11 | host    | {all}             | {rdsadmin} | all      |         | reject      |         |
         12 | host    | {rdsadmin}        | {all}      | all      |         | reject      |         |
         13 | hostssl | {all}             | {all}      | all      |         | md5         |         |
         14 | host    | {replication}     | {all}      | samehost |         | md5         |         |
         15 | hostssl | {rds_replication} | {all}      | all      |         | md5         |         |

您可能会注意到,当 rds.force_ssl 设为 1 (on) 后,line_number (13) 的类型值会更新为 hostssl

在实例上激活 SSL 连接后,当您启动与 RDS for PostgreSQL 实例的连接时,会看到类似以下内容的消息:

$ psql "host=myinstance.123456789012.rds-us-east-1.amazonaws.com port=5432 user=testuser dbname=testpg"
. . .
SL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

所有非 SSL 连接都会被拒绝,并显示以下消息:

$ psql "host=myinstance.123456789012.rds-us-east-1.amazonaws.com port=5432 user=testuser dbname=testpg sslmode=disable"
psql: FATAL: no pg_hba.conf entry for host "host.ip", user "testuser", database "testpg", SSL off
$

这篇文章对您有帮助吗?


您是否需要账单或技术支持?