OpenSSL-Fehlerbehebung
Bei der Verwendung von OpenSSL (einschließlich in der PHP-Umgebung, dem openssl
-Befehl, dem curl
-Befehl) kann es zu Fehlermeldungen 20:unable to get local issuer certificate
kommen. Dies ist ein häufiges historisches Problem von OpenSSL. Aus Sicherheitsgründen vertraut OpenSSL bei direktem Aufruf keinem CA und benötigt eine spezielle Angabe von CAFile oder CAPath. Dieser Artikel stellt Lösungen für dieses Problem vor und liefert relevante Codebeispiele für PHP, Python und Node.js.
Fehlermeldung 20:unable to get local issuer certificate
Problembeschreibung
Wenn bei der Verwendung von OpenSSL die Fehlermeldung 20:unable to get local issuer certificate
auftritt, liegt dies daran, dass OpenSSL das lokale Ausstellerzertifikat nicht finden kann. Die Lösung für dieses Problem besteht darin, CAFile oder CAPath anzugeben.
OpenSSL-Version in ServBay
Je nach verwendetem Chiptyp variiert die OpenSSL-Version in ServBay:
- ServBay mit Intel-Chip: Verwendet OpenSSL Version 1.1.1u
- ServBay mit Apple Silicon Chip: Verwendet OpenSSL Version 3.2.1
Entsprechende Dateipfade
cafile=/Applications/ServBay/package/common/openssl/3.2/cacert.pem
capath=/Applications/ServBay/package/common/openssl/3.2/certs
2
cafile=/Applications/ServBay/package/common/openssl/1.1.1u/cacert.pem
capath=/Applications/ServBay/package/common/openssl/1.1.1u/certs
2
Beispiel: Verwendung des OpenSSL-Befehls
Wenn bei der Ausführung des folgenden Befehls ein Fehler auftritt:
openssl s_client -quiet -connect gmail.com:443
könnte die Fehlermeldung wie folgt aussehen:
Connecting to 172.217.163.37
depth=2 C=US, O=Google Trust Services LLC, CN=GTS Root R1
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=1 C=US, O=Google Trust Services, CN=WR2
verify return:1
depth=0 CN=gmail.com
verify return:1
2
3
4
5
6
7
8
Lösung
Durch Angabe von CAFile kann das Problem gelöst werden:
openssl s_client -quiet -connect gmail.com:443 -CAfile /Applications/ServBay/package/common/openssl/3.2/cacert.pem
Nach erfolgreicher Verbindung sieht die Ausgabe folgendermaßen aus:
Connecting to 172.217.163.37
depth=2 C=US, O=Google Trust Services LLC, CN=GTS Root R1
verify return:1
depth=1 C=US, O=Google Trust Services, CN=WR2
verify return:1
depth=0 CN=gmail.com
verify return:1
2
3
4
5
6
7
Beispiel: Verwendung von OpenSSL in PHP
Wenn OpenSSL in PHP verwendet wird, kann das Problem durch Ändern der php.ini
Datei oder durch Hinzufügen der entsprechenden Konfiguration im Code gelöst werden.
Änderung der php.ini
In der php.ini
Datei im Abschnitt [openssl]
füge oder ändere die folgenden Inhalte:
[openssl]
openssl.cafile=/Applications/ServBay/package/common/openssl/3.2/cacert.pem
openssl.capath=/Applications/ServBay/package/common/openssl/3.2/certs
2
3
[openssl]
openssl.cafile=/Applications/ServBay/package/common/openssl/1.1.1u/cacert.pem
openssl.capath=/Applications/ServBay/package/common/openssl/1.1.1u/certs
2
3
Hinzufügen der Konfiguration im Code
Du kannst CAFile auch im PHP-Code angeben. Zum Beispiel:
<?php
$server = 'ssl0.ovh.net';
$port = 465;
// CA-Dateipfad
$caCertFile = '/Applications/ServBay/package/common/openssl/3.2/cacert.pem';
$contextOptions = [
'ssl' => [
'verify_peer' => true,
'verify_peer_name' => true,
'allow_self_signed' => false,
'cafile' => $caCertFile,
],
];
$context = stream_context_create($contextOptions);
$connection = @stream_socket_client(
"ssl://$server:$port",
$errno,
$errstr,
30,
STREAM_CLIENT_CONNECT,
$context
);
if ($connection) {
echo "Verbindung zu $server:$port hergestellt\n";
fwrite($connection, "EHLO example.com\r\n");
while ($line = fgets($connection)) {
echo $line;
}
fclose($connection);
} else {
echo "Verbindung zu $server:$port fehlgeschlagen. Fehler: $errstr ($errno)\n";
}
?>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Beispiel: Verwendung von OpenSSL in Python
Wenn OpenSSL in Python verwendet wird, kann CAFile im Code angegeben werden. Zum Beispiel:
import ssl
import socket
server = 'ssl0.ovh.net'
port = 465
ca_cert_file = '/Applications/ServBay/package/common/openssl/3.2/cacert.pem'
context = ssl.create_default_context(cafile=ca_cert_file)
with socket.create_connection((server, port)) as sock:
with context.wrap_socket(sock, server_hostname=server) as ssock:
print(f"SSL-Verbindung hergestellt. Peer: {ssock.getpeercert()}")
ssock.sendall(b"EHLO example.com\r\n")
while True:
data = ssock.recv(4096)
if not data:
break
print(data.decode())
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Beispiel: Verwendung von OpenSSL in Node.js
Wenn OpenSSL in Node.js verwendet wird, kann CAFile im Code angegeben werden. Zum Beispiel:
const tls = require('tls');
const fs = require('fs');
const server = 'ssl0.ovh.net';
const port = 465;
const caCertFile = '/Applications/ServBay/package/common/openssl/3.2/cacert.pem';
const options = {
host: server,
port: port,
ca: fs.readFileSync(caCertFile),
checkServerIdentity: () => { return null; } // Ignoriere Server-ID-Überprüfung
};
const socket = tls.connect(options, () => {
console.log('SSL-Verbindung hergestellt');
socket.write("EHLO example.com\r\n");
});
socket.on('data', (data) => {
console.log(data.toString());
});
socket.on('error', (error) => {
console.error('Fehler:', error);
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Beispiel: Verwendung von curl und OpenSSL
Wenn das Problem bei der Verwendung des curl
-Befehls auftritt, kann durch Angabe von CAFile gelöst werden:
curl --cacert /Applications/ServBay/package/common/openssl/3.2/cacert.pem https://example.com
Zusammenfassung
Wenn bei der Verwendung von OpenSSL die Fehlermeldung 20:unable to get local issuer certificate
auftritt, kann das Problem durch Angabe von CAFile oder CAPath gelöst werden. Finde je nach Chiptyp des Geräts die entsprechenden CAFile- und CAPath-Pfade und setze die Angabe in den OpenSSL-Befehlen, der PHP-, Python-, Node.js- oder curl-Konfiguration.