首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PHP stream_socket_client连接失败

PHP stream_socket_client连接失败
EN

Stack Overflow用户
提问于 2015-10-13 20:17:42
回答 1查看 4K关注 0票数 1

我试图通过php的stream_socket_client()命令联系一个url,该命令没有错误代码或msg就失败了。这是使用openssl、curl还是其他什么的吗?该站点使用https,并在web浏览器上运行良好。

当我直接调用openssl时,它会连接起来,但与我的证书链没有关联。

代码语言:javascript
复制
root@drupal7 drupal7/includes# openssl s_client -connect test.cgps.org:443
CONNECTED(00000003)
Verify return code: 21 (unable to verify the first certificate)

卷曲也一样

代码语言:javascript
复制
curl https://test.cgps.org/?q=/admin/config/search/clean-urls/check
curl: (60) SSL certificate problem: unable to get local issuer certificate

因此,我认为我需要将中间证书安装到Linux中,这是通过将Apache使用的中间证书放入/usr/local/share/ca证书和运行update证书来实现的。

代码语言:javascript
复制
root@drupal7 drupal7/includes# update-ca-certificates
Updating certificates in /etc/ssl/certs... 1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....done.

还是没有运气..。

EN

回答 1

Stack Overflow用户

发布于 2018-02-06 12:08:16

尽管在评论中发表了一项声明,称PHP的steam_socket_client()太低而不关心证书,但我知道确实关心,因为我观察到它在标准位置缺少一些证书的系统上返回false,在那里提供流上下文(告诉它在哪里查找证书)阻止了这种情况的发生。

令人沮丧的是,在您修复这个问题之前,$errno可以保持为0,所以最好先使用另一个工具检查证书颁发机构目录。

诊断

通过curl

要使用curl,通常可以通过添加--verbose标志来了解发生了什么。这将告诉您正在使用哪些连接的证书PEM文件(CAfile/cacert)和CA-目录(capath) (如果有的话)。在输出的顶部,您将得到如下内容:

代码语言:javascript
复制
[...]
* successfully set certificate verify locations:
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: /home2/wynddorg/private_html/trusted_roots
[...]

一旦您知道这些是默认的,您可以调整您的系统配置,或者简单地添加--cacert <concatenated_cert_path>标志或--capath <c_rehash'd_directory>,或者同时添加两者。

通过openssl s_client

使用s_client要复杂一些;您可能可以访问它的-trace选项,这取决于您的版本以及它是如何编译的,但是请尝试:

代码语言:javascript
复制
strace -e open,stat openssl s_client -connect test.cgps.org:443 [-CApath <dir>]
# this trick provided by the amazing xemdetia in irc://freenode/%23%23openssl

CONNECTED(00000003)消息之后大约5行,您应该会看到一个open("...", O_RDONLY) (或几行),它应该显示用于查找证书的位置。

我错过了一个或多个证书。这次又是什么?

一旦您知道丢失了哪些证书,就可以下载它们如图所示,然后执行以下操作:

  • 将它们连接到PEM文件(最好是按顺序),然后在尝试连接到站点时指定该文件。
  • 将它们保存为“..crt”--默认目录中的文件,然后在该目录上运行c_rehash (可能需要root/sudo)
  • 将它们保存为单独的“..crt”--另一个目录中的文件,并在连接时显式指定为capath。您可能希望在共享主机上这样做,或者如果您不希望所有应用程序信任证书,只希望信任特定的应用程序。

一旦您使用了openssl s_clientcurl或两者,您就可以指定如下相同的选项:

代码语言:javascript
复制
$context = stream_context_create();
stream_context_set_option($context, 'ssl', 'cafile', <concatenated_cert_file_path>);
stream_context_set_option($context, 'ssl', 'capath', <c_rehashed_cert_dir_path>);
// You only really need to provide one of the two options above. Using capath is
// faster, but this only matters if you'll be making a huge number of
// connections.
$ssc = stream_socket_client(
    'ssl://subdomain.example.com:443',
    $errno,
    $errstr,
    30,
    STREAM_CLIENT_CONNECT,
    $context
);
if ($ssc) { /* ... */  }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33111851

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档