CentOS8 出现 SSL certificate problem: unable to get local issuer certificate 解决办法

我想直接看解决办法

1.错误来源

我在一个docker安装的Centos8.5系统中启动我自己写的kook机器人时,遇到了下面的异常输出

1
aiohttp.client_exceptions.ClientConnectorCertificateError: Cannot connect to host www.kookapp.cn:443 ssl:True [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1002)')]
点我查看完整错误截图

错误截图

这个图片如果加载不出来也没关系,不影响本文内容。

报错的大概意思是没有办法获取到本地的issuer certificate。如果你知道证书和CA的含义,那么大概能猜到这个报错是什么意思。

所有站点的ssl证书,都需要经过CA机构的认证和颁发。操作系统会默认内嵌已有CA机构的公钥,以用于解密CA颁发的证书中的数字签名。

因为CA机构是内嵌在操作系统本地的,如果一个证书的颁发机构不在本地已有CA中,该站点的SSL证书可能是自签名证书,就会被报不安全。因为在默认情况下,自签名证书是不被认可的。

而无法获取本地issuer certificate,我猜测意思就是没有办法获取道操作系统内嵌的CA。

2.解决

刚开始我尝试过通过python的ssl模组取消证书验证、更新本地证书和openssl,都没有解决这个问题。

在Kook平台khl.py服务器的大佬帮助下,最终定位并解决了这个问题。

2.1 更新本地ca包

yum install ca-certificates,已经装过的话那就是 yum update ca-certificates 如果不行再 pip3 install certifi

操作完毕上面的步骤,发现本地已经安装了最新版本的ca-certificates,python也有安装certifi

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ yum update ca-certificates
Repository extras is listed more than once in the configuration
Warning: failed loading '/etc/yum.repos.d/epel.repo', skipping.
Last metadata expiration check: 8:42:37 ago on Thu 23 Feb 2023 03:09:14 PM UTC.
Dependencies resolved.
Nothing to do.
Complete!

$ pip3.10 install certifi
Defaulting to user installation because normal site-packages is not writeable
Requirement already satisfied: certifi in ./.local/lib/python3.10/site-packages (2022.12.7)

$ pip3.10 install certifi -U
Defaulting to user installation because normal site-packages is not writeable
Requirement already satisfied: certifi in ./.local/lib/python3.10/site-packages (2022.12.7)

2.2 查看本地主机的链接

于是尝试使用如下命令,看看主机是否能成功连接到kaiheila.cn(kookapp.cn) 并认证ssl证书

1
openssl s_client -connect www.kookapp.cn:443 -showcerts

