PHP 到 MySQL 的 SSL 连接

4
我已经成功地在一个网络上的一台服务器上设置了启用SSL的MySQL安装,并可以使用Linux命令行mysql客户端连接到它,但是每次我尝试连接(PHP 5.3.3),我都会收到以下错误信息:
警告:mysqli_real_connect():(HY000/2026):SSL连接错误位于/var/www/html/test.php第18行
我的PHP代码如下,我做错了什么吗?证书权限为777(仅用于测试),对于另一个用户的未加密连接,相同的代码可以正常工作(即将SSL设置注释掉后mysqli可以通常连接到数据库)。
<?php

error_reporting(E_ALL);
ini_set("display_errors", "1");

$obj = mysqli_init();

mysqli_options($obj, MYSQLI_OPT_CONNECT_TIMEOUT, 5);

mysqli_ssl_set($obj,
               '/mysql-ssl-certs/server-key.pem',
               '/mysql-ssl-certs/server-cert.pem',
               '/mysql-ssl-certs/ca-cert.pem',
               NULL,
               NULL);

$link = mysqli_real_connect($obj, 'localhost', 'ssluser', 'some_password', 'test');

if (!$link)
{
    die('<br /><br />Connect Error (' . mysqli_connect_errno() . ') '.mysqli_connect_error());
}

echo 'Success... ' . mysqli_get_host_info($obj) . "\n";

$obj->close();

?>

注意:这里说的是localhost,因为我现在也在本地机器上尝试它,所以我可以确定这不是防火墙问题——我在那里得到了相同的错误... - CoderChris
不,我知道它们在一个奇怪的位置,但是根目录下有一个有效的文件夹,并且为了测试已经设置了chmod 777权限。 - CoderChris
MySQL服务器的错误日志中是否有相关信息?如果可能,请使用--log-warnings=2(或3或99,大于1的某个数字)启动MySQL服务器,请参见http://dev.mysql.com/doc/refman/5.0/en/communication-errors.html。 - VolkerK
顺便问一下,你使用的是哪个版本的MySQL?你的系统还有其他注意事项吗?例如操作系统版本,证书是如何创建的...我不知道这是否相关,但可能会有帮助... - VolkerK
3个回答

8

在这里,PHP(以及mysqli_real_connect)是客户端而不是服务器。您正在使用mysqli_ssl_set进行客户端证书身份验证的配置(并且使用服务器密钥和证书)。

我不确定您如何配置MySQL服务器,但在配置文件的(MySQL)服务器部分应该有类似这样的内容:

ssl-key=/mysql-ssl-certs/server-key.pem
ssl-cert=/mysql-ssl-certs/server-cert.pem
ssl-ca=/mysql-ssl-certs/ca-cert.pem

这些内容与客户端无关(只有 CA 证书才与之相关,但绝对不是服务器的私钥)。

完成后,您可以使用命令行客户端尝试查看服务器是否正确配置:

mysql --ssl-verify-server-cert --ssl-ca=/mysql-ssl-certs/ca-cert.pem --ssl -h hostname ...

或者是这样的(虽然验证服务器证书对于SSL/TLS的有用性确实应该启用)
mysql --ssl-ca=/mysql-ssl-certs/ca-cert.pem --ssl -h hostname ...

这应该至少在命令行上工作。

然后,从PHP中,您有两个选择:

  • use mysqli_ssl_set like you've done, but leaving $key and $cert null, unless you want to use a client-certificate which really ought to be different from your server certificate. (I can't remember whether that works.)
  • possibly easier, omit mysqli_ssl_set altogether and configure this in your global MySQL client configuration file (where PHP should be able to pick it up, possibly /etc/mysql/my.cnf, but this may vary depending on your distribution):

    [client]
    ssl-ca=/mysql-ssl-certs/ca-cert.pem
    

这与服务器配置类似,但位于客户端侧/客户端部分。

对于授权部分(GRANT):

  • REQUIRE SSL 仅要求使用 SSL/TLS
  • REQUIRE ISSUERREQUIRE SUBJECTREQUIRE X509 要求客户端呈现客户端证书以与所需值进行比较(这是需要在客户端侧(配置或mysqli_ssl_set内)使用 ssl-keyssl-cert 的情况)。

你还应该在客户端配置中启用 ssl-verify-server-cert - Bruno
我现在已经把这个搞定了。大部分都已经按照提到的设置完成了,但我喜欢[客户端]的想法——没想到。证书的生成完全按照mysql手册中的说明进行,但奇怪的是,如果我只在mysqli连接中设置ca变量,并将其设置为server-cert.pem,那么从PHP连接的唯一工作方式似乎就是这样。你有什么想法吗?以下是[mysqld]的ssl部分:ssl=1 ssl-ca=/mysql-ssl-certs/ca-cert.pem ssl-capath=/mysql-ssl-certs ssl-cert=/mysql-ssl-certs/server-cert.pem ssl-key=/mysql-ssl-certs/server-key.pem - CoderChris
感谢授权说明。我使用了REQUIRE SSL:建立了SSL连接,但所有本地证书都被忽略了。在设置了REQUIRE X509之后,至少需要客户端密钥和证书文件。 - lmeurs
我遇到了这个确切的问题。我设置了 mysqli_ssl_set($db, null, null, '/path/to/ca-cert.pem', null, null) 到 ca-cert.pem,但是得到了 Warning: mysqli_real_connect(): Unable to locate peer certificate CN in /MySQLConnection.php on line 31 - Justin
@Justin,你最好的选择可能是使用与建立连接所使用的CN相对应的服务器证书。 - Bruno
2
请注意,my.cnf解决方案仅适用于PHP <5.3.0。较新版本的PHP默认使用mysql本地驱动程序(mysqlnd)与服务器通信,它不会读取my.cnf或my.ini文件。http://php.net/manual/en/ref.pdo-mysql.php#pdo.constants.mysql-attr-read-default-file - Mr_Moneybags

0
也许你的 PHP 版本使用 mysqlnd 作为传输驱动程序,该驱动程序尚不支持 SSL(但可能会在未来支持)。

” 是 HTML 标记语言中的一个标签,用于表示段落结束。
<?php
error_reporting(E_ALL);
ini_set("display_errors", "1");
echo 'version: ', phpversion(), "\n";
echo function_exists('mysqli_fetch_all') ? 'mysqlnd' : '--', "\n";

打印?


0

如果你使用的是MySQL 5.7.3之前的版本和标准PHP库,你需要小心:

在MySQL 5.7.3之前,--ssl选项允许但不要求客户端使用SSL连接到服务器。因此,仅使用此选项本身是不足以导致使用SSL连接的。例如,如果你为客户端程序指定了此选项,但服务器未配置为允许SSL连接,则将使用未加密的连接。

http://dev.mysql.com/doc/refman/5.7/en/ssl-options.html#option_general_ssl

在PHP的情况下,如果服务器不支持SSL,MySQL将会默默地失败。

https://www.idontplaydarts.com/2015/03/mysql-with-ssl-does-not-protect-against-active-mitm/


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