当前位置: 首页 > 科技观察

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

时间:2023-03-13 14:34:40 科技观察

CA根证书过期导致的失败,真相原来是……服务器上应用服务发送的一些https请求失败,真相竟然是……问题10:00,同事反馈在线咨询哨兵服务器现在是否正常。之后查看哨兵服务,运行正常,但是应用服务连接的哨兵通道长时间没有事件。感觉不对,然后查看了sentryworker专用的容器,在worker服务中发现了一些错误日志:E,[2020-06-01T04:02:03.670850#6]ERROR--sentry:**[Raven]UnabletorecorderdeventwithremoteSentryserver(Raven::Error-SSL_connectreturned=1errno=0state=SSLv3readservercertificateB:certificateverifyfailed(certificatehasexpired)):/usr/local/bundle/gems/sentry-raven-2.7.3/lib/raven/transports/http.rb:34:在`rescueinsend_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(2levels)inprocess'/usr/local/bundle/gems/sidekiq-5.1.3/lib/sidekiq/middleware/chain.rb:128:我n`blockininvoke'/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`blockininvoke'/usr/local/bundle/gems/sidekiq-5.1.3/lib/sidekiq/middleware/chain.rb:133:in`invoke'E,[2020-06-01T04:02:03.671130#6]错误--sentry:**[Raven]Failedtosubmitevent:奇怪?sentry-worker连接哨兵服务器时,域名证书过期?分析根据上面的报错信息,我首先查看了相关调用的域名证书的有效期,发现都在有效期内,并且都是年初更换的。所以排除了域名证书的问题。然后根据错误日志,尝试在自己的电脑上使用curl命令。巧的是,我也遇到了类似的错误。$curlhttps://sentry.xxx.comcurl:(60)SSL证书问题:证书已过期更多详细信息在这里:https://curl.haxx.se/docs/sslcerts.htmlcurl无法验证服务器的合法性,因此无法建立安全连接。curl返回的结果是正常的。从web端和centos客户端的curl成功来看,好像是我本地电脑的curl和sentry-workerhost有问题。后来在网上找到了使用openssl命令排查ssl错误的方法:$openssls_client-showcerts-servernamesentry.xxx.com-connectsentry.xxx.com:443CONNECTED(00000003)depth=3C=SE,O=AddTrustAB,OU=AddTrustExternalTTPNetwork,CN=AddTrustExternalCARootverifyerror:num=10:certificatehasexpirednotAfter=May3010:48:382020GMT---证书链0s:/OU=DomainControlValidated/OU=GoGetSSLWildcardSSL/CN=*.xxx.comi:/C=LV/L=Riga/O=GoGetSSL/CN=GoGetSSLRSADVCA-----BEGINCERTIFICATE-----#...省略从上面命令返回的内容来看,这里的CA证书AddTrustExternalCARootexpiredatMay3010:48:382020格林威治标准时间。在网上查了相关资料,发现他们官方发布了一个公告: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时证书过期的原因。接下来看看如何解决:修改服务器ca配置更新ca库信息主机(Ubuntu)修改服务器CA配置修改服务器ca证书配置文件:/etc/ca-certificates.confsed-i”/AddTrust_External_Root。crt/d"/etc/ca-certificates.conf更新CA库使用update-ca-certificates命令更新目录/etc/ssl/certs保存SSL证书并生成ca-certificates.crt:$sudoupdate-ca-certificates--freshClearingsymlinksin/etc/ssl/certs...完成。正在更新/etc/ssl/certs中的证书...添加了147个,删除了0个;完毕。在/etc/ca-certificates/update.d中运行挂钩...完成。在主机上重新启动应用程序。Container(Docker-AlpineOS)容器与宿主机上的修改没有太大区别。修改ca配置文件,然后执行update命令。下面以alpine系统为例:修改配置文件:sed-i"/AddTrust_External_Root.crt/d"/etc/ca-certificates.conf更新ca证书链:update-ca-certificates-f-v当然,以上两个命令最好在Dockerfile中,要知道,在容器内部所做的任何更改都是不可靠的(除非挂载了共享或卷)。Dockerfile例子,CMD前加一行:omit...RUNsed-i"/AddTrust_External_Root.crt/d"/etc/ca-certificates.conf\&&update-ca-certificates-f-vMacOScurl在我自己的电脑上是一样的问题是目前还没有很好的办法自动修改。但是,找到了系统上ca文件的路径。先备份文件:sudocp/etc/ssl/cert.pem~/etc-ssl-cert.pem-20200601之后运行以下命令禁用过期的CA证书:sudosed-i"/^###AddTrust/,/^-.*END/s/^/#/g"/etc/ssl/cert.pem被注释掉了,当然你也可以直接编辑文件删除这几行。验证修改更新ca配置后,再次执行curl命令访问之前的网站:$curlhttps://sentry.xxx.com这次访问正常。其他问题当时出现问题的时候还有一个现象,就是用curl访问其他网站(比如bing.com,qq.com)是正常的。不知是不是目标域名使用的证书链不一样,导致只有我们的业务域名有问题?验证猜测,使用openssl查看我们企业域名证书的链:#openssls_client-connectsentry.xxx.com:443CONNECTED(00000003)depth=2C=US,ST=NewJersey,L=JerseyCity,O=TheUSETRUSTNetwork,CN=USERTrustRSACertificationAuthorityverifyreturn:1depth=1C=LV,L=Riga,O=GoGetSSL,CN=GoGetSSLRSADVCAverifyreturn:1depth=0OU=DomainControlValidated,OU=GoGetSSLWildcardSSL,CN=*.xxx.comverifyreturn:1---Certificatechain0s:/OU=DomainControlValidated/OU=GoGetSSLWildcardSSL/CN=*.xxx.comi:/C=LV/L=Riga/O=GoGetSSL/CN=GoGetSSLRSADVCA1s:/C=LV/L=Riga/O=GoGetSSL/CN=GoGetSSLRSADVCAi:/C=US/ST=NewJersey/L=JerseyCity/O=TheUSERTRUSTNetwork/CN=USERTrustRSACertificationAuthority2s:/C=US/ST=NewJersey/L=JerseyCity/O=TheUSERTRUSTNetwork/CN=USERTrustRSACertificationAuthorityi:/C=SE/O=AddTrustAB/OU=AddTrustExternalTTPNetwork/CN=AddTrustExternalCARoot---Servercertificate省略...上面提到的其他网站bing.com检测下:$openssls_client-connectcn.bing.com:443CONNECTED(00000003)depth=2C=IE,O=Baltimore,OU=Cyber??Trust,CN=BaltimoreCyber??TrustRootverifyreturn:1depth=1C=US,ST=Washington,L=Redmond,O=MicrosoftCorporation,OU=MicrosoftIT,CN=MicrosoftITTLSCA2verifyreturn:1depth=0CN=www.bing.comverifyreturn:1---Certificatechain0s:/CN=www.bing.comi:/C=US/ST=Washington/L=Redmond/O=MicrosoftCorporation/OU=MicrosoftIT/CN=MicrosoftITTLSCA21s:/C=US/ST=Washington/L=Redmond/O=MicrosoftCorporation/OU=MicrosoftIT/CN=MicrosoftITTLSCA2i:/C=IE/O=Baltimore/OU=Cyber??Trust/CN=BaltimoreCyber??TrustRoot---省略……我测试了其他几个大站点,发现都正常。为什么我们的SSL只有证书链中的其中一个CA(SectigoAddTrust)过期了呢?去找相关文章,关键字sectigogogetssl2020may30。我发现第三条记录有gogetssl发布的新闻,标题是:SectigoAddTrustExternalCARootExpiredMay30,2020,有兴趣的可以点击查看它。https://www.gogetssl.com/news/23.html消息大意:由于SectigoAddTrust的外部CA根证书到期,部分老设备或者部分老服务器受到影响,因为上面的root证书链仍然存在。过期的CA证书。对于客户端(浏览器/SDK),它们不受此CA过期问题的影响。所以最大的影响是在服务器端。您可以通过下载最新的AddTrustRSA证书来替换过期的证书。综上所述,目前这个问题的影响并不广泛。这个暂时还不得而知,但是根据我遇到的情况来看,大部分影响是服务端对外服务之间的调用。对于web客户端,因为更新了浏览器中的证书链,所以不涉及这个问题。但是对于服务端来说,对于一些对外调用的https请求,如果过期的CA参与到对方的域名证书链中,可能会导致访问失败。Tips1:如果你的应用是直接部署在宿主机上,可以使用配置管理工具(ansible/saltstack)统一修改。如果是容器部署的情况,可能涉及的会多一些,需要修改项目的Dockerfile,然后滚动更新服务(当然如果你的应用不涉及外部访问https/ssl调用,理论上可以延迟更改!)。Tips2:删除过期证书后,记得重启宿主机上运行的服务!!!