SSL-fout SSL3_GET_SERVER_CERTIFICATE:certificaatverificatie mislukt

Na het upgraden naar PHP 5.6 krijg ik een foutmelding wanneer ik probeer verbinding te maken met een server via fsockopen()..

Het certificaat op de server (host) is zelfondertekend

PHP-waarschuwing: fsockopen(): SSL-bewerking is mislukt met code 1. OpenSSL-foutmeldingen:
error:14090086:SSL-routines:SSL3_GET_SERVER_CERTIFICATE:certificaat verifiëren mislukt

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

Heb het geprobeerd

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

php.ini

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

Maar het script werkt nog steeds niet

bijwerken

Dit werkt

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

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

fout

PHP-waarschuwing: stream_socket_client(): SSL-bewerking is mislukt met code 1. OpenSSL-foutmeldingen:
error:14090086:SSL-routines:SSL3_GET_SERVER_CERTIFICATE:certificaat verifiëren mislukt


Antwoord 1, autoriteit 100%

Het bestand dat je hebt gedownload (http://curl.haxx.se/ca/cacert .pem) is een bundel van de rootcertificaten van de belangrijkste vertrouwde certificaatautoriteiten. U zei dat de externe host een zelfondertekend SSL-certificaat heeft, dus geen vertrouwd certificaat gebruikte. De instelling openssl.cafilemoet verwijzen naar het CA-certificaat dat is gebruikt om het SSL-certificaat op de externe host te ondertekenen. PHP 5.6 is verbeterd ten opzichte van eerdere versies van PHP om nu standaard peercertificaten en hostnamen te verifiëren (http://php.net/manual/en/migration56.openssl.php)

U moet het CA-certificaat vinden dat is gegenereerd op de server die het SSL-certificaat heeft ondertekend en deze naar deze server kon kopiëren. Als u zelfondertekende certificaten gebruikt, moet u de CA CERT toevoegen die werd gebruikt om het SSL-certificaat van de Remote Host te ondertekenen op de Trusted Store op de server waar u verbinding maakt via of gebruik Stream Contexten om dat certificaat voor te gebruiken elk individueel verzoek. Het toevoegen aan de vertrouwde certificaten is de eenvoudigste oplossing. Voeg gewoon de inhoud van de CA-cert van de externe host toe aan het einde van het Cacert.pem-bestand dat u hebt gedownload.

Vorige:

Fsockopen ondersteunt geen streamcontexten, dus gebruik in plaats daarvan Stream_Socket_client. Het retourneert een bron die kan worden gebruikt met alle opdrachten die FSOCKOpen-middelen kunnen.

Dit moet een druppel in vervanging zijn voor het fragment dat u in uw vraag hebt:

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

Antwoord 2, autoriteit 18%

Ik heb een soortgelijk probleem ondervonden tijdens het werken met Ubuntu 16.04 door Docker te gebruiken. In mijn geval was dat een probleem met Composer, maar de foutmelding (en dus het probleem) was hetzelfde.

Vanwege de minimalistische Docker-georiënteerde basisafbeelding miste ik het pakket ca-certificatesen eenvoudige apt-get install ca-certificateshielp me.


Antwoord 3, autoriteit 15%

Het probleem zit in de nieuwe PHP-versie in macOS Sierra

Voeg toe

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

Antwoord 4, autoriteit 9%

Toevoegen

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

voor

mail->send()

en vervang

require "mailer/class.phpmailer.php";

met

require "mailer/PHPMailerAutoload.php";

Antwoord 5, autoriteit 3%

In mijn geval was ik op CentOS 7 en mijn php-installatie wees naar een certificaat dat werd gegenereerd via update-ca-trust. De symbolische link was /etc/pki/tls/cert.pemwijzend naar /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem. Dit was slechts een testserver en ik wilde dat mijn zelfondertekende certificaat goed zou werken. Dus in mijn geval…

# 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

Toen begonnen sommige van mijn api-aanroepen te werken omdat mijn certificaat nu werd vertrouwd. Ook als je ca-trust wordt bijgewerkt via yum of zoiets, zal dit je rootcertificaten opnieuw opbouwen en nog steeds je zelfondertekende certificaat bevatten. Voer man update-ca-trustuit voor meer informatie over wat u moet doen en hoe u dit moet doen. 🙂


Antwoord 6

Als eerste, zorg ervoor dat uw antivirussoftware SSL2 niet blokkeert.
Omdat ik een probleem lange tijd niet kon oplossen en alleen het uitschakelen van de antivirus hielp me


Antwoord 7

U vermeldt dat het certificaat zelfondertekend is (door u)? Dan heb je twee keuzes:

  • voeg het certificaat toe aan uw trust store (het ophalen van cacert.pemvan de cURL-website zal niets doen, aangezien het zelfondertekend is)
  • doe geen moeite om het certificaat te verifiëren: u vertrouwt uzelf, nietwaar?

Hier is een lijst met SSL-contextopties in PHP:
https://secure.php.net/manual/en/context.ssl.php

Stel allow_self_signedin als u uw certificaat importeert in uw trust store, of stel verify_peerin op false om verificatie over te slaan.

De reden waarom we een specifiek certificaat vertrouwen, is omdat we de uitgeververtrouwen. Aangezien uw certificaat zelfondertekend is, zal geen enkele client het certificaat vertrouwen, aangezien de ondertekenaar (u) niet wordt vertrouwd. Als u uw eigen CA hebt gemaakt bij het ondertekenen van het certificaat, kunt u de CA toevoegen aan uw trust store. Als uw certificaat geen CA bevat, kunt u niet verwachten dat iemand verbinding maakt met uw server.


Antwoord 8

Als je macOS sierra gebruikt, is er een update in de PHP-versie. u moet het bestand Entrust.net Certificate Authority (2048) hebben toegevoegd aan de PHP-code. meer info check geaccepteerd antwoord hier Pushmelding in PHP met PEM-bestand


Antwoord 9

Heb je geprobeerd de stream_context_set_option()methode te gebruiken?

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

Probeer bovendien file_get_contents()voor het pem-bestand, om er zeker van te zijn dat je toegangsrechten hebt en zorg ervoor dat de hostnaam overeenkomt met het certificaat.

Other episodes