尝试使用 fsockopen() 连接 SSL 服务器
我正在从本地主机和生产服务器运行下一个脚本,我得到了不同的输出。有人知道为什么我从本地主机得到那个
false
吗?
<?php
$host = 'ssl://mail.companyname.org';
$port = 993;
$error = 0;
$errorString = "";
var_dump(fsockopen($host, $port, $error, $errorString, 30));
var_dump($errorString);
var_dump($error);
本地主机输出:
bool(false)
生产服务器输出:
resource(4) 类型 (stream)
更新 :在评论/回答之后,我修改了代码,现在我在本地主机上得到了这个输出:
PHP Warning: fsockopen(): SSL operation failed with code 1. OpenSSL Error messages: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed in /tmp/test.php on line 7 PHP Warning: fsockopen(): Failed to enable crypto in /tmp/test.php on line 7 PHP Warning: fsockopen(): unable to connect to ssl://mail.twmdata.org:993 (Unknown error) in /tmp/test.php on line 7 bool(false) string(0) "" int(0)
这似乎是服务器证书的问题:
首先,您可以通过以下方式检查您的服务器证书及其链是否有效:
https://www.sslshopper.com/ssl-checker.htm
ssl-checker 中是否有错误?
-
您可以尝试在 companyname.org
中更正 SSL 证书配置>如果成功但错误仍然存​​在?
- 您必须 手动添加证书文件 。
如果您有自签名证书:
- 您必须 手动添加证书文件 。
如果如果您没有证书,也不关心中间人攻击, 您仍然可以使用没有证书的 SSL。
- 关闭 php fsock 证书检查 (不推荐)
建议至少拥有一个自签名证书。如果您有自签名证书,请尝试 1 解决方案。
我发现了问题
您已在 PHP 警告日志中暴露了您的 域名 ,因此我已检查了您的域名 SSL。
我使用此工具检查了贵公司的域名证书后:
https://www.sslshopper.com/ssl-checker.html#hostname=twmdata.org
您的证书有 2 个错误:
-
此证书已过期(0 天前)。立即续订。
-
证书中没有任何通用名称与输入的名称 (twmdata.org) 匹配。在 Web 浏览器中访问此站点时,您可能会收到错误。
因此,您似乎必须先更新证书
更新:
我发现这个答案可能有用
https://stackoverflow.com/a/40962061/9287628
建议使用
stream_context_create(['ssl' => [
'ciphers' => 'RC4-MD5'
]])
正如 @ChrisHaas 建议的那样连接如果您想指定证书目录或者关闭证书检查,
stream_context_create
和
stream_socket_client
为您提供了很多选项。
根据
fsockopen
的
文档
,>
The function stream_socket_client() is similar but provides a richer set of options, including non-blocking connection and the ability to provide a stream context.
基本上,
fsockopen
非常低级,但没有很多选项,或者可以说是“合理的默认值”。
相反,您可以切换到
stream_socket_client
,它将允许您指定
context
作为最后一个参数,并且该对象有许多选项,包括一个专用选项,其中包含超过
十几个特定于 SSL 的选项
。从此函数创建的对象与
fwrite
和其他函数兼容,因此它应该可以完成您希望的所有操作。
$context = stream_context_create([/*Options here*/]);
$connection = stream_socket_client($host, $errno, $errorString, 30, null, $context);
现在,您应该使用哪些选项?
可能起作用的最差选项可能是
verify_peer
。我说“最差”是因为您正在抛弃 SSL/TLS 的可验证性部分,而仅将其用于加密,这样做会使您容易受到 MitM 攻击。但是,这有时间和地点,因此如果其他选项太复杂,您可以尝试一下。
$context = stream_context_create(['ssl' => ['verify_peer' => false]]);
$connection = stream_socket_client($host, $errno, $errorString, 30, null, $context);
相反,我建议使用
cafile
或
capath
,它们的作用相同,只是前者用于文件,而后者用于目录。
$context = stream_context_create(['ssl' => ['verify_peer' => true, 'cafile' => '/path/to/file']]);
$connection = stream_socket_client($host, $errno, $errorString, 30, null, $context);
您应该使用哪些证书?我们定期使用 此库 提取最新的 CA 文件,非常方便。每个项目都需要进行一些设置,但一旦掌握,就会很快。请参阅 此 以了解如何在知名位置提取 CA 文件。
最后一个选项是
local_cert
,如果您有权访问该文件,则可以将其与包含来自服务器的证书和私钥的 PEM 文件一起使用。
编辑
mail.twmdata.org:993
上的证书与其他人谈论的 Web 服务器的证书不同,这通常是最佳做法。您可以使用以下命令检查该证书:
openssl s_client -connect mail.twmdata.org:993 -servername mail.twmdata.org
如果执行此操作,您将看到服务器具有自签名证书,您可以通过将
verify_peer
选项设置为 false 来绕过该证书。
删除 @ 符号。您正在隐藏可能告诉您问题所在错误消息。您还应该在 fsockopen() 的 errorno 参数中设置一个变量,并回显它以进行调试。
我猜您没有在本地服务器上安装支持 SSL 的 PHP。请参阅 此处 。
Companyname.org 可能还会阻止来自本地服务器的请求,而这些请求是允许从生产服务器发出的。