Let's encrypt的TLS-SNI安全问题

问题

这两天按以前的做法给一个新域名加Let’s encrypt证书,如下:

certbot run --nginx --email <your_email> -w /<path_to>/challenges -d <your.domain.name> --preferred-challenges tls-sni --renew-by-default --agree-tos

结果报了这么一个错误:

Client with the currently selected authenticator does not support any combination of challenges that will satisfy the CA.

放狗搜了一番,才知道原来是因为ACME的tls-sni验证被曝了一个安全问题:

2018.01.09 Issue with TLS-SNI-01 and Shared Hosting Infrastructure

所以这个方式不能用了。

原理说明

基本上就如上面那个官方说明所说,tls-sni验证的方式是:

  • 客户向let’s encrypt申请其域名的证书,let’s encrypt随机生成一个无效域名
  • certbot在客户服务器上创建一个此无效域名的自签名证书,并启动一个此域名的https服务
  • Let’s encrypt的服务器连接客户端的IP,并通过SNI申请验证此无效域名的证书
  • 如果验证通过,则认为这个客户身份有效
  • 给此客户签发其域名的有效证书

这里的漏洞在于,某些主机服务商存在多个用户共用一个IP的情况,如果有人知道某个域名指向的服务器与自己所在同一个IP,即可利用tls-sni的这个漏洞取得不属于自己域名的有效证书,即可用于类似中间攻击之类的恶意用途。

所以在没有找到解决方案之前,let’s encrypt关闭了tls-sni验证方式。

影响

对于大部分用户来说,影响不大,只要把验证方式从tls-sni改为http即可。

但是这就要求服务器可以同时提供80端口的访问,这对于某些只开放443端口的服务器就不方便了。

还有一个方法是用DNS验证,但这又需要域名注册商支持。

由于国内的ISP最近把443也关闭了,所以实际上http和tls-sni两个方法都已经行不通了,只剩下DNS方式可用……

谁叫你不幸生在中国——何作庥

最后附上DNS验证的方式:

certbot certonly --manual --email <your_email> -w /<path_to>/challenges -d <your.domain.name> --preferred-challenges dns --renew-by-default --agree-tos

会有两次提问,第一次选择Y确定有外网IP,第二次把提示的内容放到你的DNS TXT记录中,记录的子域名为:_acme-challenge.<your.domain.name>,设置好DNS后按回车继续即可完成证书更新。

不过这只是更新证书,还得手工重启一下Web server才能生效。

推送到[go4pro.org]