Risoluzione dei Problemi di OpenSSL
Quando si utilizza OpenSSL (incluso negli ambienti PHP, il comando openssl
, il comando curl
), potrebbe capitare di incontrare l'errore 20:unable to get local issuer certificate
. Questo è un problema comune ereditato nell'uso storico di OpenSSL. Per motivi di sicurezza, OpenSSL non si fida di alcun CA quando viene invocato direttamente ed è necessario specificare appositamente CAFile o CAPath. Questo articolo spiega come risolvere il problema, fornendo esempi di codice rilevanti per PHP, Python e Node.js.
Errore 20:unable to get local issuer certificate
Descrizione del Problema
Se durante l'uso di OpenSSL si verifica l'errore 20:unable to get local issuer certificate
, significa che OpenSSL non riesce a trovare il certificato dell'autorità di certificazione locale. La soluzione a questo problema è specificare CAFile o CAPath.
Versioni di OpenSSL in ServBay
La versione di OpenSSL varia a seconda del tipo di chip utilizzato da ServBay:
- Versione Intel di ServBay: utilizza OpenSSL versione 1.1.1u
- Versione Apple Silicon di ServBay: utilizza OpenSSL versione 3.2.1
Percorsi dei File Correlati
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
Esempio: Utilizzo del Comando OpenSSL
Se si verifica un errore eseguendo il seguente comando:
openssl s_client -quiet -connect gmail.com:443
Potresti vedere un errore simile al seguente:
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
Soluzione
Risolvi il problema specificando il CAFile:
openssl s_client -quiet -connect gmail.com:443 -CAfile /Applications/ServBay/package/common/openssl/3.2/cacert.pem
Dopo una connessione riuscita, l'output sarà simile al seguente:
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
Esempio: Uso di OpenSSL in PHP
Se si utilizza OpenSSL in PHP, è possibile risolvere il problema modificando il file php.ini
o aggiungendo la configurazione appropriata nel codice.
Modifica del file php.ini
Nella sezione [openssl]
del file php.ini
, aggiungi o modifica il seguente contenuto:
[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
Aggiunta della Configurazione nel Codice
È possibile specificare CAFile direttamente nel codice PHP, ad esempio:
<?php
$server = 'ssl0.ovh.net';
$port = 465;
// Percorso del file CA
$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 "Connessione stabilita a $server:$port\n";
fwrite($connection, "EHLO example.com\r\n");
while ($line = fgets($connection)) {
echo $line;
}
fclose($connection);
} else {
echo "Connessione fallita a $server:$port. Errore: $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
Esempio: Uso di OpenSSL in Python
Se si utilizza OpenSSL in Python, è possibile specificare CAFile direttamente nel codice, ad esempio:
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 stabilito. 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
Esempio: Uso di OpenSSL in Node.js
Se si utilizza OpenSSL in Node.js, è possibile specificare CAFile direttamente nel codice, ad esempio:
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; } // Ignora la verifica dell'identità del server
};
const socket = tls.connect(options, () => {
console.log('Connessione SSL stabilita');
socket.write("EHLO example.com\r\n");
});
socket.on('data', (data) => {
console.log(data.toString());
});
socket.on('error', (errore) => {
console.error('Errore:', errore);
});
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
Esempio: Uso di curl con OpenSSL
Se si verifica un problema utilizzando il comando curl
, è possibile risolverlo specificando il CAFile:
curl --cacert /Applications/ServBay/package/common/openssl/3.2/cacert.pem https://example.com
Sommario
Quando si utilizza OpenSSL, se si verifica l'errore 20:unable to get local issuer certificate
, è possibile risolvere il problema specificando CAFile o CAPath. A seconda del tipo di chip del dispositivo, trova il percorso corrispondente di CAFile e CAPath, quindi configurali nei comandi OpenSSL, PHP, Python, Node.js oppure nelle configurazioni di curl.