使用SSL连接PHP Mysql的PDO出现问题

5

MySQL服务器正在运行php5.3。新的Web服务器正在运行php7.1(从php5.3迁移而来)。当我尝试使用SSL连接MySQL服务器时,它无法工作。

try {
$dbh = new PDO($dsn, $user, $password, array(PDO::MYSQL_ATTR_SSL_KEY  => '/etc/mysql/client-key.pem',
                                             PDO::MYSQL_ATTR_SSL_CERT => '/etc/mysql/client-cert.pem',
                                             PDO::MYSQL_ATTR_SSL_CA   => '/etc/mysql/ca-cert.pem')
              );
    echo "Connestion established";
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}

连接失败:SQLSTATE[HY000] [2002]
PDO::__construct():SSL操作失败,错误代码为1。OpenSSL错误信息:error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed
但是,当我从连接中删除SSL块时,它可以正常工作。我不知道发生了什么。可能是服务器和客户端之间的版本不匹配。因为我正在使用旧的公钥和私钥。
这是因为mysql客户端和服务器版本不匹配吗?
PS:我只在web服务器中升级了php7。

有来自PHP的错误报告吗?在配置中安装并启用SSL后,证书是否仍然有效? - Funk Forty Niner
@Fred-ii-,我在使用try-catch时出现了“php”错误。我从未更改过证书,只是将其从旧的Web服务器复制粘贴到新的服务器上。 - RNK
@Fred-ii-:旧的 Web 服务器使用了 apache2,新的则是 nginx。在哪里可以启用 Nginx 的 mysql-ssl? - RNK
我认为“tls”是关键。 - Rick James
@RickJames:是啊,但我在网上找不到任何相关的信息。希望能尽快得到解决方案! - RNK
显示剩余2条评论
5个回答

3
因为PHP 5.6已经批准SSL处理并默认启用同行验证,所以我相信问题的原因是这个。虽然以下内容不是关于mysql而是关于fsock,但我认为这篇文章回答了你的问题:https://dev59.com/nlwY5IYBdhLWcg3wyqWH#32366242。你可以选择禁用同行验证(这通常不是一个好主意)或修复根证书。确实有必要测试一下禁用同行验证是否是你的问题。
(请注意,我在我的先前回答旁边添加了第二个回答。那不是你的问题的答案,但可能与其他人相关)。

在连接到数据库服务器之前添加了此代码块。stream_context_set_default([ 'ssl' => [ 'verify_peer_name' => false, 'verify_peer' => false ] ]); 仍然出现相同的错误。我有什么遗漏吗? - RNK
你发给我的解决方案是针对这个错误的:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed,但在我的情况下,错误是 tls_process_server_certificate:certificate verify failed - RNK
让我重新创建证书并在两台服务器上尝试。我会随时向您通报状态。 - RNK
@vrijdenker,您不应该在同一个问题上创建多个答案。下次请编写、编辑和修改一个答案。 - Christos Lytras

1
你说你“将SSL密钥从一个服务器复制到另一个服务器”。所以有了一个新服务器?新服务器有一个新的身份,因此远程服务器将拒绝证书,因为ID不匹配。
我认为你应该首先从“known_hosts”文件中删除远程服务器上的行。 然后在您的Nginx服务器上,您应该使用这些SSH密钥手动连接到远程服务器,并进行一次连接,以便将新身份添加到known_hosts中。
之后,我认为它应该可以工作了。
即使上述方法不起作用,我认为最好通过手动连接到远程主机来调试此问题。当这个工作时,你可以尝试设置mysql连接。

keypairs 从 MySQL 服务器生成。我只是更改了部分客户端代码。其次,如果我使用 php5.3 创建新的客户端-服务器,一切都像以前一样工作。可能是 php 版本问题或 apache2 或 nginx 配置问题。你对此有什么想法? - RNK
哎呀,糟糕。抱歉。 - vrijdenker

1
您可以生成新的SSL证书,并确保使用正确的“通用名称”:
CA: hostname 
Server: FQDN, e.g. hostname.example.com 
Client: somename

重要的部分是服务器证书,其中通用名称必须与您连接到的主机相同,例如:hostname.example.com。

如果有两个客户端连接到同一个服务器,那么服务器和这两个客户端的公共名称应该是什么? - RNK
1
当您生成证书时,会要求您提供一些参数,例如“州”(S)、“城市”(L)、“公共名称”(CN)。因此,CN应该是与客户端连接的确切地址。如果您的MySQL运行在db.myhost.com上,则应将db.myhost.com用作CN,并从客户端连接到db.myhost.com。http://info.ssl.com/article.aspx?id=10048 - Max Chernopolsky

0

您需要生成一个新的SSL证书并测试服务器上的端点,以确保其正常工作。之后您应该不会遇到任何问题。我建议使用Let's Encrypt:它是免费、开放和得到广泛支持的。请确保在此之后按照这里的说明进行操作。


0

经过一些尝试和错误,我成功解决了这个问题,而不需要禁用对等验证,这在一定程度上要感谢MySQL文档的帮助:

Important

Whatever method you use to generate the certificate and key files, the Common Name value used for the server and client certificates/keys must each differ from the Common Name value used for the CA certificate. Otherwise, the certificate and key files will not work for servers compiled using OpenSSL. A typical error in this case is:

ERROR 2026 (HY000): SSL connection error:
error:00000001:lib(0):func(0):reason(1)

MySQL documentation

然而,这只是让我走了一半的路。默认情况下,PHP启用了VERIFY_IDENTITY,它要求通用名称与主机名匹配。

这满足了所有条件:

CA:分配一个唯一的名称。可以是任何东西。我只是在我的FQDN前面加上root.

客户端和服务器:分配MySQL服务器的FQDN。这两个值必须匹配。

如果客户端和服务器之间的FQDN不匹配,则VERIFY_IDENTITY将失败。

如果CA、客户端和服务器之间的FQDN匹配,则PHP中的OpenSSL将如MySQL文档中所承诺的那样失败。


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