如何通过SSL连接到Amazon RDS?

20

我正在尝试建立一个通过Amazon RDS托管的MySQL数据库的SSL连接,但是我对如何连接感到困惑。

根据Amazon的文档,我需要下载名为"rds-ca-2015-root.pem"的CA证书,并在我的SSL连接中使用它。 我将要连接的数据库用户设置为需要SSL。

在PHP中,我包含了以下代码来启动连接:

$mysqli = mysqli_init();
mysqli_options($mysqli, MYSQLI_OPT_SSL_VERIFY_SERVER_CERT, true);
$mysqli->ssl_set(NULL, NULL, "/path/to/pem", NULL, NULL);
$mysqli->real_connect("host", "username", "password", "name", 3306, NULL, MYSQLI_CLIENT_SSL);

然而,无论我在ssl_set()的第三个参数中指定哪个路径(即使路径无效),SSL连接都会成功建立。第三个参数只是不能设置为NULL。

我通过运行此查询进行验证:SHOW STATUS LIKE 'Ssl_cipher';。输出验证了连接已加密(Ssl_cipher => AES256-SHA)。

请问有人可以解释一下这是如何工作的吗?当路径不正确时,为什么连接仍然可以成功工作?RDS服务器是如何进行验证的?


1
如果您在Unix机器上运行此程序,取决于您使用的OpenSSL版本和配置,有一个目录保存着您系统范围内的证书。OpenSSL将在该路径下寻找适当的证书。这里不清楚的是(假设您在Unix机器上),您是否已将证书放置在该目录中。如果您已经成功连接,那么必须已经放置了证书。您可以在此处获取有关特定目录位置的更多信息:http://serverfault.com/questions/62496/ssl-certificate-location-on-unix-linux - mba12
2
我在EC2实例上进行了相当多的测试,看起来设置PEM公钥路径的行甚至不需要,连接AWS文档中包含PEM的行也不需要。这意味着@mba12是正确的,即RDS证书必须已经存在于实例中,而不需要引用。如果我引用它们不正确,那么就会出现错误。您是从AWS VPC外部进行测试吗? - scrowler
@RobbieAverill 我已经有一年左右没有经常使用AWS了,但当我使用时,我总是使用PEM文件并指定路径。我从未尝试将PEM文件集成到特定于AWS的openssl中。但对于其他通用Linux框,将证书放入OpenSSL默认目录效果很好。您只需要小心确保正确获取特定框的openssl配置即可。那是唯一让我有点问题的事情。正如我提到的,openssl有几种不同的版本。 - mba12
@Jack Humphries,你现在有很多跟进/后续问题。如果你能回答它们,那就太好了,这样我们就可以尝试回答你的问题。 - Emil Vikström
在服务器上上传.pem文件的位置在哪里? - urfusion
大家好,感谢你们的回复。我在服务器的任何预期目录中都没有看到PEM文件,所以我不认为它已经在服务器上了。我遇到的问题是,为什么即使我引用的证书无效或路径无效时,连接也会成功。有什么想法吗?有什么你想让我尝试的吗? - Jack Humphries
2个回答

1
据我所知 - 如果您要求或需要与RDS MySQL建立SSL连接,您将会得到一个 - 无论本地证书副本是否有效或可读。
我正在Drupal中使用以下配置,并且不管我在证书路径中放置什么,我都会得到SSL连接:
$databases['default']['default'] = [
  'database' => 'drupal_db',
  'username' => 'db_user',
  'password' => 'db_password',
  'host' => 'hostname',
  'port' => '3306',
  'driver' => 'mysql',
  'prefix' => '',
  'pdo' => array(
      PDO::MYSQL_ATTR_SSL_CA => '/etc/ssl/certs/rds-combined-ca-bundle.pem',
      PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false,
  ),  
];

然而,如果将MYSQL_ATTR_SSL_VERIFY_SERVER_CERT值设置为“false”,我会收到连接错误并导致Drupal失败。到目前为止,我还没有找到任何关于为什么无法验证证书或如何成功验证的解释!

1
RDS文档实际上解释了为什么会发生这种情况,并建议您甚至不需要CA证书:
Amazon RDS于2015年3月23日开始更新所有DB实例的SSL证书,但没有启动实例的重新启动。执行这些更新时不会产生任何运营影响或停机时间,在许多情况下,我们将在您的维护窗口中执行更新。如果您已经执行了更新,则Amazon RDS不会为您的实例更新证书。另请注意,Amazon RDS不会在AWS GovCloud(美国)和中国(北京)地区更新证书。
无论您是手动更新证书还是Amazon RDS更新证书,都必须重新启动DB实例才能使新证书生效。您可以自行决定何时手动重启DB实例,但必须在旧证书(rds-ca-2010)于2015年4月3日到期之前更新证书并重新启动实例。
您可以使用Amazon RDS控制台检查您的DB实例所使用的证书颁发机构(CA)。 CA在DB实例详细信息的“安全性和网络”部分下列出。如果您的实例显示为rds-ca-2015,则已成功应用新证书。您仍需要重新启动数据库实例并更新客户端应用程序以使用新的SSL证书。
如果Amazon RDS控制台显示您的实例CA为rds-ca-2010,则尚未将新证书应用于您的数据库实例。请按照以下说明更新数据库实例上的SSL证书。
第3个参数实际上被客户端忽略了。我打赌通过将第3个参数设置为NULL,如果所有参数都为null,则调用mysqli::ssl_set()没有任何意义。
尝试完全删除该函数调用。

你在RDS文档中引用的内容指的是服务器,这并不能说明为什么他在EC2实例上以客户端身份运行的php代码,尽管进行了ssl_set调用,但仍能成功连接到服务器。OP的问题是关于连接的客户端,而不是关于RDS的。 - S. Imp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接