简体   繁体   English

SSL错误SSL3_GET_SERVER_CERTIFICATE:证书验证失败

[英]SSL error SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

After upgrading to PHP 5.6 I get an error when trying to connect to a server via fsockopen() .. 升级到PHP 5.6后,尝试通过fsockopen()连接到服务器时出错。

The certificate on the server (host) is self-signed 服务器(主机)上的证书是自签名的

PHP Warning: fsockopen(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed PHP警告:fsockopen():SSL操作失败,代码为1. OpenSSL错误消息:错误:14090086:SSL例程:SSL3_GET_SERVER_CERTIFICATE:证书验证失败

code

if($fp = fsockopen($host, $port, $errno, $errstr, 20)){
    $this->request = 'POST '.substr($this->url, strlen($this->host)).' HTTP/1.1'.$crlf
        .'Host: '.$this->host.$crlf
        .'Content-Length: '.$content_length.$crlf
        .'Connection: Close'.$crlf.$crlf
        .$body;
    fwrite($fp, $this->request);

    while($line = fgets($fp)){
        if($line !== false){
            $this->response .= $line;
        }
    }

    fclose($fp);
}

Have tried 试过

# cd /etc/ssl/certs/
# wget http://curl.haxx.se/ca/cacert.pem

php.ini php.ini中

openssl.cafile = "/etc/ssl/certs/cacert.pem"

But the script still fails to work 但脚本仍无法正常工作

update 更新

This works 这有效

echo file_get_contents("/etc/ssl/certs/cacert.pem");

update 2 更新2

$contextOptions = array(
    'ssl' => array(
        'verify_peer' => true, // You could skip all of the trouble by changing this to false, but it's WAY uncool for security reasons.
        'cafile' => '/etc/ssl/certs/cacert.pem',
        //'CN_match' => 'example.com', // Change this to your certificates Common Name (or just comment this line out if not needed)
        'ciphers' => 'HIGH:!SSLv2:!SSLv3',
        'disable_compression' => true,
    )
);

$context = stream_context_create($contextOptions);

$fp = stream_socket_client("{$host}:{$port}", $errno, $errstr, 20, STREAM_CLIENT_CONNECT, $context);

error 错误

PHP Warning: stream_socket_client(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed PHP警告:stream_socket_client():SSL操作失败,代码为1. OpenSSL错误消息:错误:14090086:SSL例程:SSL3_GET_SERVER_CERTIFICATE:证书验证失败

The file that you downloaded ( http://curl.haxx.se/ca/cacert.pem ) is a bundle of the root certificates from the major trusted certificate authorities. 您下载的文件( http://curl.haxx.se/ca/cacert.pem )是来自主要受信任证书颁发机构的一组根证书。 You said that the remote host has a self-signed SSL certificate, so it didn't use a trusted certificate. 您说远程主机具有自签名SSL证书,因此它不使用可信证书。 The openssl.cafile setting needs to point to the CA certificate that was used to sign the SSL certificate on the remote host. openssl.cafile设置需要指向用于在远程主机上签署SSL证书的CA证书。 PHP 5.6 has been improved over previous versions of PHP to now verify peer certificates and host names by default ( http://php.net/manual/en/migration56.openssl.php ) PHP 5.6比以前的PHP版本有所改进,现在默认验证对等证书和主机名( http://php.net/manual/en/migration56.openssl.php

You'll need to locate the CA certificate that was generated on the server that signed the SSL certificate and copy it to this server. 您需要找到在签署SSL证书的服务器上生成的CA证书,并将其复制到此服务器。 The only other option is to disable verifying the peer, but that defeats the SSL security. 唯一的另一种选择是禁用验证对等体,但这会破坏SSL安全性。 If you DO want to try disabling verification, try this array with the code from my previous answer: 如果您想尝试禁用验证,请使用我之前的答案中的代码尝试此数组:

$contextOptions = array(
    'ssl' => array(
        'verify_peer' => false,
        'verify_peer_name' => false
    )
);

Either way, if you're using self-signed certificates, you'll need to add the CA cert that was used to sign the remote host's SSL certificate to the trusted store on the server you're connecting from OR use stream contexts to use that certificate for each individual request. 无论哪种方式,如果您使用的是自签名证书,则需要将用于签署远程主机SSL证书的CA证书添加到您要连接的服务器上的受信任存储中,或者使用流上下文来使用每个请求的证书。 Adding it to the trusted certificates is the simplest solution. 将其添加到可信证书是最简单的解决方案。 Just add the contents of the remote host's CA cert to the end of the cacert.pem file you downloaded. 只需将远程主机CA证书的内容添加到您下载的cacert.pem文件的末尾即可。

Previous: 以前:

fsockopen doesn't support stream contexts, so use stream_socket_client instead. fsockopen不支持流上下文,因此请改用stream_socket_client。 It returns a resource that can be used with all the commands that fsockopen resources can. 它返回一个资源,可以与fsockopen资源可以使用的所有命令一起使用。

This should be a drop in replacement for the snippet you have in your question: 这应该是您在问题中的代码段的替代品:

<?php

$contextOptions = array(
    'ssl' => array(
        'verify_peer' => true, // You could skip all of the trouble by changing this to false, but it's WAY uncool for security reasons.
        'cafile' => '/etc/ssl/certs/cacert.pem',
        'CN_match' => 'example.com', // Change this to your certificates Common Name (or just comment this line out if not needed)
        'ciphers' => 'HIGH:!SSLv2:!SSLv3',
        'disable_compression' => true,
    )
);

$context = stream_context_create($contextOptions);

$fp = stream_socket_client("tcp://{$host}:{$port}", $errno, $errstr, 20, STREAM_CLIENT_CONNECT, $context);

if (!$fp) {

    echo "$errstr ({$errno})<br />\n";

}else{

    $this->request = 'POST '.substr($this->url, strlen($this->host)).' HTTP/1.1'.$crlf
        .'Host: '.$this->host.$crlf
        .'Content-Length: '.$content_length.$crlf
        .'Connection: Close'.$crlf.$crlf
        .$body;

    fwrite($fp, $this->request);

    while (!feof($fp)) {
        $this->response .= fgets($fp);
    }

    fclose($fp);

}

The problem is in new PHP Version in macOS Sierra 问题出在macOS Sierra的新PHP版本中

Please add 请加

stream_context_set_option($ctx, 'ssl', 'verify_peer', false);

I faced a similar issue during work with Ubuntu 16.04 by using Docker. 我使用Docker在使用Ubuntu 16.04时遇到了类似的问题。 In my case that was a problem with Composer, but error message (and thus the problem) was the same. 在我的情况下,这是Composer的问题,但错误消息(因此问题)是相同的。

Because of minimalist Docker-oriented base image I had missing ca-certificates package and simple apt-get install ca-certificates helped me. 由于极简主义的面向Docker的基本映像,我缺少ca-certificates包和简单的apt-get install ca-certificates帮助了我。

Add

$mail->SMTPOptions = array(
'ssl' => array(
    'verify_peer' => false,
    'verify_peer_name' => false,
    'allow_self_signed' => true
));

before 之前

mail->send()

and replace 并替换

require "mailer/class.phpmailer.php";

with

require "mailer/PHPMailerAutoload.php";

Firstable, make sure that you Antivirus software doesn't block SSL2. Firstable,确保您的防病毒软件不会阻止SSL2。
Because I could not solve a problem for a long time and only disabling the antivirus helped me 因为我长时间无法解决问题,只有禁用防病毒帮助了我

You mention the certificate is self-signed (by you)? 你提到证书是自签名的(由你)? Then you have two choices: 那你有两个选择:

  • add the certificate to your trust store (fetching cacert.pem from cURL website won't do anything, since it's self-signed) 将证书添加到您的信任存储区(从cURL网站获取cacert.pem将不会执行任何操作,因为它是自签名的)
  • don't bother verifying the certificate: you trust yourself, don't you? 不要打扰验证证书:你相信自己,不是吗?

Here's a list of SSL context options in PHP: https://secure.php.net/manual/en/context.ssl.php 以下是PHP中的SSL上下文选项列表: https//secure.php.net/manual/en/context.ssl.php

Set allow_self_signed if you import your certificate into your trust store, or set verify_peer to false to skip verification. 设置allow_self_signed如果导入您的证书到您的信任存储,或者设置verify_peer为false以跳过验证。

The reason why we trust a specific certificate is because we trust its issuer . 我们信任特定证书的原因是因为我们信任其发行人 Since your certificate is self-signed, no client will trust the certificate as the signer (you) is not trusted. 由于您的证书是自签名的,因此签名者(您)不受信任,因此任何客户都不会信任该证书。 If you created your own CA when signing the certificate, you can add the CA to your trust store. 如果在签署证书时创建了自己的CA,则可以将CA添加到信任库。 If your certificate doesn't contain any CA, then you can't expect anyone to connect to your server. 如果您的证书不包含任何CA,那么您不能指望任何人连接到您的服务器。

In my case, I was on CentOS 7 and my php installation was pointing to a certificate that was being generated through update-ca-trust . 在我的情况下,我在CentOS 7上,我的php安装指向通过update-ca-trust生成的证书。 The symlink was /etc/pki/tls/cert.pem pointing to /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem . 符号链接是/etc/pki/tls/cert.pem指向/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem This was just a test server and I wanted my self signed cert to work properly. 这只是一个测试服务器,我希望我的自签名证书能够正常工作。 So in my case... 所以在我的情况下......

# My root ca-trust folder was here. I coped the .crt file to this location
# and renamed it to a .pem
/etc/pki/ca-trust/source/anchors/self-signed-cert.pem

# Then run this command and it will regenerate the certs for you and
# include your self signed cert file.
update-ca-trust

Then some of my api calls started working as my cert was now trusted. 然后我的一些api调用开始工作,因为我的证书现在已被信任。 Also if your ca-trust gets updated through yum or something, this will rebuild your root certificates and still include your self signed cert. 此外,如果您的ca-trust通过yum或其他内容进行更新,这将重建您的根证书并仍然包含您的自签名证书。 Run man update-ca-trust for more info on what to do and how to do it. 运行man update-ca-trust以获取有关如何操作以及如何执行操作的更多信息。 :) :)

If you are using macOS sierra there is a update in PHP version. 如果您使用的是macOS sierra,则会有PHP版本的更新。 you need to have Entrust.net Certificate Authority (2048) file added to the PHP code. 您需要将Entrust.net证书颁发机构(2048)文件添加到PHP代码中。 more info check accepted answer here Push Notification in PHP using PEM file 更多信息检查接受的答案在这里使用PEM文件在PHP中推送通知

Have you tried using the stream_context_set_option() method ? 您是否尝试过使用stream_context_set_option()方法?

$context = stream_context_create();
$result = stream_context_set_option($context, 'ssl', 'local_cert', '/etc/ssl/certs/cacert.pem');
$fp = fsockopen($host, $port, $errno, $errstr, 20, $context);

In addition, try file_get_contents() for the pem file, to make sure you have permissions to access it, and make sure the host name matches the certificate. 此外,请尝试pem文件的file_get_contents() ,以确保您有权访问它,并确保主机名与证书匹配。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 php SSL3_GET_SERVER_CERTIFICATE:证书验证失败 - php SSL3_GET_SERVER_CERTIFICATE:certificate verify failed PHPMailer - SSL3_GET_SERVER_CERTIFICATE:证书验证失败 - PHPMailer - SSL3_GET_SERVER_CERTIFICATE:certificate verify failed 错误信息:error:14090086:SSLroutines:ssl3_get_server_certificate:certificate verify failed - Error message: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed Composer 错误:14090086:SSL 例程:SSL3_GET_SERVER_CERTIFICATE:证书验证失败 - Composer error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed PHPMailer 5.2 OpenSSL 错误消息:错误:14090086:SSL 例程:SSL3_GET_SERVER_CERTIFICATE:证书验证失败 - PHPMailer 5.2 OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed SSL3_GET_SERVER_CERTIFICATE证书在Windows 10 Pro with IIS上验证失败 - SSL3_GET_SERVER_CERTIFICATE certificate verify failed on Windows 10 Pro with IIS mysqli_real_connect()获取SSL3_GET_SERVER_CERTIFICATE:证书验证失败 - mysqli_real_connect() getting SSL3_GET_SERVER_CERTIFICATE:certificate verify failed SSL3_GET_SERVER_CERTIFICATE:证书验证在mac上使用xampp失败 - SSL3_GET_SERVER_CERTIFICATE:certificate verify failed using xampp on mac HTTPS and SSL3_GET_SERVER_CERTIFICATE:certificate verify failed, CA is OK - HTTPS and SSL3_GET_SERVER_CERTIFICATE:certificate verify failed, CA is OK 使用 php 通过 https 加载外部 xml 文件时出错:SSL3_GET_SERVER_CERTIFICATE - Error when loading external xml file with php via https : SSL3_GET_SERVER_CERTIFICATE
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM