我试图通过php的stream_socket_client()命令联系网址,该命令失败,没有错误代码或消息。这是使用openssl,curl还是别的什么?该网站使用https,并在网络浏览器中正常工作。
当我直接调用openssl时,它会连接但我的证书链显得不那么好。
root@drupal7 drupal7/includes# openssl s_client -connect test.cgps.org:443
CONNECTED(00000003)
Verify return code: 21 (unable to verify the first certificate)
与curl相同
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-certificates并运行update-ca-certificates。
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.
仍然没有运气......
答案 0 :(得分:0)
尽管在评论中发表声明称PHP的steam_socket_client()
太低而无法关注证书,但我知道 关心,因为我观察过它在标准位置缺少某些证书的系统上返回false
,其中提供流上下文(告诉它在哪里查找证书)会阻止这种情况发生。
令人沮丧的是,$errno
可以保持为0,直到您修复此问题为止,因此最好先使用其他工具检查您的证书颁发机构目录。
curl
为了使curl
工作正常,你通常可以通过添加--verbose
标志来弄清楚发生了什么。这应该告诉您正在使用哪个连接的证书(CAfile / cacert)和CA目录(capath)的PEM文件(如果有)。在输出的顶部,你会得到类似的东西:
[...]
* 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
选项,具体取决于您的版本以及编译方式,但请尝试:
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)
(或几个),它们应该显示哪些位置用于查找证书。
一旦您知道缺少哪些证书,您可以下载它们as shown here,然后执行任何操作:
c_rehash
(可能需要root / sudo)使用openssl s_client
或curl
或两者后,您可以指定相同的选项:
$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) { /* ... */ }