Let’s Encrypt OCSP 域名被封

目录


引子

一直以来,我都是使用 Caddy 来部署自己的一些网站,这是一个用 golang 写的 web 服务端,类似 nginx,但一个显著的优势是默认支持 HTTPS,且无需额外配置。

下文摘抄自维基百科

Caddy 默认通过检查域名来启用 HTTPS (通过 ACME protocol 检查域名并签发证书), 并且重定向 HTTP 请求到 HTTPS。它在启动期间根据需要签发证书,并在服务器的使用期间自动重签发。 Let’s Encrypt 是默认的证书颁发机构,……。在 2016 年第一季度,有百分之二的 Let’s Encrypt 证书是由 Caddy 签发的

可见,Caddy 和 Let’s Encrypt 的关系甚是紧密。

其实我的博客本质上就是一个静态网站,使不使用 HTTPS 原本区别不大。但是当我看到自己的网站上出现了不是自己挂载的广告内容时,我才对“运营商劫持”这件事有了更清醒的认识,于是带着愤怒,借助 Caddy 实现了全站 HTTPS,在它的保驾护航下,一直运转至今。

前几天,我在做一些维护工作时,发现 Caddy 一直启动不起来,一直卡在 Activating privacy features... 这一步,在重试了几次之后,我发现了规律,不是启动不起来,而是启动耗时很长,等上几分钟后还是能正常启动的,这时候查看日志,可以看到多条类似这样的日志:

[WARNING] Stapling OCSP: no OCSP stapling for [blog.wolfogre.com]: making OCSP request: Post "http://ocsp.int-x3.letsencrypt.org": dial tcp 69.63.176.15:80: i/o timeout

原来 Caddy 会在正式工作之前,为每个域名向 http://ocsp.int-x3.letsencrypt.org 发起校验请求,然而每次都会连接失败,且超时时间目测是 30 秒。因为是串行执行,这就需要你等上 N 个 30 秒了。不过好在,即使校验失败,Caddy 也不会放弃运行,所以在等待足够久之后,还是可以正常工作的。

我满腹狐疑,尝试在服务器上 curlping 这个 ocsp.int-x3.letsencrypt.org 地址,发现确实是连不通的。因为日常运行时,Caddy 也会不定时向这个地址发起请求,所以我搜索了一下日志,发现大约是从 4 月 1 日 10 时开始,这样的错误日志大量出现,一直至今。

2020/04/01 09:50:56 [ERROR] Checking OCSP: no OCSP stapling for [image.wolfogre.com]: making OCSP request: Post http://ocsp.int-x3.letsencrypt.org: dial tcp 64.13.192.74:80: connect: connection refused
2020/04/01 09:51:26 [ERROR] Checking OCSP: no OCSP stapling for [blog.wolfogre.com]: making OCSP request: Post http://ocsp.int-x3.letsencrypt.org: dial tcp 66.220.147.11:80: i/o timeout
2020/04/01 10:51:25 [ERROR] Checking OCSP: no OCSP stapling for [image.wolfogre.com]: making OCSP request: Post http://ocsp.int-x3.letsencrypt.org: dial tcp 31.13.64.1:80: i/o timeout
2020/04/01 10:51:55 [ERROR] Checking OCSP: no OCSP stapling for [blog.wolfogre.com]: making OCSP request: Post http://ocsp.int-x3.letsencrypt.org: dial tcp 174.37.54.20:80: i/o timeout
2020/04/01 11:51:25 [ERROR] Checking OCSP: no OCSP stapling for [blog.wolfogre.com]: making OCSP request: Post http://ocsp.int-x3.letsencrypt.org: dial tcp 88.191.253.157:80: i/o timeout
2020/04/01 11:51:55 [ERROR] Checking OCSP: no OCSP stapling for [image.wolfogre.com]: making OCSP request: Post http://ocsp.int-x3.letsencrypt.org: dial tcp 31.13.74.17:80: i/o timeout
2020/04/01 12:51:25 [ERROR] Checking OCSP: no OCSP stapling for [image.wolfogre.com]: making OCSP request: Post http://ocsp.int-x3.letsencrypt.org: dial tcp 31.13.75.18:80: i/o timeout
2020/04/01 12:51:55 [ERROR] Checking OCSP: no OCSP stapling for [blog.wolfogre.com]: making OCSP request: Post http://ocsp.int-x3.letsencrypt.org: dial tcp 31.13.75.17:80: i/o timeout
……

