首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

一个因 CA 根证书过期引起的故障,真相竟然是…

服务器上的应用服务对外发送的一些 https 请求都失败了,真相竟然是……

问题

10点左右,同事反馈咨询线上的Sentry 服务器现在是否正常。之后去检查 Sentry 服务,运行正常,但是该应用服务对接的Sentry频道已经很久没有事件进来了。

感觉不太对劲,再去检查下 Sentry worker专用的容器,发现该Worker服务中中有些错误日志:

代码语言:javascript
复制
E,?[2020-06-01T04:02:03.670850?#6]?ERROR?--?sentry:?**?[Raven]?Unable?to?record?event?with?remote?Sentry?server?(Raven::Error?-?SSL_connect?returned=1?errno=0?state=SSLv3?read?server?certificate?B:?certificate?verify?failed?(certificate?has?expired)):??/usr/local/bundle/gems/sentry-raven-2.7.3/lib/raven/transports/http.rb:34:in?`rescue?in?send_event'??/usr/local/bundle/gems/sentry-raven-2.7.3/lib/raven/transports/http.rb:16:in?`send_event'??/usr/local/bundle/gems/sentry-raven-2.7.3/lib/raven/client.rb:37:in?`send_event'??/usr/local/bundle/gems/sentry-raven-2.7.3/lib/raven/instance.rb:81:in?`send_event'??/app/src/worker.rb:26:in?`perform'??/usr/local/bundle/gems/sidekiq-5.1.3/lib/sidekiq/processor.rb:187:in?`execute_job'??/usr/local/bundle/gems/sidekiq-5.1.3/lib/sidekiq/processor.rb:169:in?`block?(2?levels)?in?process'??/usr/local/bundle/gems/sidekiq-5.1.3/lib/sidekiq/middleware/chain.rb:128:in?`block?in?invoke'??/usr/local/bundle/gems/sentry-raven-2.7.3/lib/raven/integrations/sidekiq.rb:9:in?`call'??/usr/local/bundle/gems/sidekiq-5.1.3/lib/sidekiq/middleware/chain.rb:130:in?`block?in?invoke'??/usr/local/bundle/gems/sidekiq-5.1.3/lib/sidekiq/middleware/chain.rb:133:in?`invoke'??E,?[2020-06-01T04:02:03.671130?#6]?ERROR?--?sentry:?**?[Raven]?Failed?to?submit?event:?<no?message?value>?

奇怪?sentry-worker 在连sentry server 时请求域名的证书过期了?

分析

针对上面的错误信息,先去检查了相关调用的域名证书的有效期,发现都在有效期内。而且印象中都是年初刚更换的。所以排除了是域名证书问题。

然后根据错误日志,尝试在自己电脑上用下curl 命令,巧合的很,也遇到了类似的错误。

代码语言:javascript
复制
$?curl?https://sentry.xxx.com??curl:?(60)?SSL?certificate?problem:?certificate?has?expired??More?details?here:?https://curl.haxx.se/docs/sslcerts.html??curl?failed?to?verify?the?legitimacy?of?the?server?and?therefore?could?not??establish?a?Secure?connection?to?it.?To?learn?more?about?this?situation?and??how?to?fix?it,?please?visit?the?web?page?mentioned?above.?

我又去找了其它一台 Centos 主机,发现 curl 返回的结果是正常的,从 web 端和centos 客户端 curl 都成功的看,像是我本机电脑的 curl 和sentry-worker主机出了问题。

之后用到网上找到使用openssl命令排查ssl错误的方法:

代码语言:javascript
复制
$?openssl?s_client?-showcerts?-servername?sentry.xxx.com?-connect?sentry.xxx.com:443??CONNECTED(00000003)??depth=3?C?=?SE,?O?=?AddTrust?AB,?OU?=?AddTrust?External?TTP?Network,?CN?=?AddTrust?External?CA?Root??verify?error:num=10:certificate?has?expired??notAfter=May?30?10:48:38?2020?GMT??---??Certificate?chain??0?s:/OU=Domain?Control?Validated/OU=GoGetSSL?Wildcard?SSL/CN=*.xxx.com??i:/C=LV/L=Riga/O=GoGetSSL/CN=GoGetSSL?RSA?DV?CA??-----BEGIN?CERTIFICATE-----??#...省略?

从上面执行命令返回的内容来看,这里的 CA 证书 AddTrust External CA Root 在 May 30 10:48:38 2020 GMT 这个时间过期了。

上网查了下相关的资料,发现他们官方发过一篇通告:Sectigo-AddTrust-External-CA-Root-Expiring-May-30-2020.

https://support.sectigo.com/articles/Knowledge/Sectigo-AddTrust-External-CA-Root-Expiring-May-30-2020

解决方案

现在算是找到为什么请求 https 会出现证书过期的原因了。接下来看下如何解决:

  1. 修改服务器ca配置
  2. 更新ca库信息

主机(Ubuntu)

修改服务器 CA 配置

修改服务器 ca 证书配置文件:/etc/ca-certificates.conf

代码语言:javascript
复制
sed?-i?"/AddTrust_External_Root.crt/d"?/etc/ca-certificates.conf?

更新 CA 库

使用update-ca-certificates该命令用以更新目录/etc/ssl/certs来保存SSL证书,并生成 ca-certificates.crt:

代码语言:javascript
复制
$?sudo?update-ca-certificates?--fresh??Clearing?symlinks?in?/etc/ssl/certs...??done.??Updating?certificates?in?/etc/ssl/certs...??147?added,?0?removed;?done.??Running?hooks?in?/etc/ca-certificates/update.d...??done.?

重启主机上的应用程序。

容器(Docker-Alpine OS)

容器同主机上的修改差不太多。修改ca配置文件,之后执行更新命令。以下以alpine系统为例:

修改配置文件:

代码语言:javascript
复制
sed?-i?"/AddTrust_External_Root.crt/d"?/etc/ca-certificates.conf?

更新 ca 证书链:

代码语言:javascript
复制
update-ca-certificates?-f?-v?

当然上面的两条命令最好是放在 Dockerfile 中,你知道,在容器里做的任何修改都是不可靠的(除非挂载了共享或卷)。

Dockerfile 示例,在 CMD 之前添加一行:

省略...

代码语言:javascript
复制
RUN?sed?-i?"/AddTrust_External_Root.crt/d"?/etc/ca-certificates.conf?\??&&?update-ca-certificates?-f?-v??MacOS?

我自己电脑上的curl也是同样的问题,目前没找到好的自动修改的方式。不过找到了系统上的 ca 文件路径。

先备份下文件:

代码语言:javascript
复制
sudo?cp?/etc/ssl/cert.pem?~/etc-ssl-cert.pem-20200601?

之后,运行以下命令可以禁用掉过期的 CA 证书:

代码语言:javascript
复制
sudo?sed?-i?"/^###?AddTrust/,/^-.*END/?s/^/#/g"?/etc/ssl/cert.pem?

上面是注释掉,当然你也可以直接编辑文件删除这些行。

验证

修改更新完 ca 配置后,再次执行curl 命令去访问之前的网站:

代码语言:javascript
复制
$?curl?https://sentry.xxx.com?

这次访问正常了。

其他问题

当时出现问题时,还有另外一个现象,就是用 curl 访问其他网站(如,bing.com、qq.com)都是正常的。怀疑是不是目标域名使用的证书链不一样, 导致了只有我们业务域名出现了问题呢?

验证下猜想

使用 openssl 检查下我们业务域名证书的链:

代码语言:javascript
复制
#?openssl?s_client?-connect?sentry.xxx.com:443??CONNECTED(00000003)??depth=2?C?=?US,?ST?=?New?Jersey,?L?=?Jersey?City,?O?=?The?USERTRUST?Network,?CN?=?USERTrust?RSA?Certification?Authority??verify?return:1??depth=1?C?=?LV,?L?=?Riga,?O?=?GoGetSSL,?CN?=?GoGetSSL?RSA?DV?CA??verify?return:1??depth=0?OU?=?Domain?Control?Validated,?OU?=?GoGetSSL?Wildcard?SSL,?CN?=?*.xxx.com??verify?return:1??---??Certificate?chain??0?s:/OU=Domain?Control?Validated/OU=GoGetSSL?Wildcard?SSL/CN=*.xxx.com??i:/C=LV/L=Riga/O=GoGetSSL/CN=GoGetSSL?RSA?DV?CA??1?s:/C=LV/L=Riga/O=GoGetSSL/CN=GoGetSSL?RSA?DV?CA??i:/C=US/ST=New?Jersey/L=Jersey?City/O=The?USERTRUST?Network/CN=USERTrust?RSA?Certification?Authority??2?s:/C=US/ST=New?Jersey/L=Jersey?City/O=The?USERTRUST?Network/CN=USERTrust?RSA?Certification?Authority??i:/C=SE/O=AddTrust?AB/OU=AddTrust?External?TTP?Network/CN=AddTrust?External?CA?Root??---??Server?certificate??省略...?

在检测下上面说的其他网站 bing.com:

代码语言:javascript
复制
$?openssl?s_client?-connect?cn.bing.com:443??CONNECTED(00000003)??depth=2?C?=?IE,?O?=?Baltimore,?OU?=?CyberTrust,?CN?=?Baltimore?CyberTrust?Root??verify?return:1??depth=1?C?=?US,?ST?=?Washington,?L?=?Redmond,?O?=?Microsoft?Corporation,?OU?=?Microsoft?IT,?CN?=?Microsoft?IT?TLS?CA?2??verify?return:1??depth=0?CN?=?www.bing.com??verify?return:1??---??Certificate?chain??0?s:/CN=www.bing.com??i:/C=US/ST=Washington/L=Redmond/O=Microsoft?Corporation/OU=Microsoft?IT/CN=Microsoft?IT?TLS?CA?2??1?s:/C=US/ST=Washington/L=Redmond/O=Microsoft?Corporation/OU=Microsoft?IT/CN=Microsoft?IT?TLS?CA?2??i:/C=IE/O=Baltimore/OU=CyberTrust/CN=Baltimore?CyberTrust?Root??---??省略...?

我又测试了其他几个大的站点,发现都正常。为什么唯独我们的SSL证书链中的其中一个 CA(Sectigo AddTrust)过期了呢?

去查找下相关的文章,关键词 sectigo gogetssl 2020 may 30.

发现第三条记录中有gogetssl发布的新闻,标题是:Sectigo AddTrust External CA Root Expired May 30, 2020,感兴趣的可以点击进去看看。

https://www.gogetssl.com/news/23.html

新闻大致的意思:

由于Sectigo AddTrust外部CA根证书过期,影响了一些旧的设备或者一些老服务器,因为上面的根证书链中还存在该过期的 CA 证书。对于客户端(浏览器/SDK)来说,他们是不受该 CA 过期的问题影响。所以最大影响是在server端. 可以通过下载最新的 AddTrust RSA 证书替换过期的。

总结

目前该问题的影响面广不广,这个还暂时未知,不过根据我遇到的情况来看,影响大多在服务器端的外部服务之间的调用。对web用户端来说,因为浏览器内证书链是更新的,不涉及该问题。但对于服务端来说,对于一些对外调用的 https 请求,如果对方域名证书链中涉及到该过期CA的话,可能会访问失败。

Tips1:如果你的应用程序的部署方式是直接运行在主机上的话,可以使用配置管理工具(ansible/saltstack),统一修改。如果是容器话部署的情况,可能涉及的稍微多一些,需要修改项目的 Dockerfile,之后滚动更新该服务(当然如果你的应用不涉及到对外访问 https/ssl 调用,理论上可以延后更改!)。

Tips2:删除过期证书后,记得要重启主机上运行的服务!!!

  • 发表于:
  • 原文链接http://news.51cto.com/art/202006/619093.htm
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券
http://www.vxiaotou.com