CentOS PHP curl 无法协商一组可接受的安全参数

Posted

技术标签:

【中文标题】CentOS PHP curl 无法协商一组可接受的安全参数【英文标题】:CentOS PHP curl unable to negotiate an acceptable set of security parameters 【发布时间】:2016-02-01 14:03:33 【问题描述】:

在 Ubuntu 14.04.3 上,此代码运行良好:

$url_login = "https://test.example.com/login.do";

$cert_file = '/var/www/html/test/cert.pem';
$ssl_key = '/var/www/html/test/cert_private.pem';

$post_fields = 'userAction=1&cancelReason=&cancelType=&account=&memoType=&userText=&userid=99999999&password=xxxxxxxxxxxxxxxx';

$ch = curl_init();

$options = array( 
    CURLOPT_RETURNTRANSFER => 1,
    CURLOPT_HEADER         => 1,
    CURLOPT_FOLLOWLOCATION => 1,
    CURLOPT_SSL_VERIFYHOST => 0,
    CURLOPT_SSL_VERIFYPEER => 0,

    CURLOPT_USERAGENT => 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)',
    CURLOPT_VERBOSE        => 0,
    CURLOPT_URL => $url_login ,

    CURLOPT_SSLCERT => $cert_file ,
    CURLOPT_SSLCERTTYPE, 'PEM',
    CURLOPT_SSLKEY => $ssl_key,

    CURLOPT_COOKIESESSION => 1,

    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $post_fields
);

curl_setopt_array($ch , $options);

$output = curl_exec($ch);

Ubuntu 上的 php 使用 curl 和 openssl。

在 Centos 7 上如果失败:

Curl Error : SSL peer was unable to negotiate an acceptable set of security parameters.

curl 和 nss 在这里。

“cert.pem”仅包含带有证书链的客户端证书,“cert_private.pem”包含不受密码保护的私钥。 (-----开始 RSA 私钥-----)。

我怎样才能让上面的 PHP 代码同时工作? curl 的 openssl 和 nss 实现?

【问题讨论】:

【参考方案1】:

如何纠正:

CURLOPT_SSLCERTTYPE, 'PEM',

CURLOPT_SSLCERTTYPE => 'PEM',

?

【讨论】:

您能否发布您的证书的密钥类型、签名(哈希)算法?您是否检查了 HTTP 服务器配置(它允许使用哪些密码套件)?【参考方案2】:

我在使用 nss 的客户端证书身份验证时也遇到过这个问题,而 openssl 工作正常。

经过大量测试,这是我与我们尝试联系的服务器建立的:

使用带有客户端证书的 TLS v1.2(某些情况下为默认)的 curl 失败 curl 使用 TLS v1.2 和服务器需要的客户端证书,但客户端未使用,连接成功。但是客户端未通过身份验证。 curl 使用带有客户端证书的 TLS v1.0 成功

无论密码套件如何,都会发生上述情况,通常我们使用的是 rsa_aes_256_cbc_sha_256。

快速解决方法是强制使用 TLS v1.0:

CURLOPT_SSLVERSION => 4,

显然这并不理想,您的服务器可能不支持它。

另一个选择是用 openssl 甚至 GnuTLS(虽然我没有测试过后者)而不是 nss 来编译 curl。同样,这可能不是一个选择。

到目前为止,这表明 NSS 存在问题。如果进一步调试产生任何有用的信息,我会更新这个答案。

仅供参考,这是在命令行中使用 curl 的完整错误信息:

* NSS error -12227 (SSL_ERROR_HANDSHAKE_FAILURE_ALERT)
* SSL peer was unable to negotiate an acceptable set of security parameters.
* Closing connection 0
curl: (35) SSL peer was unable to negotiate an acceptable set of security parameters.

2015 年 11 月 24 日更新: 使用 Wireshark 和 ssltap 进行的进一步测试显示初始握手成功,并且连接到达客户端发送 ChangeCipherSpec,然后是其加密的“完成”消息。

然后,服务器应解密客户端的“完成”消息,验证哈希和 MAC,并以自己的加密“完成”消息进行响应。相反,此时服务器正在响应“handshake_failure”。

这应该提供关于 NSS 失败的线索。

Chrome、Openssl 和 Charles Proxy 都可以使用客户端证书进行身份验证。 Firefox(使用 NSS)和 curl(使用 NSS)此时都失败了。

2015 年 11 月 27 日更新:服务器运营团队提供的其他信息表明,这可能是不合规服务器的问题。只有在某些情况下使用 TLS 1.2 时才会出现此问题。这可以解释为什么某些 SSL 库(例如 OpenSSL)足够灵活,可以绕过它。

NSS 在遵守 RFC 方面可能更加严格。如果/当我们从管理服务器的运营团队那里听到更多消息时,我会更新答案。

2017-01-25 更新:网络服务器软件和负载平衡器是为特定银行的支付网关定制的。我们最近再次尝试使用新客户端,服务器现在似乎可以与使用 NSS 或 OpenSSL 构建的 Curl 一起使用,并且不再看到错误。总之:解决方法是使用不同的 SSL 库并等待开发人员修复服务器软件。

【讨论】:

如果这仍然相关,如果有人感兴趣,我可以提供一些具体信息。

以上是关于CentOS PHP curl 无法协商一组可接受的安全参数的主要内容,如果未能解决你的问题,请参考以下文章

您的要求无法解决为 pinterest API 的一组可安装软件包

您的要求无法解析为一组可安装的软件包(Composer 更新)

Composer 更新 - 您的要求无法解析为一组可安装的软件包

Laravel 7 w/ Laravel Excel:您的需求无法解决为一组可安装的软件包

如何解决“您的需求无法解析为一组可安装的软件包”

无法使用 curl 协商到不同的域