未备案域名绕过腾讯云 HTTP 劫持申请 SSL 证书

2020-03-21

咋回事儿?#

前阵子在腾讯云☁️上部署一些小服务,一切正常,域名可以正常访问。过了几天再访问,就忽然变成了这样:

🏄‍♀️在互联网上冲浪一番,得知最近国内域名管理越来越严格,像阿里云、腾讯云这样的服务器供应商,已经针对自己的服务器做了 HTTP 拦截。如果检测到你的域名是未备案的,并且流量指向它们服务器的 80 端口,便会跳转到类似http://dnspod.qcloud.com/static/webblock.html?d=example.com 的网址,提醒你备案。

但是.. 自己部署在国内的服务器并不会运行什么大型服务,可能随时会有变更;而且域名是在国外供应商购买的,备案非常麻烦。真的让人头疼。而国外的服务器 IP 经常被墙,访问速度也相对较慢,不适合部署一些服务性的网页。

不过,在 V2EX 上看到有人指出,这种拦截只针对 HTTP 协议。因为 HTTP 协议是没有加密的,所以供应商可以轻易地获取请求的所有信息。而 HTTPS 是加密的,因此可以绕过拦截(参考:传输层安全协议SSL/TLS协议运行机制的概述)。另外,直接访问 IP 也是不会被拦截的。

于是,决定为自己的域名申请一个证书,走 HTTPS 协议。嗯,申请 SSL 证书,一切都是这么自然。

Let’s Encrypt#

Let’s Encrypt 是一个免费并且广泛信任的证书签发机构,于是,成为大部分人的首选。只需要根据官方的指引,我们轻松地来到了 Certbot 的网页。

Certbot#

image-20200321173107802

在你选择对应的服务以及所部属的环境之后,Certbot 会自动给出合适的操作指引:

image-20200321173251891

嗯,一切都是这么自然,但是你身处中国大陆。在增加 PPA 那一步,巨慢无比,即便是打开全局代理。只能选择手动下载 Certbot。好在 Git 是可以走代理的,于是:

git clone https://github.com/certbot/certbot.git
cd certbot
./certbot-auto --help all

只需要用 ./certbot-auto 代替指引中出现的 certbot 命令即可。

生成证书#

image-20200321173745150

因为我的服务随时可以停止,自然就选择第一种方式生成证书,只需要根据提示输入域名等信息。嗯,一切都是这么自然,但是你身处中国大陆…

IMPORTANT NOTES:
 - The following errors were reported by the server:

   Domain: example.com
   Type:   unauthorized
   Detail: Invalid response from
   https://dnspod.qcloud.com/static/webblock.html?d=example.com
   [212.64.120.232]: "<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<meta
   charset=\"utf-8\" />\n\t\t<meta http-equiv=\"X-UA-Compatible\"
   content=\"IE=edge,chrome=1\" />\n\t\t<"

   To fix these errors, please make sure that your domain name was
   entered correctly and the DNS A/AAAA record(s) for that domain
   contain(s) the right IP address.

嗯,因为 --standalone 模式会在服务器的 80 端口上部署一个临时的服务来证明域名所属权,然而这个端口是被拦截了的。我尝试过更改子域名、重置服务器 IP 等操作,均无济于事(因为初期的一段时间是没有被拦截的,所以抱有侥幸心理..)。

更换模式#

🏄在互联网上继续冲浪一番之后,发现 Certbot 还提供手动验证的模式,只需要添加 DNS 的 TXT 解析即可。于是我们运行 ./certbot-auto --manual --preferred-challenges dns certonly,便会有以下提示:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.example.com with the following value:

N6CQk5z84uK5albd3sCBa9qEBoROUitLQl84eB686KA

Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

此时 Certbot 便会暂停,等待我们去添加 DNS 解析。

添加 DNS 解析#

我们只需要根据指引,添加我们所申请域名的子域名(_acme-challenge.example.com)的 TXT 解析即可,解析内容就是 Console 中给出的随机字符串:N6CQk5z84uK5albd3sCBa9qEBoROUitLQl84eB686KA.

验证成功#

在等待 DNS 生效后继续执行程序,便可以生成证书:

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/example.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/example.com/privkey.pem
   Your cert will expire on 2020-06-19. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot-auto
   again. To non-interactively renew *all* of your certificates, run
   "certbot-auto renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

之后只需要在对应的后端配置证书即可。