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 sslssl.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 sslssl.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 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
也成功响应了命令!
MAC 下更常见? 似乎这个问题在 mac 下更常见?由于没有使用过 mac 设备,本文不解释相关内容