OpenSSL समस्या निवारण: unable to get local issuer certificate
त्रुटि का समाधान
जब OpenSSL का उपयोग सुरक्षित कनेक्शन के लिए किया जाता है (जैसे PHP में नेटवर्क अनुरोध, openssl
या curl
कमांड चलाना, या Node.js/Python ऐप्स में SSL/TLS कनेक्शन बनाना), तो डेवलपर्स को अक्सर 20:unable to get local issuer certificate
त्रुटि संदेश मिल सकता है। यह एक सामान्य, ऐतिहासिक समस्या है जो OpenSSL के प्रमाणपत्र सत्यापन के तरीके से संबंधित है।
सुरक्षा कारणों से, OpenSSL जब प्रमाणपत्र श्रृंखला की जांच करता है तो उसे विश्वसनीय रूट सर्टिफिकेट अथॉरिटी (CA) की स्पष्ट जानकारी चाहिए। अगर उसे ये विश्वसनीय आधार नहीं मिलते या निर्दिष्ट नहीं किए जाते, तो वह सर्वर प्रमाणपत्र की वैधता की पुष्टि नहीं कर सकता, जिससे यह त्रुटि सामने आती है।
यह लेख इस त्रुटि के कारणों की विस्तार से व्याख्या करता है और ServBay वातावरण में इसका समाधान कैसे करें, इस पर निर्देश देता है। इसमें PHP, Python, Node.js और curl
कमांड के लिए OpenSSL ट्रस्ट स्टोर को कॉन्फ़िगर करने के तरीके बताए गए हैं।
त्रुटि संदेश 20:unable to get local issuer certificate
समस्या विवरण
जब OpenSSL रिमोट सर्वर के SSL/TLS प्रमाणपत्र को सत्यापित करने की कोशिश करता है, तो वह एक प्रमाणपत्र श्रृंखला बनाता है जो सर्वर सर्टिफिकेट से लेकर विश्वसनीय रूट CA तक जाती है। यदि OpenSSL को स्थानीय रूप से कोई आवश्यक इंटरमीडिएट या अंतिम रूट CA प्रमाणपत्र नहीं मिल पाता, या उसके पास विश्वसनीय स्टोर (CAFile या CAPath) का कॉन्फ़िगरेशन नहीं है, तो सत्यापन विफल हो जाता है और 20:unable to get local issuer certificate
त्रुटि दिखाई देती है।
साधारण भाषा में कहें तो, OpenSSL यह नहीं जानता कि किस सर्टिफिकेट अथॉरिटी पर भरोसा किया जाए, इसलिए वह कनेक्ट किए जा रहे सर्वर की पहचान की पुष्टि नहीं कर सकता।
ServBay में OpenSSL संस्करण और CA प्रमाणपत्र पथ
ServBay एक एकीकृत स्थानीय वेब विकास वातावरण है, जिसमें OpenSSL के पैकेज्ड संस्करण के साथ आम सार्वजनिक रूट CA प्रमाणपत्र शामिल हैं, जिससे डेवलपर्स को आसानी होती है। ServBay में OpenSSL का कौन-सा संस्करण प्रयोग होगा, यह आपके डिवाइस के चिपसेट पर निर्भर करता है:
- Apple Silicon (M Series) के लिए ServBay: OpenSSL 3.2.1 संस्करण का उपयोग करता है।
- Intel चिप वाले Mac के लिए ServBay: OpenSSL 1.1.1u संस्करण का उपयोग करता है।
इन OpenSSL संस्करणों के संबंधित CA प्रमाणपत्र फाइल (cacert.pem
) और प्रमाणपत्र निर्देशिका (certs
) ServBay के इंस्टालेशन पथ के अंतर्गत होती हैं। आपको अपने ServBay संस्करण के अनुसार सही पथ देखना होगा:
ini
# सभी विश्वसनीय रूट सर्टिफिकेट का बंडल फाइल
cafile=/Applications/ServBay/package/common/openssl/3.2/cacert.pem
# अलग-अलग प्रमाणपत्र फाइलों की निर्देशिका (आमतौर पर केवल cacert.pem पर्याप्त है, कुछ एप्लिकेशन capath की जरूरत कर सकते हैं)
capath=/Applications/ServBay/package/common/openssl/3.2/certs
1
2
3
4
2
3
4
ini
# सभी विश्वसनीय रूट सर्टिफिकेट का बंडल फाइल
cafile=/Applications/ServBay/package/common/openssl/1.1.1u/cacert.pem
# अलग-अलग प्रमाणपत्र फाइलों की निर्देशिका
capath=/Applications/ServBay/package/common/openssl/1.1.1u/certs
1
2
3
4
2
3
4
unable to get local issuer certificate
त्रुटि का मूल समाधान है—जहाँ भी OpenSSL का उपयोग हो रहा हो, वहाँ ऊपर बताए गए cafile
या capath
का रास्ता स्पष्ट रूप से बताना, ताकि OpenSSL को विश्वसनीय CA प्रमाणपत्र मिल सकें।
समाधान के उदाहरण
नीचे दिए गए उदाहरण बताते हैं कि विभिन्न टूल और प्रोग्रामिंग भाषा वातावरणों में OpenSSL CA ट्रस्ट स्टोर कैसे निर्दिष्ट करें।
उदाहरण 1: openssl
कमांड के साथ कनेक्शन टेस्ट करना
अगर आप सीधे openssl s_client
कमांड से कनेक्शन टेस्ट करते समय इस तरह की त्रुटि देखते हैं:
bash
openssl s_client -quiet -connect gmail.com:443
1
आपको नीचे जैसा त्रुटि आउटपुट दिखाई दे सकता है, जिसमें verify error:num=20:unable to get local issuer certificate
भी शामिल होता है:
bash
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
# ... अन्य कनेक्शन जानकारी ...
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
समाधान:
-CAfile
पैरामीटर से ServBay द्वारा दी गई CA सर्टिफिकेट बंडल फाइल का पथ स्पष्ट रूप से निर्दिष्ट करें:
bash
openssl s_client -quiet -connect gmail.com:443 -CAfile /Applications/ServBay/package/common/openssl/3.2/cacert.pem
1
bash
openssl s_client -quiet -connect gmail.com:443 -CAfile /Applications/ServBay/package/common/openssl/1.1.1u/cacert.pem
1
सफल कनेक्शन और प्रमाणपत्र सत्यापन के बाद, आउटपुट में verify return
की वैल्यू 1
होगी और verify error:num=20
वाला संदेश नहीं आएगा:
bash
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
# ... अन्य कनेक्शन जानकारी ...
1
2
3
4
5
6
7
2
3
4
5
6
7
उदाहरण 2: PHP में OpenSSL का उपयोग
PHP की कई नेटवर्क विशेषताएँ (जैसे file_get_contents
के ज़रिए HTTPS URL एक्सेस करना, stream_socket_client
से SSL/TLS कनेक्शन बनाना, या cURL एक्सटेंशन) OpenSSL पर निर्भर करती हैं। आप php.ini
फाइल संपादित करके या कोड में stream context ऑप्शन सेट करके CA ट्रस्ट स्टोर निर्दिष्ट कर सकते हैं।
तरीका A: php.ini
में बदलाव करें (अनुशंसित)
यह सबसे आसान और वैश्विक समाधान है। सर्वे के कंट्रोल पैनल मे जाकर मौजूदा PHP संस्करण की php.ini
फाइल में [openssl]
सेक्शन खोजें और निम्नलिखित को जोड़ें या संशोधित करें। अपने चिप टाइप के अनुसार सही पथ दें।
ini
[openssl]
; विश्वसनीय CA प्रमाणपत्र बंडल फाइल का पथ
openssl.cafile=/Applications/ServBay/package/common/openssl/3.2/cacert.pem
; प्रमाणपत्र फाइलों की निर्देशिका का पथ (ऐच्छिक, लेकिन सेट करना अच्छा है)
openssl.capath=/Applications/ServBay/package/common/openssl/3.2/certs
1
2
3
4
5
2
3
4
5
ini
[openssl]
; विश्वसनीय CA प्रमाणपत्र बंडल फाइल का पथ
openssl.cafile=/Applications/ServBay/package/common/openssl/1.1.1u/cacert.pem
; प्रमाणपत्र फाइलों की निर्देशिका का पथ (ऐच्छिक, लेकिन सेट करना अच्छा है)
openssl.capath=/Applications/ServBay/package/common/openssl/1.1.1u/certs
1
2
3
4
5
2
3
4
5
php.ini
में बदलाव के बाद, ServBay में PHP सेवा (या पूरी सर्वबे) को पुनः प्रारंभ करें ताकि परिवर्तन प्रभावी हों।
तरीका B: कोड में कॉन्फ़िगरेशन जोड़ें (केवल मौजूदा कनेक्शन पर असर)
अगर आप वैश्विक php.ini
में बदलाव नहीं करना चाहते, तो stream_context_create
से SSL/TLS कनेक्शन के लिए context विकल्प सेट करते समय ssl
विकल्प में cafile
जोड़ सकते हैं।
php
<?php
// उदाहरण: SSL/TLS के लिए SMTP सर्वर से जुड़ना
$server = 'ssl0.ovh.net';
$port = 465;
// अपने ServBay संस्करण के हिसाब से सही CA फाइल का पथ चुनें
// Apple Silicon के लिए:
$caCertFile = '/Applications/ServBay/package/common/openssl/3.2/cacert.pem';
// Intel के लिए:
// $caCertFile = '/Applications/ServBay/package/common/openssl/1.1.1u/cacert.pem';
$contextOptions = [
'ssl' => [
'verify_peer' => true, // प्रतिरूप प्रमाणपत्र सत्यापन सक्षम
'verify_peer_name' => true, // कनेक्ट हो रहे होस्ट से प्रमाणपत्र के नाम का मेल
'allow_self_signed' => false, // केवल विश्वसनीय प्रमाणपत्र स्वीकार करें
'cafile' => $caCertFile, // CA प्रमाणपत्र बंडल फाइल का पथ
// 'capath' => '/Applications/ServBay/package/common/openssl/3.2/certs', // ऐच्छिक—CA प्रमाणपत्र फोल्डर
],
];
$context = stream_context_create($contextOptions);
// बनाए गए context के साथ SSL/TLS कनेक्शन बनाएं
$connection = @stream_socket_client(
"ssl://$server:$port",
$errno,
$errstr,
30, // कनेक्शन टाइमआउट
STREAM_CLIENT_CONNECT,
$context
);
if ($connection) {
echo "Connection established to $server:$port\n";
// उदाहरण: EHLO कमांड भेजना
fwrite($connection, "EHLO servbay.demo\r\n"); // ServBay के ब्रांड डोमेन के साथ उदाहरण
while (!feof($connection)) {
echo fgets($connection);
}
fclose($connection);
} else {
echo "Failed to connect to $server:$port. Error: $errstr ($errno)\n";
}
?>
1
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
40
41
42
43
44
45
46
47
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
40
41
42
43
44
45
46
47
उदाहरण 3: Python में OpenSSL का उपयोग (ssl मॉड्यूल)
Python का ssl
मॉड्यूल भी SSL/TLS context बनाने और विश्वसनीय CA प्रमाणपत्र निर्दिष्ट करने में सक्षम है।
python
import ssl
import socket
server = 'ssl0.ovh.net'
port = 465
# अपने ServBay संस्करण के हिसाब से सही CA फाइल का पथ चुनें
# Apple Silicon के लिए:
ca_cert_file = '/Applications/ServBay/package/common/openssl/3.2/cacert.pem'
# Intel के लिए:
# ca_cert_file = '/Applications/ServBay/package/common/openssl/1.1.1u/cacert.pem'
# डिफ़ॉल्ट SSL context बनाएं, और CA फाइल निर्धारित करें
context = ssl.create_default_context(cafile=ca_cert_file)
# साथ में directory भी सेट कर सकते हैं: context = ssl.create_default_context(capath='/Applications/ServBay/package/common/openssl/3.2/certs')
try:
# सामान्य socket कनेक्शन बनाएं
with socket.create_connection((server, port)) as sock:
# socket को SSL socket में लपेटें
with context.wrap_socket(sock, server_hostname=server) as ssock:
print(f"SSL connection established. Negotiated Protocol: {ssock.version()}")
# उदाहरण: EHLO कमांड भेजना
ssock.sendall(b"EHLO servbay.demo\r\n") # ServBay ब्रांड डोमेन
while True:
data = ssock.recv(4096)
if not data:
break
print(data.decode())
except Exception as e:
print(f"Failed to connect or SSL error: {e}")
1
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
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
उदाहरण 4: Node.js में OpenSSL का उपयोग (tls मॉड्यूल)
Node.js के tls
मॉड्यूल से SSL/TLS कनेक्शन बनते हैं। कनेक्शन ऑप्शन्स में ca
प्रॉपर्टी द्वारा आप CA प्रमाणपत्र सेट कर सकते हैं। यह फाइल कंटेंट के स्ट्रिंग या बफ़र का ऐरे हो सकता है। सबसे आसान तरीका है ServBay का cacert.pem
फाइल पढ़ना।
javascript
const tls = require('tls');
const fs = require('fs');
const server = 'www.google.com'; // एक भरोसेमंद वेबसाइट का उदाहरण
const port = 443;
// अपने ServBay संस्करण के अनुसार सही CA फाइल का पथ चुनें
// Apple Silicon के लिए:
const caCertFile = '/Applications/ServBay/package/common/openssl/3.2/cacert.pem';
// Intel के लिए:
// const caCertFile = '/Applications/ServBay/package/common/openssl/1.1.1u/cacert.pem';
const options = {
host: server,
port: port,
// CA प्रमाणपत्र फाइल पढ़ना
ca: fs.readFileSync(caCertFile),
// Node.js tls मॉड्यूल में डिफ़ॉल्ट रूप से होस्टनेम चेक (checkServerIdentity) होता है,
// यदि CA प्रमाणपत्र सही हो और सर्वर प्रमाणपत्र वैध हो तो यह सत्यापन सफल होना चाहिए।
// जब तक जरूरी ना हो या आप जोखिम न समझ लें, checkServerIdentity को डिसेबल न करें।
// checkServerIdentity: () => { return null; } // <-- इसे प्रयोग न करें, यह जरूरी सुरक्षा को बंद करता है!
};
const socket = tls.connect(options, () => {
console.log('SSL connection established');
// HTTPS कनेक्शन के लिए सामान्यतः HTTP अनुरोध भेजना पड़ता है, यहाँ केवल कनेक्शन का उदाहरण है
// socket.write('GET / HTTP/1.1\r\nHost: ' + server + '\r\n\r\n');
});
socket.on('data', (data) => {
console.log(data.toString());
});
socket.on('close', () => {
console.log('Connection closed');
});
socket.on('error', (error) => {
console.error('Error:', error.message); // त्रुटि सूचना दिखाएँ
});
1
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
40
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
40
नोट: Node.js उदाहरण से checkServerIdentity: () => { return null; }
को हटा दिया गया है। यह ऑप्शन सर्वर होस्टनेम वैरिफिकेशन को बंद करता है, जो असुरक्षित है। OpenSSL की unable to get local issuer certificate
त्रुटि भरोसेमंद जड़ से संबंधित है, न कि होस्टनेम वैरिफिकेशन से। अगर सही रूप से ca
विकल्प तथा वैध सर्वर प्रमाणपत्र दिया जाए, तो Node.js की डिफ़ॉल्ट होस्टनेम वैरिफिकेशन पास होनी चाहिए। यदि होस्टनेम वैरिफिकेशन में समस्या आ रही है, तो अधिकतर गलती प्रमाणपत्र में है, ट्रस्ट स्टोर में नहीं।
उदाहरण 5: curl
कमांड में OpenSSL का प्रयोग
curl
कमांड भी HTTPS अनुरोधों के लिए OpenSSL (या कोई अन्य SSL लाइब्रेरी) का प्रयोग करती है। आप --cacert
पैरामीटर से भी CA सर्टिफिकेट बंडल फाइल तय कर सकते हैं।
bash
# ServBay की CA सर्टिफिकेट फाइल का उपयोग करते हुए HTTPS साइट एक्सेस करना
# अपने ServBay संस्करण के हिसाब से सही पथ चुनें
# Apple Silicon के लिए:
curl --cacert /Applications/ServBay/package/common/openssl/3.2/cacert.pem https://example.com
# Intel के लिए:
# curl --cacert /Applications/ServBay/package/common/openssl/1.1.1u/cacert.pem https://example.com
1
2
3
4
5
6
7
2
3
4
5
6
7
अगर CA सर्टिफिकेट का मार्ग सही है और सर्वर प्रमाणपत्र वैध है, तो curl
बिना कोई प्रमाणपत्र त्रुटि दिखाए सामग्री प्राप्त करेगा।
सारांश
20:unable to get local issuer certificate
त्रुटि SSL/TLS कनेक्शन के लिए OpenSSL के साथ आम है। इसका मूल कारण है कि OpenSSL को सत्यापित करने के लिए एक विश्वसनीय स्टोर चाहिए। ServBay डेवलपर्स के लिए आम सार्वजनिक रूट CA प्रमाणपत्रों की cacert.pem
फाइल पहले से उपलब्ध कराता है।
समाधान यह है कि अपने विकास वातावरण में (php.ini
, कोड में SSL context विकल्प, कमांड लाइन विकल्प—जैसे openssl
का -CAfile
, या curl
का --cacert
) ServBay की दी गई cacert.pem
फाइल का मार्ग भली-भांति दर्ज करें। ध्यान दें कि macOS की चिप टाइप (Apple Silicon या Intel) और सेवबे के OpenSSL संस्करण के हिसाब से सही मार्ग चुनें। सही ट्रस्ट स्टोर कॉन्फ़िगरेशन के साथ, आपका स्थानीय विकास वातावरण बाहरी SSL/TLS सेवाओं के साथ सुरक्षित रूप से संवाद कर सकेगा।