如何解决“SSL证书问题:证书链中的自签名证书”错误?

22

我有一个基于Linux的Docker容器,在其中如果我执行:

curl https://google.com

...然后我会收到一个错误:

curl: (60) SSL证书问题: 证书链中有自签名的证书。更多详情请参见:https://curl.haxx.se/docs/sslcerts.html

任何URL都会出现相同的问题,这不是谷歌的问题。

上面提到的链接提供了各种解决方案,除了最后一个解决方案之外,似乎都不太适用,该解决方案建议更新证书存储。 但是没有说明如何执行此操作(或者至少对我来说没有可理解的说明)。

那么,这样做正确吗?如果正确,怎么做?


更新:如请求所示,下面是结果:

openssl s_client -showcerts -connect www.google.com:443

CONNECTED(00000003)
depth=3 DC = com, DC = forestroot, CN = SHA256RootCA
verify error:num=19:self signed certificate in certificate chain
---
Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google LLC/CN=www.google.com
   i:/CN=ssl-decrypt
-----BEGIN CERTIFICATE-----
MIIDXzCCAkegAwIBAgIIXIk3p8xOX/kwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UE
AxMLc3NsLWRlY3J5cHQwHhcNMTgxMjE5MDgxNzAwWhcNMTkwMzEzMDgxNzAwWjBo
...
tq0VAGIoj4+YhO6bktTq3alCRoLstJuuxjVdb1wRkH4YRi0I6ZAB1Cw+M8Lg+2eQ
KuEo
-----END CERTIFICATE-----
 1 s:/CN=ssl-decrypt
   i:/DC=com/DC=bgs/CN=SHA256IssueCA
-----BEGIN CERTIFICATE-----
MIIGzDCCBLSgAwIBAgITEQAADvB9T7mSaacwDQABAAAO8DANBgkqhkiG9w0BAQsF
ADBCMRMwEQYKCZImiZPyLGQBGRYDY29tMRMwEQYKCZImiZPyLGQBGRYDYmdzMRYw
...
1z9f/nkj2XTRyGeACoy0qRd5uXJHp1iGM27l3RFDR9OjrfPV56pOBUYWAlc9Nn+1
Vr3qUZrcCkROrmYisVF4jg==
-----END CERTIFICATE-----
 2 s:/DC=com/DC=MyCompanyServer/CN=SHA256IssueCA
   i:/DC=com/DC=MyCompanyServer/CN=SHA256RootCA
-----BEGIN CERTIFICATE-----
MIIH4zCCBcugAwIBAgITOQAAAAOa4wv9nnK0uQAAAAAAAzANBgkqhkiG9w0BAQsF
ADBIMRMwEQYKCZImiZPyLGQBGRYDY29tMRowGAYKCZImiZPyLGQBGRYKZm9yZXN0
...
IomErcbcymIWBmN75PVMsk9EMyqDP394jG8+IOK+lVUVX4pxzhdd7eYbqTAwDE1X
bNWcZZkt/w==
-----END CERTIFICATE-----
 3 s:/DC=com/DC=MyCompanyServer/CN=SHA256RootCA
   i:/DC=com/DC=MyCompanyServer/CN=SHA256RootCA
-----BEGIN CERTIFICATE-----
MIIFgzCCA2ugAwIBAgIQULxmYXGJ1aFIlIyCHA4NIzANBgkqhkiG9w0BAQsFADBI
MRMwEQYKCZImiZPyLGQBGRYDY29tMRowGAYKCZImiZPyLGQBGRYKZm9yZXN0cm9v
...
jQBLY0/KIjHywv66GhtVWpexgQcXrLxQP2VHW7eXpsylvwkNU5XNQYzHTB7u+w5C
VunfRLt/7mVWyURcwkOre38tVSByKR4=
-----END CERTIFICATE-----
---
Server certificate
subject=/C=US/ST=California/L=Mountain View/O=Google LLC/CN=www.google.com
issuer=/CN=ssl-decrypt
---
No client certificate CA names sent
Peer signing digest: SHA256
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 6556 bytes and written 302 bytes
Verification error: self signed certificate in certificate chain
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID: 723D9976F985887CA5F256EE3C2E7B44B9C98A6B440AAF4E19564AE101F78D00
    Session-ID-ctx:
    Master-Key: C3D8759A753C1D269FF9C00854E59B8C10ABC1E94AFE9F0166486A649FE295ACE1AF5E5BEDB0129E557E781BC860D2FA
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1548690163
    Timeout   : 7200 (sec)
    Verify return code: 19 (self signed certificate in certificate chain)
    Extended master secret: yes
---
read:errno=0

我的理解是,这条链中有一张证书属于我工作的公司(我将其重命名为MyCompanyServer),我想这就是问题所在。