“4 月 1 日 10 时开始”?这个时间点未免也太巧合了,让我嗅出了一丝人为的味道……

深究

我尝试在在网上搜索了一下,已经有人发现了这个问题,核心点就是 ocsp.int-x3.letsencrypt.org 无法访问,利用 Let’s Encrypt 签发证书可能受阻。

我倒吸了一口凉气,如果不能使用 Let’s Encrypt 签发 HTTPS 证书,像我这样不舍得掏钱买付费证书的人,难不成就得回到 HTTP 时代,任由网络运营商的劫持广告肆虐?

帖子中,大家开始了各种关于这件事的阴谋论揣测,其中的一些分析也不乏一些道理,但是我还是很难相信会有这样强硬且无理的举措,让 Let’s Encrypt 在中国境内一夜猝死?

我重新梳理了一遍 Let’s Encrypt 的工作逻辑,稍稍放了点心,结论是:ocsp.int-x3.letsencrypt.org 域名被封,其实并不会对使用 Let’s Encrypt 有较大影响,仍然是可以继续签发、更新的。

根据 Let’s Encrypt 对其工作原理的介绍,我们可以看到,签发证书时,主机确实需要连接至 Let’s Encrypt,发起一次证书签名请求(CSR)

image

但需要注意的是,这个过程并不需要 ocsp.int-x3.letsencrypt.org 这个域名参与,换句话说,即使这个域名被封,也不影响上述签发证书的过程。我已经实操验证过了,签发、更新证书确实是可以正常进行的。

被影响到的其实是证书被吊销过程:

image

当想吊销证书时,主机会发起一个吊销请求,Let’s Encrypt 将吊销信息发布到正常的吊销通道(即 OCSP)中,以便浏览器等依赖方知道他们不应该接受这个已被吊销的证书。而 ocsp.int-x3.letsencrypt.org 这个域名,正是为浏览器等依赖方提供查询证书吊销状态的服务,即 OCSP Server。

所以这样看来,Caddy 启动时向 OCSP Server 发起请求,目的就是检查机器上缓存的证书是否已经被吊销,而如果请求受阻,无法确认证书吊销状态,Caddy 是默认证书有效的,所以仍可以继续工作。换句话说,屏蔽 ocsp.int-x3.letsencrypt.org 并非会让 Let’s Encrypt 完全无法使用,但这一手段大大削弱了其安全性。可以想象,当证书泄露时,即使已经成功吊销了被泄露的证书,但因为浏览器无法访问 OCSP Server,也就无法确认证书状态,导致可能继续信任被泄露的证书,访问到恶意站点。

多损啊。

结论

话说回来,当浏览器无法确定一个证书是否已经被吊销,这个时候浏览器是信任这个证书,还是不信任这个证书呢?

在文章《你不在意的 HTTPS 证书吊销机制》里,作者详细展开了在吊销证书这件事情上会面临的种种难题,其中“OCSP Server 无法访问”这一情况,本身就是这套证书吊销机制的核心痛点,所以各家厂商的浏览器在对待 OCSP 这一机制时,明显是偏保守的,鲜有说“无法请求 OCSP Server 进行校验就认定证书不安全”,这样过分依赖 OCSP Server 可用性的做法。

其中更有甚者,早早就弃用了 OCSP,认为它效率低、速度慢,并一针见血地提到:“攻击者既然能拦截 HTTPS 请求,就同样能阻断 OCSP 请求,从而规避这一检查机制。”——我相信你已经猜到了,这家浏览器就是 Google Chrome,见《Google Chrome Will No Longer Check for Revoked SSL Certificates Online》。