输出了如下的信息

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
verify return:1
depth=1 C = US, O = "DigiCert, Inc.", CN = RapidSSL Global TLS RSA4096 SHA256 2022 CA1
verify return:1
depth=0 CN = *.kookapp.cn
verify return:1
CONNECTED(00000003)
---
Certificate chain
0 s:CN = *.kookapp.cn
i:C = US, O = "DigiCert, Inc.", CN = RapidSSL Global TLS RSA4096 SHA256 2022 CA1
-----BEGIN CERTIFICATE-----
MIIHkTCCBXmgAwIBAgIQCUlurlf6m1VXsuISNqlT8DANBgkqhkiG9w0BAQsFADBc
MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xNDAyBgNVBAMT
K1JhcGlkU1NMIEdsb2JhbCBUTFMgUlNBNDA5NiBTSEEyNTYgMjAyMiBDQTEwHhcN
MjIwNjE1MDAwMDAwWhcNMjMwNjE1MjM1OTU5WjAXMRUwEwYDVQQDDAwqLmtvb2th
cHAuY24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDB1uHkQ/oEkGNl
oVa6wHz424VznxL+eUt6AAfNhtIXeone8rtnJqeoDJ24lmBYUrL00tChCp4rdTdd
crqPppDYSEY7+/U0hf39pDrmsGKZeeOu7JvANjtvqLFdXsqe5CnXtxAo5QUXB9gc
kttoLTZZX5O1Gyi6mqDtsFCTaVpsQmZWVcbA21zLAdAZJyUyzM2VyfCUPQHs+VFE
rcmA9SN8nkppLyf00lIHCWR6v9HYC2XgjHN2JX8ARJwTEddhHjvleMc/SlHncU6f
pZ8itWx8NzBL6MwPKEjmHgKp0VYBMY6PHrSR/j/XtgOweodp1JBIr6yLLlyCu/lJ
ksCwMUIZAgMBAAGjggOSMIIDjjAfBgNVHSMEGDAWgBTwnIX9op99j8lou9XUiU0d
vtOQ/zAdBgNVHQ4EFgQUYe6lb4/s4J82aqWfNDaev2MD8k4wIwYDVR0RBBwwGoIM
Ki5rb29rYXBwLmNuggprb29rYXBwLmNuMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUE
FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwgZ8GA1UdHwSBlzCBlDBIoEagRIZCaHR0
cDovL2NybDMuZGlnaWNlcnQuY29tL1JhcGlkU1NMR2xvYmFsVExTUlNBNDA5NlNI
QTI1NjIwMjJDQTEuY3JsMEigRqBEhkJodHRwOi8vY3JsNC5kaWdpY2VydC5jb20v
UmFwaWRTU0xHbG9iYWxUTFNSU0E0MDk2U0hBMjU2MjAyMkNBMS5jcmwwPgYDVR0g
BDcwNTAzBgZngQwBAgEwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3dy5kaWdpY2Vy
dC5jb20vQ1BTMIGHBggrBgEFBQcBAQR7MHkwJAYIKwYBBQUHMAGGGGh0dHA6Ly9v
Y3NwLmRpZ2ljZXJ0LmNvbTBRBggrBgEFBQcwAoZFaHR0cDovL2NhY2VydHMuZGln
aWNlcnQuY29tL1JhcGlkU1NMR2xvYmFsVExTUlNBNDA5NlNIQTI1NjIwMjJDQTEu
Y3J0MAkGA1UdEwQCMAAwggF/BgorBgEEAdZ5AgQCBIIBbwSCAWsBaQB3AOg+0No+
9QY1MudXKLyJa8kD08vREWvs62nhd31tBr1uAAABgWbUskcAAAQDAEgwRgIhAL1q
ZKig2NqYtlAVnaXtJ7Tk+OuROrPHGR8t2zyNTb6xAiEAsLL5yuvJ/WtIj0bLwbKR
0/nFe/Juub3aZjrNvUhzZIIAdQA1zxkbv7FsV78PrUxtQsu7ticgJlHqP+Eq76gD
wzvWTAAAAYFm1LJ6AAAEAwBGMEQCIDK3qkxuTUB1Dngycy9/LECyVXjlpi2eJBAC
6oZPJQ/VAiBs1iupiYwavmD2m6QrDzzZrW2MJWx4LMxCtvf6pmN3NwB3ALc++yTf
nE26dfI5xbpY9Gxd/ELPep81xJ4dCYEl7bSZAAABgWbUsnkAAAQDAEgwRgIhAL5v
fkeeQAwowpkUhf0U/Z2fFiL8IY+QsCyED40zw0d1AiEA02UjHM3tztsrMn2xyzmT
kVgXnly/OozP+LjdwdsTa6gwDQYJKoZIhvcNAQELBQADggIBAGdBom7y2NXOZL7K
xtZFBFQCBJrEQOHZvuN4Etkmotb+0aVnrEZ/Qc5+zl86YqURcmOZgPhzSjuVfTvU
sJJ1TkC/tMYofoo1Db7B5yRxQmjEYRNLFAZ8rbP/pd5Js8ZGWW7RcxqG+zebqDDD
2CWvpiJNStu/yjWwdsFXQUwU0XOGUfwJDHD0eSBaa3uclAn3kUqF82l2X9qzvy9E
exGjPOSWyNuksjeScr32OyNUrwo7RUYJU4Ztl8xaiaxcvg7u2/o9WWzPhHMVI6ij
rJbj6Wn+BMe3SMYcR/L+foItjWAuOqOVB7IKO32JgCkP1vyl8AWs0up8ddI/9jn3
px8ii0HphKJnkCPZNmLnnOhFXQjoPy2PRmKqusP0kleJw1ZpQXsQpm3yZqFggyFH
8S4ii83kkHBynC89dlwlBIkF29Ds4mYjau6mZZxE69By7ptvFvcYREYslaRMxd16
6PEf5mp5jBKSiI2iYcP8PQOudhObpkuw+KHz8ntkf++HeluuEiqsKyiyyiXm5dmR
E/9uIUjPcQia5ohs2VpAgOLhLG6yphWCHQ6awFj9q3Ce1Mm5yXyZFvLXWGwoJj6j
CVXAZDchwX4uiHW2fI3GHz1pTPg0L3NE/M2CHnQWJlh9cgOljmaZXCeKmLdA9phD
+NQho5xVElRiF+rijlrkMutS7p1Y
-----END CERTIFICATE-----
1 s:C = US, O = "DigiCert, Inc.", CN = RapidSSL Global TLS RSA4096 SHA256 2022 CA1
i:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
-----BEGIN CERTIFICATE-----
MIIFyzCCBLOgAwIBAgIQCgWbJfVLPYeUzGYxR3U4ozANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0yMjA1MDQwMDAwMDBaFw0zMTExMDkyMzU5NTlaMFwxCzAJBgNVBAYTAlVT
MRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE0MDIGA1UEAxMrUmFwaWRTU0wgR2xv
YmFsIFRMUyBSU0E0MDk2IFNIQTI1NiAyMDIyIENBMTCCAiIwDQYJKoZIhvcNAQEB
BQADggIPADCCAgoCggIBAKY5PJhwCX2UyBb1nelu9APen53D5+C40T+BOZfSFaB0
v0WJM3BGMsuiHZX2IHtwnjUhLL25d8tgLASaUNHCBNKKUlUGRXGztuDIeXb48d64
k7Gk7u7mMRSrj+yuLSWOKnK6OGKe9+s6oaVIjHXY+QX8p2I2S3uew0bW3BFpkeAr
LBCU25iqeaoLEOGIa09DVojd3qc/RKqr4P11173R+7Ub05YYhuIcSv8e0d7qN1sO
1+lfoNMVfV9WcqPABmOasNJ+ol0hAC2PTgRLy/VZo1L0HRMr6j8cbR7q0nKwdbn4
Ar+ZMgCgCcG9zCMFsuXYl/rqobiyV+8U37dDScAebZTIF/xPEvHcmGi3xxH6g+dT
CjetOjJx8sdXUHKXGXC9ka33q7EzQIYlZISF7EkbT5dZHsO2DOMVLBdP1N1oUp0/
1f6fc8uTDduELoKBRzTTZ6OOBVHeZyFZMMdi6tA5s/jxmb74lqH1+jQ6nTU2/Mma
hGNxUuJpyhUHezgBA6sto5lNeyqc+3Cr5ehFQzUuwNsJaWbDdQk1v7lqRaqOlYjn
iomOl36J5txTs0wL7etCeMRfyPsmc+8HmH77IYVMUOcPJb+0gNuSmAkvf5QXbgPI
Zursn/UYnP9obhNbHc/9LYdQkB7CXyX9mPexnDNO7pggNA2jpbEarLmZGi4grMmf
AgMBAAGjggGCMIIBfjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBTwnIX9
op99j8lou9XUiU0dvtOQ/zAfBgNVHSMEGDAWgBQD3lA1VtFMu2bwo+IbG8OXsj3R
VTAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC
MHYGCCsGAQUFBwEBBGowaDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNl
cnQuY29tMEAGCCsGAQUFBzAChjRodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20v
RGlnaUNlcnRHbG9iYWxSb290Q0EuY3J0MEIGA1UdHwQ7MDkwN6A1oDOGMWh0dHA6
Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RDQS5jcmwwPQYD
VR0gBDYwNDALBglghkgBhv1sAgEwBwYFZ4EMAQEwCAYGZ4EMAQIBMAgGBmeBDAEC
AjAIBgZngQwBAgMwDQYJKoZIhvcNAQELBQADggEBAAfjh/s1f5dDdfm0sNm74/dW
MbbsxfYV1LoTpFt+3MSUWvSbiPQfUkoV57b5rutRJvnPP9mSlpFwcZ3e1nSUbi2o
ITGA7RCOj23I1F4zk0YJm42qAwJIqOVenR3XtyQ2VR82qhC6xslxtNf7f2Ndx2G7
Mem4wpFhyPDT2P6UJ2MnrD+FC//ZKH5/ERo96ghz8VqNlmL5RXo8Ks9rMr/Ad9xw
Y4hyRvAz5920myUffwdUqc0SvPlFnahsZg15uT5HkK48tHR0TLuLH8aRpzh4KJ/Y
p0sARNb+9i1R4Fg5zPNvHs2BbIve0vkwxAy+R4727qYzl3027w9jEFC6HMXRaDc=
-----END CERTIFICATE-----
---
Server certificate
subject=CN = *.kookapp.cn

