我从使用CURL通过SSL请求URI的PHP组件遇到以下错误:
cURL error 35: gnutls_handshake() failed: A TLS packet with unexpected length was received.
此错误发生在travis-ci.org环境中,但不在我们的任何测试环境中。请参阅travis-ci build 144663700。
我发现Travis worker中运行的PHP版本在“Ubuntu 12.04.5 LTS”上再次编译为“GnuTLS / 2.12.14”,在“Ubuntu 14.04.3 LTS”上编译为“GnuTLS / 2.12.23” ”
在我们的开发环境中,我们在Debian(各种版本)上使用针对“OpenSSL / 1.0.1t”编译的标准包。
因此,我认为问题与“GnuTLS / 2.12.14”或“GnuTLS / 2.12.23”有关,或与编译它们的参数有关。
我尝试使用CURL常量CURLOPT_SSLVERSION来限制SSL版本,但这并没有解决问题。
根据www.ssllabs.com,有问题的主机 - api.reporting.cloud - 支持TLS 1.2,TLS 1.1和TLS 1.0。
有人会对我有任何提示或指示吗?
答案 0 :(得分:7)
解决此问题的方法是将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代码的情况下设置上述常量:
if (getenv('TRAVIS')) {
$options['curl'][CURLOPT_SSLVERSION] = CURL_SSLVERSION_TLSv1_1;
}
此解决方法的缺点是它只适用于Ubuntu Trusty提供的特定PHP版本(PHP 5.5)。考虑到PHP 5.5在2016年7月10日达到了使用寿命,此解决方案是不可接受的。
对于travis-ci来说,更新到Ubuntu 16.04 LTS是理想的,但2016年2月28日travis-ci wrote的基础架构经理Brandon Burton:
鉴于此,我们目前专注于支持12.04和14.04作为我们的支持 主要环境。目前,我们不太可能 今年支持16.04作为本土环境。
因此,我们似乎暂时停留在Ubuntu Trusty上。
这个问题的根源是在travis-ci上运行的PHP版本是用2011年的gnutls-cli(GnuTLS)2.12.23编译的。这个特定版本的gnutls-cli有一些问题(但不是全部) )TLS 1.2连接。
@travis-ci:是否可以重新编译您使用的PHP版本以更新版本的GnuTLS - 或者至少有一个更好地支持TLS 1.2?
答案 1 :(得分:4)
在PHP中,可以控制curl与CURL_SSLVERSION_ *常量一起使用的SSL协议。
通过设置:
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_1);
我可以强制卷曲使用“TLS 1.1”。
通过设置:
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
我可以强制卷曲使用“TLS 1.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);
我的开发环境中此脚本的输出是:
array(9) {
["version_number"]=>
int(468480)
["age"]=>
int(3)
["features"]=>
int(182173)
["ssl_version_number"]=>
int(0)
["version"]=>
string(6) "7.38.0"
["host"]=>
string(19) "x86_64-pc-linux-gnu"
["ssl_version"]=>
string(14) "OpenSSL/1.0.1t"
["libz_version"]=>
string(5) "1.2.8"
["protocols"]=>
array(21) {
[0]=>
string(4) "dict"
[1]=>
string(4) "file"
[2]=>
string(3) "ftp"
[3]=>
string(4) "ftps"
[4]=>
string(6) "gopher"
[5]=>
string(4) "http"
[6]=>
string(5) "https"
[7]=>
string(4) "imap"
[8]=>
string(5) "imaps"
[9]=>
string(4) "ldap"
[10]=>
string(5) "ldaps"
[11]=>
string(4) "pop3"
[12]=>
string(5) "pop3s"
[13]=>
string(4) "rtmp"
[14]=>
string(4) "rtsp"
[15]=>
string(3) "scp"
[16]=>
string(4) "sftp"
[17]=>
string(4) "smtp"
[18]=>
string(5) "smtps"
[19]=>
string(6) "telnet"
[20]=>
string(4) "tftp"
}
}
Trying 0
* Rebuilt URL to: https://api.reporting.cloud/
* Hostname was NOT found in DNS cache
* Trying 40.76.93.116...
* Connected to api.reporting.cloud (40.76.93.116) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-SHA384
* Server certificate:
* subject: serialNumber=HRB 25927; 1.3.6.1.4.1.311.60.2.1.3=DE; businessCategory=Private Organization; C=DE; postalCode=28215; ST=Bremen; L=Bremen; street=Admiralstr. 54; O=Text Control GmbH; OU=ReportingCloud; OU=COMODO EV SSL; CN=api.reporting.cloud
* start date: 2016-06-17 00:00:00 GMT
* expire date: 2017-06-17 23:59:59 GMT
* subjectAltName: api.reporting.cloud matched
* issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO RSA Extended Validation Secure Server CA
* SSL certificate verify ok.
> GET / HTTP/1.1
Host: api.reporting.cloud
Accept: */*
< HTTP/1.1 200 OK
< Cache-Control: private
< Content-Type: text/html; charset=utf-8
* Server Microsoft-IIS/8.5 is not blacklisted
< Server: Microsoft-IIS/8.5
< X-AspNetMvc-Version: 5.2
< X-AspNet-Version: 4.0.30319
< X-Powered-By: ASP.NET
< Date: Fri, 15 Jul 2016 14:22:40 GMT
< Content-Length: 952
<
* Connection #0 to host api.reporting.cloud left intact
Trying 1
* Rebuilt URL to: https://api.reporting.cloud/
* Hostname was found in DNS cache
* Trying 40.76.93.116...
* Connected to api.reporting.cloud (40.76.93.116) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-SHA384
* Server certificate:
* subject: serialNumber=HRB 25927; 1.3.6.1.4.1.311.60.2.1.3=DE; businessCategory=Private Organization; C=DE; postalCode=28215; ST=Bremen; L=Bremen; street=Admiralstr. 54; O=Text Control GmbH; OU=ReportingCloud; OU=COMODO EV SSL; CN=api.reporting.cloud
* start date: 2016-06-17 00:00:00 GMT
* expire date: 2017-06-17 23:59:59 GMT
* subjectAltName: api.reporting.cloud matched
* issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO RSA Extended Validation Secure Server CA
* SSL certificate verify ok.
> GET / HTTP/1.1
Host: api.reporting.cloud
Accept: */*
< HTTP/1.1 200 OK
< Cache-Control: private
< Content-Type: text/html; charset=utf-8
* Server Microsoft-IIS/8.5 is not blacklisted
< Server: Microsoft-IIS/8.5
< X-AspNetMvc-Version: 5.2
< X-AspNet-Version: 4.0.30319
< X-Powered-By: ASP.NET
< Date: Fri, 15 Jul 2016 14:22:40 GMT
< Content-Length: 952
<
* Connection #0 to host api.reporting.cloud left intact
Trying 4
* Rebuilt URL to: https://api.reporting.cloud/
* Hostname was found in DNS cache
* Trying 40.76.93.116...
* Connected to api.reporting.cloud (40.76.93.116) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSL connection using TLSv1.0 / ECDHE-RSA-AES256-SHA
* Server certificate:
* subject: serialNumber=HRB 25927; 1.3.6.1.4.1.311.60.2.1.3=DE; businessCategory=Private Organization; C=DE; postalCode=28215; ST=Bremen; L=Bremen; street=Admiralstr. 54; O=Text Control GmbH; OU=ReportingCloud; OU=COMODO EV SSL; CN=api.reporting.cloud
* start date: 2016-06-17 00:00:00 GMT
* expire date: 2017-06-17 23:59:59 GMT
* subjectAltName: api.reporting.cloud matched
* issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO RSA Extended Validation Secure Server CA
* SSL certificate verify ok.
> GET / HTTP/1.1
Host: api.reporting.cloud
Accept: */*
< HTTP/1.1 200 OK
< Cache-Control: private
< Content-Type: text/html; charset=utf-8
* Server Microsoft-IIS/8.5 is not blacklisted
< Server: Microsoft-IIS/8.5
< X-AspNetMvc-Version: 5.2
< X-AspNet-Version: 4.0.30319
< X-Powered-By: ASP.NET
< Date: Fri, 15 Jul 2016 14:22:40 GMT
< Content-Length: 952
<
* Connection #0 to host api.reporting.cloud left intact
Trying 5
* Rebuilt URL to: https://api.reporting.cloud/
* Hostname was found in DNS cache
* Trying 40.76.93.116...
* Connected to api.reporting.cloud (40.76.93.116) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSL connection using TLSv1.1 / ECDHE-RSA-AES256-SHA
* Server certificate:
* subject: serialNumber=HRB 25927; 1.3.6.1.4.1.311.60.2.1.3=DE; businessCategory=Private Organization; C=DE; postalCode=28215; ST=Bremen; L=Bremen; street=Admiralstr. 54; O=Text Control GmbH; OU=ReportingCloud; OU=COMODO EV SSL; CN=api.reporting.cloud
* start date: 2016-06-17 00:00:00 GMT
* expire date: 2017-06-17 23:59:59 GMT
* subjectAltName: api.reporting.cloud matched
* issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO RSA Extended Validation Secure Server CA
* SSL certificate verify ok.
> GET / HTTP/1.1
Host: api.reporting.cloud
Accept: */*
< HTTP/1.1 200 OK
< Cache-Control: private
< Content-Type: text/html; charset=utf-8
* Server Microsoft-IIS/8.5 is not blacklisted
< Server: Microsoft-IIS/8.5
< X-AspNetMvc-Version: 5.2
< X-AspNet-Version: 4.0.30319
< X-Powered-By: ASP.NET
< Date: Fri, 15 Jul 2016 14:22:41 GMT
< Content-Length: 952
<
* Connection #0 to host api.reporting.cloud left intact
Trying 6
* Rebuilt URL to: https://api.reporting.cloud/
* Hostname was found in DNS cache
* Trying 40.76.93.116...
* Connected to api.reporting.cloud (40.76.93.116) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-SHA384
* Server certificate:
* subject: serialNumber=HRB 25927; 1.3.6.1.4.1.311.60.2.1.3=DE; businessCategory=Private Organization; C=DE; postalCode=28215; ST=Bremen; L=Bremen; street=Admiralstr. 54; O=Text Control GmbH; OU=ReportingCloud; OU=COMODO EV SSL; CN=api.reporting.cloud
* start date: 2016-06-17 00:00:00 GMT
* expire date: 2017-06-17 23:59:59 GMT
* subjectAltName: api.reporting.cloud matched
* issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO RSA Extended Validation Secure Server CA
* SSL certificate verify ok.
> GET / HTTP/1.1
Host: api.reporting.cloud
Accept: */*
< HTTP/1.1 200 OK
< Cache-Control: private
< Content-Type: text/html; charset=utf-8
* Server Microsoft-IIS/8.5 is not blacklisted
< Server: Microsoft-IIS/8.5
< X-AspNetMvc-Version: 5.2
< X-AspNet-Version: 4.0.30319
< X-Powered-By: ASP.NET
< Date: Fri, 15 Jul 2016 14:22:41 GMT
< Content-Length: 952
<
* Connection #0 to host api.reporting.cloud left intact
Trying 2
* Rebuilt URL to: https://api.reporting.cloud/
* Hostname was found in DNS cache
* Trying 40.76.93.116...
* Connected to api.reporting.cloud (40.76.93.116) port 443 (#0)
* OpenSSL was built without SSLv2 support
* Closing connection 0
string(39) "OpenSSL was built without SSLv2 support"
Trying 3
* Rebuilt URL to: https://api.reporting.cloud/
* Hostname was found in DNS cache
* Trying 40.76.93.116...
* Connected to api.reporting.cloud (40.76.93.116) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* Unknown SSL protocol error in connection to api.reporting.cloud:443
* Closing connection 0
string(68) "Unknown SSL protocol error in connection to api.reporting.cloud:443 "
在这里,我们可以清楚地看到'使用TLSv1.0的SSL连接'正确连接到后端服务器。
但是,在travi-ci上运行相同的脚本会导致以下结果:
PHP Notice: Use of undefined constant CURL_SSLVERSION_TLSv1_0 - assumed 'CURL_SSLVERSION_TLSv1_0' in /home/travis/build/TextControl/txtextcontrol-reportingcloud-php/demo/ssl-issue.php on line 7
PHP Stack trace:
PHP 1. {main}() /home/travis/build/TextControl/txtextcontrol-reportingcloud-php/demo/ssl-issue.php:0
Notice: Use of undefined constant CURL_SSLVERSION_TLSv1_0 - assumed 'CURL_SSLVERSION_TLSv1_0' in /home/travis/build/TextControl/txtextcontrol-reportingcloud-php/demo/ssl-issue.php on line 7
Call Stack:
0.0002 241400 1. {main}() /home/travis/build/TextControl/txtextcontrol-reportingcloud-php/demo/ssl-issue.php:0
PHP Notice: Use of undefined constant CURL_SSLVERSION_TLSv1_1 - assumed 'CURL_SSLVERSION_TLSv1_1' in /home/travis/build/TextControl/txtextcontrol-reportingcloud-php/demo/ssl-issue.php on line 8
PHP Stack trace:
PHP 1. {main}() /home/travis/build/TextControl/txtextcontrol-reportingcloud-php/demo/ssl-issue.php:0
Notice: Use of undefined constant CURL_SSLVERSION_TLSv1_1 - assumed 'CURL_SSLVERSION_TLSv1_1' in /home/travis/build/TextControl/txtextcontrol-reportingcloud-php/demo/ssl-issue.php on line 8
Call Stack:
0.0002 241400 1. {main}() /home/travis/build/TextControl/txtextcontrol-reportingcloud-php/demo/ssl-issue.php:0
PHP Notice: Use of undefined constant CURL_SSLVERSION_TLSv1_2 - assumed 'CURL_SSLVERSION_TLSv1_2' in /home/travis/build/TextControl/txtextcontrol-reportingcloud-php/demo/ssl-issue.php on line 9
PHP Stack trace:
PHP 1. {main}() /home/travis/build/TextControl/txtextcontrol-reportingcloud-php/demo/ssl-issue.php:0
Notice: Use of undefined constant CURL_SSLVERSION_TLSv1_2 - assumed 'CURL_SSLVERSION_TLSv1_2' in /home/travis/build/TextControl/txtextcontrol-reportingcloud-php/demo/ssl-issue.php on line 9
Call Stack:
0.0002 241400 1. {main}() /home/travis/build/TextControl/txtextcontrol-reportingcloud-php/demo/ssl-issue.php:0
array(9) {
'version_number' =>
int(464384)
'age' =>
int(3)
'features' =>
int(50749)
'ssl_version_number' =>
int(0)
'version' =>
string(6) "7.22.0"
'host' =>
string(19) "x86_64-pc-linux-gnu"
'ssl_version' =>
string(14) "GnuTLS/2.12.14"
'libz_version' =>
string(7) "1.2.3.4"
'protocols' =>
array(18) {
[0] =>
string(4) "dict"
[1] =>
string(4) "file"
[2] =>
string(3) "ftp"
[3] =>
string(4) "ftps"
[4] =>
string(6) "gopher"
[5] =>
string(4) "http"
[6] =>
string(5) "https"
[7] =>
string(4) "imap"
[8] =>
string(5) "imaps"
[9] =>
string(4) "ldap"
[10] =>
string(4) "pop3"
[11] =>
string(5) "pop3s"
[12] =>
string(4) "rtmp"
[13] =>
string(4) "rtsp"
[14] =>
string(4) "smtp"
[15] =>
string(5) "smtps"
[16] =>
string(6) "telnet"
[17] =>
string(4) "tftp"
}
}
Trying 0
* About to connect() to api.reporting.cloud port 443 (#0)
* Trying 40.76.93.116... * connected
* found 164 certificates in /etc/ssl/certs/ca-certificates.crt
* gnutls_handshake() failed: A TLS packet with unexpected length was received.
* Closing connection #0
string(76) "gnutls_handshake() failed: A TLS packet with unexpected length was received."
Trying 1
* About to connect() to api.reporting.cloud port 443 (#0)
* Trying 40.76.93.116... * connected
* found 164 certificates in /etc/ssl/certs/ca-certificates.crt
* gnutls_handshake() failed: A TLS packet with unexpected length was received.
* Closing connection #0
string(76) "gnutls_handshake() failed: A TLS packet with unexpected length was received."
Trying 0
* About to connect() to api.reporting.cloud port 443 (#0)
* Trying 40.76.93.116... * connected
* found 164 certificates in /etc/ssl/certs/ca-certificates.crt
* gnutls_handshake() failed: A TLS packet with unexpected length was received.
* Closing connection #0
string(76) "gnutls_handshake() failed: A TLS packet with unexpected length was received."
Trying 0
* About to connect() to api.reporting.cloud port 443 (#0)
* Trying 40.76.93.116... * connected
* found 164 certificates in /etc/ssl/certs/ca-certificates.crt
* gnutls_handshake() failed: A TLS packet with unexpected length was received.
* Closing connection #0
string(76) "gnutls_handshake() failed: A TLS packet with unexpected length was received."
Trying 0
* About to connect() to api.reporting.cloud port 443 (#0)
* Trying 40.76.93.116... * connected
* found 164 certificates in /etc/ssl/certs/ca-certificates.crt
* gnutls_handshake() failed: A TLS packet with unexpected length was received.
* Closing connection #0
string(76) "gnutls_handshake() failed: A TLS packet with unexpected length was received."
Trying 2
* About to connect() to api.reporting.cloud port 443 (#0)
* Trying 40.76.93.116... * connected
* GnuTLS does not support SSLv2
* Closing connection #0
string(29) "GnuTLS does not support SSLv2"
Trying 3
* About to connect() to api.reporting.cloud port 443 (#0)
* Trying 40.76.93.116... * connected
* found 164 certificates in /etc/ssl/certs/ca-certificates.crt
* gnutls_handshake() failed: A TLS packet with unexpected length was received.
* Closing connection #0
string(76) "gnutls_handshake() failed: A TLS packet with unexpected length was received."
我还注意到常量CURL_SSLVERSION_TLSv1_0,CURL_SSLVERSION_TLSv1_1和CURL_SSLVERSION_TLSv1_2在travis-ci的PHP 5.6和PHP 7版本上都不可用。
总而言之,我已经遍历了所有可能的CURL_SSLVERSION_ *常量,并且没有一个允许我连接到travis-ci上的api.reporting.cloud,无论我使用哪个PHP版本。
有没有人对如何从travis-ci连接到api.reporting.cloud有任何建议?
答案 2 :(得分:1)
我在mailing list中找到了问题的解决方案:
服务器不喜欢gnutls的TLS 1.2支持 2.12因为如果你禁用它,它似乎工作。同一台服务器使用gnutls 3.2和两者的客户端问候的唯一区别 版本是gnutls 3.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
下一步是从PHP到CURL进行此设置(在特定的库版本错误的情况下)。