开发者问题收集

尝试使用 fsockopen() 连接 SSL 服务器

2020-11-25
2562

我正在从本地主机和生产服务器运行下一个脚本,我得到了不同的输出。有人知道为什么我从本地主机得到那个 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)

3个回答

这似乎是服务器证书的问题:

首先,您可以通过以下方式检查您的服务器证书及其链是否有效:

https://www.sslshopper.com/ssl-checker.htm

ssl-checker 中是否有错误?

  • 您可以尝试在 companyname.org

    中更正 SSL 证书配置>

    如果成功但错误仍然存​​在?

    1. 您必须 手动添加证书文件

如果您有自签名证书:

  1. 您必须 手动添加证书文件

如果如果您没有证书,也不关心中间人攻击, 您仍然可以使用没有证书的 SSL。

  1. 关闭 php fsock 证书检查 (不推荐)

建议至少拥有一个自签名证书。如果您有自签名证书,请尝试 1 解决方案。

我发现了问题

您已在 PHP 警告日志中暴露了您的 域名 ,因此我已检查了您的域名 SSL。

我使用此工具检查了贵公司的域名证书后:

https://www.sslshopper.com/ssl-checker.html#hostname=twmdata.org

您的证书有 2 个错误:

  • 此证书已过期(0 天前)。立即续订。

  • 证书中没有任何通用名称与输入的名称 (twmdata.org) 匹配。在 Web 浏览器中访问此站点时,您可能会收到错误。

因此,您似乎必须先更新证书

certificate error

更新:

我发现这个答案可能有用

https://stackoverflow.com/a/40962061/9287628

建议使用

stream_context_create(['ssl' => [
   'ciphers' => 'RC4-MD5'
]])

正如 @ChrisHaas 建议的那样连接如果您想指定证书目录或者关闭证书检查, stream_context_createstream_socket_client 为您提供了很多选项。

Abilogos
2020-12-01

根据 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);

相反,我建议使用 cafilecapath ,它们的作用相同,只是前者用于文件,而后者用于目录。

$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 来绕过该证书。

Chris Haas
2020-11-30

删除 @ 符号。您正在隐藏可能告诉您问题所在错误消息。您还应该在 fsockopen() 的 errorno 参数中设置一个变量,并回显它以进行调试。

我猜您没有在本地服务器上安装支持 SSL 的 PHP。请参阅 此处

Companyname.org 可能还会阻止来自本地服务器的请求,而这些请求是允许从生产服务器发出的。

brensnap
2020-11-25