PHP握手失败TLS1.0
Posted
技术标签:
【中文标题】PHP握手失败TLS1.0【英文标题】:PHP handshake fail TLS1.0 【发布时间】:2017-04-13 12:22:24 【问题描述】:我尝试通过fsockopen
连接到sendm.cert.legalmail.it
上的465
端口,这是意大利称为PEC 的SMTPS 服务。
对于任何版本的 php,我都尝试过这个 sn-p 工作:
<?php
fsockopen('tls://sendm.cert.legalmail.it', 465);
OpenSSL 1.0.2h
没问题,如果我升级到OpenSSL 1.0.2j
,这个 sn-p 会因为这个错误而失败:
PHP Warning: fsockopen(): SSL operation failed with code 1. OpenSSL Error messages:
error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure in ~/Development/experimental/php-handshake/connect.php on line 3
PHP Warning: fsockopen(): Failed to enable crypto in ~/Development/experimental/php-handshake/connect.php on line 3
PHP Warning: fsockopen(): unable to connect to tls://sendm.cert.legalmail.it:465 (Unknown error) in ~/Development/experimental/php-handshake/connect.php on line 3
所以使用OpenSSL 1.0.2j
我尝试通过命令行连接:
openssl s_client -connect sendm.cert.legalmail.it:465
效果很好。
我尝试使用testssl 检查服务器上的 SSL,这是转储(已剥离):
SSLv2 not offered (OK)
SSLv3 not offered (OK)
TLS 1 offered
TLS 1.1 not offered
TLS 1.2 not offered
Version tolerance downgraded to TLSv1.0 (OK)
只有TLS 1
可用,我尝试使用此uri:'tlsv1.0:://sendm.cert.legalmail.it'
强制与TLS1 握手,但结果相同。
我在 Ubuntu 16.04 上,使用 PHP5.6 和 PHP7.1 进行了测试。
错误在哪里?在openssl?在 PHP 中?在服务器握手?
更新如果我总是用./testssl.sh -E sendm.cert.legalmail.it:465
和OpenSSL 1.0.2j
来查看 Chiper,返回:
x05 RC4-SHA RSA RC4 128 TLS_RSA_WITH_RC4_128_SHA
x04 RC4-MD5 RSA RC4 128 TLS_RSA_WITH_RC4_128_MD5
x16 EDH-RSA-DES-CBC3-SHA DH 1024 3DES 168 TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
x0a DES-CBC3-SHA RSA 3DES 168 TLS_RSA_WITH_3DES_EDE_CBC_SHA
x15 EDH-RSA-DES-CBC-SHA DH 1024 DES 56 TLS_DHE_RSA_WITH_DES_CBC_SHA
x09 DES-CBC-SHA RSA DES 56 TLS_RSA_WITH_DES_CBC_SHA
x14 EXP-EDH-RSA-DES-CBC-SHA DH(512) DES 40,exp TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
x08 EXP-DES-CBC-SHA RSA(512) DES 40,exp TLS_RSA_EXPORT_WITH_DES40_CBC_SHA
x06 EXP-RC2-CBC-MD5 RSA(512) RC2 40,exp TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5
x03 EXP-RC4-MD5 RSA(512) RC4 40,exp TLS_RSA_EXPORT_WITH_RC4_40_MD5
使用版本OpenSSL 1.0.2h
x05 RC4-SHA RSA RC4 128
x04 RC4-MD5 RSA RC4 128
x16 EDH-RSA-DES-CBC3-SHA DH 1024 3DES 168
x0a DES-CBC3-SHA RSA 3DES 168
而且 php const OPENSSL_DEFAULT_STREAM_CIPHERS
在它包含的所有版本中都是相同的:
ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128:AES256:HIGH:!SSLv2:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!RC4:!ADH
【问题讨论】:
【参考方案1】:完全编辑答案:在此处查看答案HTTPS and SSL3_GET_SERVER_CERTIFICATE:certificate verify failed, CA is OK
这可能是 fsock 和 curl 的原因。 虽然他的问题是关于 windows / xampp,但我想它会有所帮助,我想升级操作系统的人没有将 php.ini 与新版本合并
【讨论】:
但这个问题与证书验证无关,它在握手时失败。【参考方案2】:好的,经过一番研究,我找到了原因:
PHP 有一个 OPENSSL_DEFAULT_STREAM_CIPHERS
,其中包含对 openssl 的默认查询,使用以下命令:
openssl ciphers -v `php -r 'echo OPENSSL_DEFAULT_STREAM_CIPHERS;'`
我得到了 PHP 可以在安装了当前版本的 openssl 的情况下处理的所有密码。
在1.0.2h
和1.0.2j
之间,相同的查询返回不同的密码,列出对这些的删除支持:
EDH-RSA-DES-CBC3-SHA
DES-CBC3-SHA
所以默认情况下 PHP 不能正确处理连接,但如果我用这个密码强制 $context
连接发生:
$context = stream_context_create(
[
'ssl' => [
'ciphers' => 'EDH-RSA-DES-CBC3-SHA:DES-CBC3-SHA',
],
]
);
$fp = stream_socket_client(
'tls://sendm.cert.legalmail.it:465',
$errno,
$errstr,
30,
STREAM_CLIENT_CONNECT,
$context
);
【讨论】:
【参考方案3】:对于遇到同样问题的其他人:Legalmail TLS 服务器现在似乎支持 TLSv1.2,所以这对他们来说不再是问题了。
【讨论】:
以上是关于PHP握手失败TLS1.0的主要内容,如果未能解决你的问题,请参考以下文章
关于在 java 8 下开启 TLS_RSA_WITH_3DES_EDE_CBC_SHA 支持 xp ie8 tls1.0 的正常访问
HTML5 / PHP WebSocket 连接失败:WebSocket 握手期间出错:意外响应代码:200