web-dev-qa-db-ja.com

SSLエラーSSL3_GET_SERVER_CERTIFICATE:証明書の検証に失敗しました

PHP 5.6にアップグレードした後、fsockopen()経由でサーバーに接続しようとするとエラーが発生します。

サーバー(ホスト)上の証明書は自己署名されています

PHP警告:fsockopen():SSL操作はコード1で失敗しました。OpenSSLエラーメッセージ:エラー:14090086:SSLルーチン:SSL3_GET_SERVER_CERTIFICATE:証明書の検証に失敗しました

コード

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);
}

試しました

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

php.ini

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

しかし、スクリプトはまだ動作しません

更新

これは動作します

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

アップデート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);

エラー

PHP警告:stream_socket_client():SSL操作はコード1で失敗しました。OpenSSLエラーメッセージ:エラー:14090086:SSLルーチン:SSL3_GET_SERVER_CERTIFICATE:証明書の検証に失敗しました

42
clarkk

ダウンロードしたファイル( http://curl.haxx.se/ca/cacert.pem )は、主要な信頼できる認証局からのルート証明書のバンドルです。リモートホストには自己署名SSL証明書があるため、信頼できる証明書を使用しなかったと言いました。 openssl.cafile設定は、リモートホスト上のSSL証明書に署名するために使用されたCA証明書を指す必要があります。 PHP 5.6は、以前のバージョンのPHPよりも改善され、デフォルトでピア証明書とホスト名を検証するようになりました( http://php.net/manual/en/migration56 .openssl.php

SSL証明書に署名したサーバーで生成されたCA証明書を見つけて、このサーバーにコピーする必要があります。他の唯一のオプションはピアの検証を無効にすることですが、それはSSLセキュリティを無効にします。検証を無効にしたい場合は、前の回答のコードでこの配列を試してください:

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

いずれにせよ、自己署名証明書を使用している場合、リモートホストのSSL証明書の署名に使用されたCA証明書を、ORから接続しているサーバー上の信頼できるストアに追加する必要があります。 _ストリームコンテキストを使用して、個々の要求にその証明書を使用します。信頼できる証明書に追加するのが最も簡単なソリューションです。ダウンロードしたcacert.pemファイルの最後に、リモートホストのCA証明書の内容を追加するだけです。

前:

fsockopenはストリームコンテキストをサポートしていないため、代わりにstream_socket_clientを使用してください。 fsockopenリソースが実行できるすべてのコマンドで使用できるリソースを返します。

これは、質問に含まれているスニペットのドロップイン代替品である必要があります。

<?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);

}
32
aecend

問題はmacOS Sierraの新しいPHPバージョンにあります

追加してください

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

Ubuntu 16.04での作業中に、Dockerを使用して同様の問題に直面しました。私の場合、それはComposerの問題でしたが、エラーメッセージ(したがって問題)は同じでした。

最小限のDocker指向のベースイメージのため、ca-certificatesパッケージがなく、シンプルなapt-get install ca-certificatesが役に立ちました。

追加

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

mail->send()

そして交換

require "mailer/class.phpmailer.php";

require "mailer/PHPMailerAutoload.php";
3
Himanshu Sharma

まず、アンチウイルスソフトウェアがSSL2をブロックしないようにしてください。
長い間問題を解決できず、ウイルス対策を無効にしただけで助けられたため

1

証明書が自己署名されていると言いますか(あなたによって)?次に、2つの選択肢があります。

  • 証明書をトラストストアに追加します(cURL Webサイトからcacert.pemを取得しても、自己署名されているため何も実行されません)
  • 証明書を確認する必要はありません。あなたは自分自身を信頼しますよね?

以下は、PHPのSSLコンテキストオプションのリストです。 https://secure.php.net/manual/en/context.ssl.php

証明書をトラストストアにインポートする場合はallow_self_signedを設定するか、verify_peerをfalseに設定して検証をスキップします。

特定の証明書を信頼する理由は、そのissuerを信頼するためです。証明書は自己署名されているため、署名者(あなた)は信頼されないため、クライアントは証明書を信頼しません。証明書に署名するときに独自のCAを作成した場合は、CAをトラストストアに追加できます。証明書にCAが含まれていない場合、だれもサーバーに接続することは期待できません。

0
DavidS

私の場合、私はCentOS 7を使用しており、phpのインストールはupdate-ca-trustを介して生成された証明書を指していました。シンボリックリンクは/etc/pki/tls/cert.pem/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pemを指していました。これは単なるテストサーバーであり、自己署名証明書が適切に機能することを望んでいました。だから私の場合は...

# 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

その後、証明書が信頼できるようになったため、API呼び出しの一部が機能し始めました。また、ca-trustがyumなどによって更新された場合、これによりルート証明書が再構築され、自己署名証明書が含まれます。 man update-ca-trustを実行して、実行する方法とその方法の詳細を確認してください。 :)

0
n0nag0n

MacOS sierraを使用している場合、PHPバージョンの更新があります。 Entrust.net認証局(2048)ファイルをPHPコードに追加する必要があります。詳細情報はここで受け入れられた回答を確認してください PEMファイルを使用してPHPのプッシュ通知

0
Im Batman