PHP通过私有CA证书远程SSL连接MySQL失败问题求助
问题描述
两台服务器均使用Ubuntu Server 22.04、MySQL 8.0、PHP 8.1。Server1上的PHP文件通过PDO尝试连接Server2的MySQL,配置了私有CA证书相关参数:
$pdo = new PDO('mysql:host=<server2_ip>;dbname=<dbname>', '<user>', '<password>', array( PDO::MYSQL_ATTR_SSL_KEY =>'<path>/client-key.pem', PDO::MYSQL_ATTR_SSL_CERT=>'<path>/client-cert.pem', PDO::MYSQL_ATTR_SSL_CA =>'<path>/ca.pem' ) ); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->exec('SET NAMES "utf8"');
私有SSL证书在Server2生成并同步到Server1。通过Server1命令行执行mysql -u <user> -h <server2_ip> -p可正常连接,但PHP文件执行时抛出PDOException:failed loading cafile stream。
尝试将ca.pem添加到/etc/ssl/certs目录并修改PDO的SSL_CA路径后,出现新错误:
SSL operation failed with code 1. OpenSSL Error messages: error:0200008A:rsa routines::invalid padding error:02000072:rsa routines::padding check failed error:1C880004:Provider routines::RSA lib error:06880006:asn1 encoding routines::EVP lib error:0A000086:SSL routines::certificate verify failed
不想通过添加PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false禁用证书验证(存在中间人攻击风险),寻求安全解决方法。
安全解决方法
1. 检查证书文件的路径与权限
- 确保证书文件使用绝对路径,避免PHP因工作目录问题找不到文件;
- 设置正确的权限:
ca.pem和client-cert.pem权限设为644,所属用户/组包含PHP运行用户(通常是www-data);client-key.pem权限设为600,仅允许所有者读取,避免密钥泄露;
- 执行命令调整权限:
chmod 644 /path/to/ca.pem /path/to/client-cert.pem chmod 600 /path/to/client-key.pem chown www-data:www-data /path/to/*.pem
2. 验证MySQL服务器证书的有效性与匹配性
- 在Server1上用OpenSSL命令验证Server2的证书链:
检查输出是否包含openssl s_client -connect <server2_ip>:3306 -CAfile /path/to/ca.pemVerify return code: 0 (ok),若否则说明证书链存在问题; - 确认Server2的MySQL证书的**Common Name(CN)或Subject Alternative Name(SAN)**包含你连接时使用的
<server2_ip>(或主机名)——PHP的PDO会严格验证这一点,而命令行mysql默认验证较宽松,这是常见的差异点。
3. 检查PHP的OpenSSL配置
- 确认PHP已启用openssl扩展:查看
php.ini中extension=openssl未被注释; - 可以在PHP中执行以下代码查看OpenSSL的证书搜索路径,确保你的CA证书位置符合要求:
var_dump(openssl_get_cert_locations());
4. 确认MySQL用户权限配置
- 在Server2的MySQL中,确保目标用户被配置为强制SSL连接,且允许从Server1的IP访问:
GRANT ALL ON <dbname>.* TO '<user>'@'<server1_ip>' REQUIRE SSL; FLUSH PRIVILEGES;
5. 重新同步证书文件
若上述步骤无效,可能是证书在同步过程中损坏,重新用scp从Server2同步证书:
scp user@server2:/path/to/{ca.pem,client-cert.pem,client-key.pem} /local/path/
内容的提问来源于stack exchange,提问作者multivax
相关产品推荐
相关产品推荐