issuer=C = US, O = "DigiCert, Inc.", CN = RapidSSL Global TLS RSA4096 SHA256 2022 CA1

---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 3993 bytes and written 392 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---

在这里面能看到如下内容

1
2
SSL handshake has read 3993 bytes and written 392 bytes
Verification: OK

也就是说,我们的本地主机是能成功认证kookapp.cn的ssl证书的,那么问题就出现在python的ssl模块中了!

2.3 检测python的ssl模块

python开启一个REPL,输入如下的两行代码

1
2
import ssl
ssl.create_default_context().cert_store_stats()

输出的内容如下

1
2
3
>>> import ssl
>>> ssl.create_default_context().cert_store_stats()
{'x509': 0, 'crl': 0, 'x509_ca': 0}

这里就能看出来问题了,全都是0!难怪说没有办法获取本地的CA证书。

作为对比,一台正常的windows11电脑输出如下,应该是有数值的。

1
2
3
>>> import ssl
>>> ssl.create_default_context().cert_store_stats()
{'x509': 87, 'crl': 0, 'x509_ca': 84}

2.4 解决错误

找到了错,那就得想办法解决!

python开启一个REPL,输入如下的两行代码

1
2
import ssl
ssl.get_default_verify_paths()

输出内容如下,这是本地python查找CA证书的位置

