连接到MySql时,PHP会忽略ssl证书

Son*_*ngo 13 php mysql ssl openssl ssl-certificate

使用此处此处的PHP手册中的代码

<?php

$mysqli = mysqli_init();
if (!$mysqli) {
    die('mysqli_init failed');
}

$mysqli->ssl_set('/path/to/client-key.pem',   
                 '/path/to/client-cert.pem',
                 '/path/to/ca-cert.pem',
                  NULL,NULL); //<-- Doesn't matter if the paths are right or wrong

if (!$mysqli->options(MYSQLI_INIT_COMMAND, 'SET AUTOCOMMIT = 0')) {
    die('Setting MYSQLI_INIT_COMMAND failed');
}

if (!$mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 5)) {
    die('Setting MYSQLI_OPT_CONNECT_TIMEOUT failed');
}

if (!$mysqli->real_connect('xx.xx.xx.xx', 'my_user', 'my_password', 'my_db')) {
    die('Connect Error (' . mysqli_connect_errno() . ') '
            . mysqli_connect_error());
}

echo 'Success... ' . $mysqli->host_info . "\n";

$mysqli->close();
?>
Run Code Online (Sandbox Code Playgroud)

我无法连接到MySql.它给出以下错误:

Message: SQLSTATE[28000] [1045] Access denied for user 'my_user'@'xx.xx.xx.xx' (using password: YES) <-- the client IP
Run Code Online (Sandbox Code Playgroud)

我把问题缩小到了界限$mysqli->ssl_set(...).

当我向证书传递错误的路径时,它应该SSL certificate error根据此帖子抛出一个用户遇到相同问题而不是它抛出相同的先前访问被拒绝错误.

我设法通过配置ssl连接,在数据库管理员的帮助下使用Navicat连接到服务器,如下所示: 在此输入图像描述

笔记:

  1. 我的PHP版本是5.3.15
  2. 远程数据库服务器上使用的MySql版本是5.5.13-55
  3. Navicat和PHP代码都是从同一台PC运行的.
  4. 数据库管理员创建了一个专门用于测试的ssl_user.此用户被拒绝正常访问,必须使用ssl进行连接.
  5. 没有使用代理.
  6. 我试过PDO,它也遇到了同样的问题.
  7. 我尝试过mysql->connect(),但它会抛出一个糟糕的握手错误,根据手册中的一些注释,它不起作用.
  8. 打开ssl启用 phpinfo() 在此输入图像描述

那么问题是为什么PHP不抱怨证书的错误路径?似乎PHP忽略了我设置证书路径的行!


更新: 我尝试更改我建立连接的行以显式设置端口并使用MYSQLI_CLIENT_SSL:

$mysqli->real_connect('xx.xx.xx.xx', 'my_user', 'my_password', 'my_db','3306',NULL,MYSQLI_CLIENT_SSL)
Run Code Online (Sandbox Code Playgroud)

但是,我收到了这个错误:

Warning: mysqli::real_connect(): (08S01/1043): Bad handshake in ...
Run Code Online (Sandbox Code Playgroud)

更新2:

这是来自数据库服务器的tcpdump的结果:

0x0040:  3142 6164 2068 616e 6473 6861 6b65       1Bad.handshake
13:16:18.133282 IP (tos 0x8, ttl  64, id 40823, offset 0, flags [DF], proto: TCP (6), length: 52) xx.xx.xx.202.mysql > xx.xx.xx.130.42766: F, cksum 0xf15f (correct), 112:112(0) ack 79 win 46 <nop,nop,timestamp 19516376 3465907>
        0x0000:  4508 0034 9f77 4000 4006 c8a7 c0a8 28ca  E..4.w@.@.....(.
        0x0010:  c0a8 2882 0cea a70e b36c 7e8b 7b4d a169  ..(......l~.{M.i
        0x0020:  8011 002e f15f 0000 0101 080a 0129 cbd8  ....._.......)..
        0x0030:  0034 e2b3                                .4..
13:16:18.133433 IP (tos 0x8, ttl  64, id 17337, offset 0, flags [DF], proto: TCP (6), length: 52) xx.xx.xx.130.42766 > xx.xx.xx.202.mysql: F, cksum 0xb695 (correct), 79:79(0) ack 113 win 92 <nop,nop,timestamp 3480910 19516376>
        0x0000:  4508 0034 43b9 4000 4006 2466 c0a8 2882  E..4C.@.@.$f..(.
        0x0010:  c0a8 28ca a70e 0cea 7b4d a169 b36c 7e8c  ..(.....{M.i.l~.
        0x0020:  8011 005c b695 0000 0101 080a 0035 1d4e  ...\.........5.N
        0x0030:  0129 cbd8                                .)..
13:16:18.133452 IP (tos 0x8, ttl  64, id 40824, offset 0, flags [DF], proto: TCP (6), length: 52) xx.xx.xx.202.mysql > xx.xx.xx.130.42766: ., cksum 0xb6c3 (correct), 113:113(0) ack 80 win 46 <nop,nop,timestamp 19516376 3480910>
        0x0000:  4508 0034 9f78 4000 4006 c8a6 c0a8 28ca  E..4.x@.@.....(.
        0x0010:  c0a8 2882 0cea a70e b36c 7e8c 7b4d a16a  ..(......l~.{M.j
        0x0020:  8010 002e b6c3 0000 0101 080a 0129 cbd8  .............)..
        0x0030:  0035 1d4e                                .5.N
Run Code Online (Sandbox Code Playgroud)

xx.xx.xx.202是数据库服务器ip.
xx.xx.xx.130是我的PC ip.

更新3:

我使用以下代码检查了密码长度:

mysql> select length(Password) from mysql.user where User='youruser'
Run Code Online (Sandbox Code Playgroud)

密码长度为41.

更新4:

当我通过远程服务器上的ssh使用命令行连接时(我将整个项目上传到远程服务器),可能会在返回的错误消息中提示:

mysql -u test_ssl -password --ssl-key=/usr/local/apache2/htdocs/certs/client-key.pem --ssl-cert=/usr/local/apache2/htdocs/certs/WRONG-CERTIFICATE.pem
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

SSL error: Unable to get certificate from '/usr/local/apache2/htdocs/certs/WRONG-CERTIFICATE.pem'
ERROR 2026 (HY000): SSL connection error ---> notice the error here
Run Code Online (Sandbox Code Playgroud)

如果我根本不提供任何证书,我会收到以下消息:

-bash-3.2$ mysql -u test_ssl -password
ERROR 1045 (28000): Access denied for user 'test_ssl'@'localhost' (using password: YES)
Run Code Online (Sandbox Code Playgroud)

当我使用PHP使用正确或无效的证书路径连接时,我得到的错误是相同的!

也许这意味着什么?

Son*_*ngo 1

好吧,我们能够解决这个问题,但我不确定这是否是一个实用的解决方案。

首先,我们能够找到问题的根源,即 MySql 客户端库,PHP 使用 SSL 进行连接。PHP 必须遵守这些库才能使用 SSL 进行连接。

此外,MySql 客户端库和 OpenSSL 库之间存在冲突。

解决我们问题的唯一方法是从头开始重新安装所有内容。我们使用了新的服务器、全新的 Mysql(最新版​​本)安装以及所有库、最新的 PHP 版本和最新的 CentOS 发行版。