Php cURL错误35:gnutls\u握手()失败
我在使用CURL通过SSL请求URI的PHP组件中遇到以下错误:Php cURL错误35:gnutls\u握手()失败,php,curl,travis-ci,gnutls,Php,Curl,Travis Ci,Gnutls,我在使用CURL通过SSL请求URI的PHP组件中遇到以下错误: cURL error 35: gnutls_handshake() failed: A TLS packet with unexpected length was received. 此错误发生在travis-ci.org环境中,但不在我们的任何测试环境中。参见travis ci构建 我发现运行在Travis worker中的PHP版本在“Ubuntu12.04.5 LTS”上再次编译为“GnuTLS/2.12.14”,或者在“
cURL error 35: gnutls_handshake() failed: A TLS packet with unexpected length was received.
此错误发生在travis-ci.org环境中,但不在我们的任何测试环境中。参见travis ci构建
我发现运行在Travis worker中的PHP版本在“Ubuntu12.04.5 LTS”上再次编译为“GnuTLS/2.12.14”,或者在“Ubuntu14.04.3 LTS”上再次编译为“GnuTLS/2.12.23”
在我们的开发环境中,我们使用针对Debian上的“OpenSSL/1.0.1t”编译的标准包(各种版本)
因此,我假设问题与“GnuTLS/2.12.14”或“GnuTLS/2.12.23”或编译它们时使用的参数有关
我曾尝试使用CURL常量curloptsslversion限制SSL版本,但这并不能解决问题
根据www.ssllabs.com,所讨论的主机api.reporting.cloud支持TLS 1.2、TLS 1.1和TLS 1.0
有人能给我一些提示或建议吗?我从以下几点中找到了解决问题的方法: 服务器不喜欢gnutls的TLS1.2支持中的某些内容 2.12因为如果你禁用它,它似乎可以工作。同一台服务器适用于GnuTLS3.2,这是两者在客户机hello方面的唯一区别 版本是GnuTLS3.2启用了更多功能 我正在使用(必须使用)“gnutls cli(gnutls)2.12.23” 下面返回上述错误:
gnutls-cli --priority "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.2" api.reporting.cloud
然而,强制执行“TLS 1.1”或“TLS 1.0”会如期返回:
gnutls-cli --priority "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.1" api.reporting.cloud
gnutls-cli --priority "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.0" api.reporting.cloud
下一步是通过CURL从PHP进行此设置(在库版本出现错误的特定情况下)。在PHP中,可以控制CURL与CURL\u SSLVERSION\u*常量一起使用的SSL协议 通过设置:
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_1);
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
我可以强制curl使用“tls1.1”
通过设置:
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_1);
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
我可以强制curl使用“TLS1.0”
为了测试所有可能的SSL协议,我创建了以下脚本,然后由travis ci执行:
<?php
$sslVersions = [
CURL_SSLVERSION_DEFAULT,
CURL_SSLVERSION_TLSv1,
CURL_SSLVERSION_TLSv1_0,
CURL_SSLVERSION_TLSv1_1,
CURL_SSLVERSION_TLSv1_2,
CURL_SSLVERSION_SSLv2,
CURL_SSLVERSION_SSLv3,
];
var_dump(curl_version());
foreach ($sslVersions as $sslVersion) {
$uri = "https://api.reporting.cloud";
printf("Trying %d", $sslVersion);
echo PHP_EOL;
$ch = curl_init($uri);
curl_setopt($ch, CURLOPT_VERBOSE , true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER , 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT , 0);
curl_setopt($ch, CURLOPT_TIMEOUT , 2);
curl_setopt($ch, CURLOPT_SSLVERSION , $sslVersion);
if (curl_exec($ch) === false) {
var_dump(curl_error($ch));
} else {
curl_close($ch);
}
echo PHP_EOL;
echo PHP_EOL;
}
exit(1);
if (getenv('TRAVIS')) {
$options['curl'][CURLOPT_SSLVERSION] = CURL_SSLVERSION_TLSv1_1;
}
我还注意到常数CURL\u SSLVERSION\u TLSv1\u 0、CURL\u SSLVERSION\u TLSv1\u 1和CURL\u SSLVERSION\u TLSv1\u 2在travis ci的PHP5.6和PHP7版本中都不可用
总而言之,我已经遍历了所有可能的CURL_SSLVERSION_*常量,没有一个允许我连接到travis ci上的api.reporting.cloud,无论我使用哪一个PHP版本
有人对我如何从travis ci连接到api.reporting.cloud有什么建议吗?解决这个问题的方法是将travis ci配置为使用标准的Ubuntu Trusty php5 cli和php5 curl软件包。标准软件包提供CURL_SSLVERSION_TLSv1_1常量 .travis.yml文件如下所示:
sudo: required
dist: trusty
language: php
before_install:
- sudo apt-get -y install git zip php5-cli php5-curl
before_script:
- php -r "printf('PHP %s', phpversion());"
- composer self-update
- composer install --no-interaction
script:
- mkdir -p ./build/logs
- ./vendor/bin/phpunit
在PHP源代码中,只要在travis ci执行PHP代码的情况下设置上述常量即可:
<?php
$sslVersions = [
CURL_SSLVERSION_DEFAULT,
CURL_SSLVERSION_TLSv1,
CURL_SSLVERSION_TLSv1_0,
CURL_SSLVERSION_TLSv1_1,
CURL_SSLVERSION_TLSv1_2,
CURL_SSLVERSION_SSLv2,
CURL_SSLVERSION_SSLv3,
];
var_dump(curl_version());
foreach ($sslVersions as $sslVersion) {
$uri = "https://api.reporting.cloud";
printf("Trying %d", $sslVersion);
echo PHP_EOL;
$ch = curl_init($uri);
curl_setopt($ch, CURLOPT_VERBOSE , true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER , 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT , 0);
curl_setopt($ch, CURLOPT_TIMEOUT , 2);
curl_setopt($ch, CURLOPT_SSLVERSION , $sslVersion);
if (curl_exec($ch) === false) {
var_dump(curl_error($ch));
} else {
curl_close($ch);
}
echo PHP_EOL;
echo PHP_EOL;
}
exit(1);
if (getenv('TRAVIS')) {
$options['curl'][CURLOPT_SSLVERSION] = CURL_SSLVERSION_TLSv1_1;
}
这种解决方法的缺点是,它只适用于Ubuntu Trusty提供的特定PHP版本(PHP5.5)。考虑到PHP5.5在2016年7月10日达到使用寿命,此解决方案是不可接受的
travis ci最好更新到Ubuntu 16.04 LTS,但travis ci基础设施经理Brandon Burton于2016年2月28日表示:
鉴于此,我们目前的重点是支持12.04和14.04
主要环境。目前,我们不太可能成功
今年支持16.04作为本地环境
因此,看起来我们在Ubuntu Trusty上停留了一段时间
这个问题的根源在于,从2011年开始,在travis ci上运行的PHP版本是使用gnutls cli(gnutls)2.12.23编译的。此特定版本的gnutls cli在某些(但不是全部)TLS 1.2连接方面存在问题
@travis ci:是否有可能针对更现代的GnuTLS版本重新编译您使用的PHP版本?或者至少有一个更好地支持TLS 1.2的版本?不幸的是,Ubuntu 16.04也受到这个问题的困扰。