到这里,我可以说,我可以暂时放心了,除了每次重启 Caddy 时需要等上一会儿,也没什么其他影响。

但是,然而,but,however,以上结论都需要加一个时间限定词,就是“到目前为止”。

这次故障过于诡异,我很难说他到底是一个“缺陷”,还是一个“特性”,如果是“缺陷”自然会有人将其修复,如果是“特性”自然又人会进一步加强这方面的“特性”。

我实在想不通,这样做的意义是什么,是为了释放一个信号?让我意识到在国内使用 Let’s Encrypt 是有风险的,进而转向付费证书,或其他没有被封风险的免费证书?

我不敢妄言。

我无 fuck 说。

后记

5 月 1 日,刚好一个月后,错误日志戛然而止:

2020/05/01 14:13:20 [WARNING] Stapling OCSP: no OCSP stapling for [blog.wolfogre.com]: making OCSP request: Post "http://ocsp.int-x3.letsencrypt.org": dial tcp 69.171.233.24:80: i/o timeout
2020/05/01 14:13:50 [WARNING] Stapling OCSP: no OCSP stapling for [image.wolfogre.com]: making OCSP request: Post "http://ocsp.int-x3.letsencrypt.org": dial tcp 69.171.233.24:80: i/o timeout
2020/05/01 15:01:13 [WARNING] Stapling OCSP: no OCSP stapling for [blog.wolfogre.com]: making OCSP request: Post "http://ocsp.int-x3.letsencrypt.org": dial tcp 69.63.180.173:80: i/o timeout
2020/05/01 15:01:43 [WARNING] Stapling OCSP: no OCSP stapling for [image.wolfogre.com]: making OCSP request: Post "http://ocsp.int-x3.letsencrypt.org": dial tcp 69.63.180.173:80: i/o timeout
2020/05/01 16:06:50 [INFO][cache:0xc000081b30] Scanning for stale OCSP staples
2020/05/01 16:06:50 [INFO][cache:0xc000081b30] Done checking OCSP staples
2020/05/01 17:06:50 [INFO][cache:0xc000081b30] Scanning for stale OCSP staples
2020/05/01 17:06:50 [INFO][cache:0xc000081b30] Done checking OCSP staples
2020/05/01 18:06:50 [INFO][cache:0xc000081b30] Scanning for stale OCSP staples

现在 ping ocsp.int-x3.letsencrypt.org 已经没有问题了:

$ ping ocsp.int-x3.letsencrypt.org
PING ocsp.int-x3.letsencrypt.org (96.17.68.81) 56(84) bytes of data.
64 bytes from ocsp.int-x3.letsencrypt.org (96.17.68.81): icmp_seq=1 ttl=48 time=234 ms
64 bytes from ocsp.int-x3.letsencrypt.org (96.17.68.81): icmp_seq=2 ttl=48 time=234 ms
64 bytes from ocsp.int-x3.letsencrypt.org (96.17.68.81): icmp_seq=3 ttl=48 time=234 ms
64 bytes from ocsp.int-x3.letsencrypt.org (96.17.68.81): icmp_seq=4 ttl=48 time=235 ms
^C
--- ocsp.int-x3.letsencrypt.org ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 234.277/234.852/235.396/0.713 ms

$ curl -v ocsp.int-x3.letsencrypt.org
* About to connect() to ocsp.int-x3.letsencrypt.org port 80 (#0)
*   Trying 96.17.68.81...
* Connected to ocsp.int-x3.letsencrypt.org (96.17.68.81) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: ocsp.int-x3.letsencrypt.org
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx
< Content-Length: 0
< Cache-Control: max-age=5425
< Expires: Sat, 09 May 2020 09:38:02 GMT
< Date: Sat, 09 May 2020 08:07:37 GMT
< Connection: keep-alive
<
* Connection #0 to host ocsp.int-x3.letsencrypt.org left intact

此前所有的阴谋论貌似都被打脸了。

不管怎样,无论是意外事故还是人为引起,但愿不要再发生了。

评论加载中……

若长时间无法加载,请刷新页面重试,或直接访问