我是否正确地认为我需要安装某种针对该证书的密钥?对于新手问题,抱歉,这都是希腊文。


1
请显示 openssl s_client -showcerts -connect www.google.com:443 的输出。可能是某些人(攻击者)“窃取”了您的 TLS 连接并使用自己签名的证书。谁提供您的互联网连接?在 Docker 守护程序配置中是否配置了任何代理,或者在容器级别定义了任何代理环境变量? - Jan Garaj
@JanGaraj:我已经添加了输出。我知道我在某种防火墙后面,但没有详细信息。看起来确实有一个证书链是本地的,属于我工作的公司。我不了解足够回答你的最后两个问题 :-( - Gary McGill
我有这个问题,到现在还没有解决。 - Ahmed Elsayed
所以,在我的情况下,问题出在该该死的杀毒软件上。我使用的是卡巴斯基全球安全软件,它正在检查通过我的Docker实例传输的流量。我在暂时禁用我的杀毒软件后成功了,并添加了一个永久性的例外。所以,@JanGaraj所说的有道理! - jefferson.macedo
4个回答

32

可能您在容器中没有正确的 CA 证书,因此无法验证 TLS 连接。

尝试安装 ca-certificates 包(包的名称可能不同,这取决于使用的发行版)。


更新:

您的公司检查企业网络中的 TLS 连接,因此原始证书被替换为公司证书。 您需要将公司 CA 证书添加到根 CA 证书中。

Linux(Ubuntu、Debian):

  • 将公司 CA 证书复制到目录/usr/local/share/ca-certificates/
  • 运行sudo update-ca-certificates

如果您的主机操作系统已经正确预配置了 CA 证书(包括公司 CA 证书),那么您只需将它们作为卷挂载到容器中即可:

docker run \
  -v /etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt \
  ...

典型的 CA 证书位置:

  • /etc/ssl/certs/ca-certificates.crt Debian / Ubuntu / Gentoo 等。
  • /etc/pki/tls/certs/ca-bundle.crt Fedora / RHEL 6
  • /etc/ssl/ca-bundle.pem OpenSUSE
  • /etc/pki/tls/cacert.pem OpenELEC
  • /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem CentOS / RHEL 7

如果我执行 apt-get install ca-certificates,它会报告已经安装并且是最新的。但是它们在哪里以及 curl 是否能够找到它们,我无法确定。 - Gary McGill
非常好 - 謝謝你。但是,令人煩惱的是,我似乎沒有 sudo :-( - Gary McGill
将公司 CA 证书包含到 Docker 镜像中。 - Jan Garaj
1
暂时禁用反病毒软件(卡巴斯基)解决了我的问题。 - Sebastian Sulinski
我正在从 Windows 机器中获取我的企业证书。请确保将您的 base64 文件从 cer 重命名为 crt,否则 update-ca-certificates 将无法工作,在我的情况下,容器中某些工具无法使用 SSL。 - Vale Trujillo
显示剩余2条评论

0
好的,我刚刚添加了这条语句,现在它可以正常工作。
CURLOPT_SSL_VERIFYPEER => 0,

6
刚刚添加到哪里了? - Ilya Kolesnikov
是的,你把它添加到哪里了?是一个环境变量吗? - Brandon
我将这个修改过的版本作为一行代码放在了我的cURL中,代码如下:curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);。这样做虽然无法验证页面身份,但至少可以避免自签名证书的SSL错误。 - Steve
1
那么你的意思是禁用检查是解决方案吗? 此选项确定curl是否验证对等证书的真实性。值为1表示curl进行验证;0(零)表示不进行验证。 [...] Curl验证证书是否真实,即您可以信任服务器是证书所说的那样。 - StackedUser

0
我使用这段代码发送cUrl请求,但是它没有起作用并抛出了以下错误:
SSL证书问题:证书链中有自签名证书 php curl
curl_setopt($ch, CURLOPT_URL, "https://test.example.com/v1/authenticate.json?api_key=123456");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_FAILONERROR, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch,CURLOPT_CAINFO,'cert.embedapp.20191004.pem');
curl_setopt($ch,CURLOPT_CAPATH,'./cert.embedapp.20191004.pem');

尝试了各种方法后,我将我的cUrl请求更改为:

curl_setopt($ch, CURLOPT_URL, "https://test.example.com/v1/authenticate.json?api_key=123456");
       curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,0);    
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,0);
curl_setopt($ch, CURLOPT_FAILONERROR, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);    
curl_setopt($ch, CURLOPT_SSLCERT,'cert.embedapp.20191004.pem');

终于对我可用了 :)


-1

如果您只想让curl工作而不检查证书,请将以下内容添加到您的Dockerfile中:

ENV CURLOPT_SSL_VERIFYHOST=0
ENV CURLOPT_SSL_VERIFYPEER=0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接