1
2
3
>>> import ssl
>>> ssl.get_default_verify_paths()
DefaultVerifyPaths(cafile=None, capath='/usr/local/openssl-1.1.1/ssl/certs', openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/usr/local/openssl-1.1.1/ssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/usr/local/openssl-1.1.1/ssl/certs')

如果是mac系统,输出如下

1
2
>>> ssl.get_default_verify_paths()
DefaultVerifyPaths(cafile=None, capath=None, openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/Library/Frameworks/Python.framework/Versions/3.10/etc/openssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/Library/Frameworks/Python.framework/Versions/3.10/etc/openssl/certs')

其中/usr/local/openssl-1.1.1/ssl/cert.pem中应该会保存CA的信息,使用ls查看本地的这个文件的内容

1
ls /usr/local/openssl-1.1.1/ssl/cert.pem

好家伙,发现文件压根不存在!

1
ls: cannot access '/usr/local/openssl-1.1.1/ssl/cert.pem': No such file or directory

看看openssl的版本和路径

1
openssl  version -d

输出如下

1
OPENSSLDIR: "/etc/pki/tls"

于是看看这个目录下有没有我们需要的cert.pem

1
2
$ ls /etc/pki/tls
cert.pem certs ct_log_list.cnf misc openssl.cnf private

有!那么接下来要做的,就是创建一个软连接,将其弄到/usr/local中!

1
ln -s /etc/pki/tls/cert.pem /usr/local/openssl-1.1.1/ssl/cert.pem

这样Python才能成功找到本地的CA证书。

3.完美!

做完这一切后,再次运行机器人,这次么有报错了!

1
2
3
4
5
$ py3 main.py
[FileManage] load all files
[BOT] Start at: [23-02-24 00:25:29]
[BOT.TASK] fetch_public_channel success

也成功响应了命令!

image-20230224092852118

MAC下更常见?

似乎这个问题在mac下更常见?由于没有使用过mac设备,本文不解释相关内容

image-20230224093050205