配置 SSL/TLS 的一点记录

写在前面

使用 Let's Encrypt 来获取免费的证书以进行 Nginx 的 HTTPS 配置已经是一个很成熟的思路,所以我猜想自己的配置路也一定顺顺利利...然鹅事情总是没有这么简单,我还是碰到了一点小问题,就记录一下叭😘。

配置思路

我的服务器 OS 是 CentOS 7,官网说得清楚明了,有不懂可以再参考这篇博客的讲解,很详细。(所以摘抄在下面

安装相关工具

yum install -y certbot 
yum install -y python2-certbot-nginx

certbot 是 Let's Encrypt 提供的一个自动化生成证书工具,python2-certbot-nginx 则是为 certbot 提供自动操作 Nginx 配置文件的工具。

####获取证书

安装版 Nginx

若你的 Nginx 是通过 yum 或 rpm 包的方式安装,那么可以通过下面两种方式的命令来自动生成证书。执行过程中可能会遇到 urllib3 的异常,原因是 Python 模块版本不兼容,需要重装相应包,具体请参见这里

  1. 生成证书并自动修改 Nginx 配置。
certbot --nginx certbot --nginx rollback # 回滚配置
  1. 只生成证书,不修改 Nginx 配置。
certbot certonly --nginx
源码版 Nginx

若你使用的是无需安装的源码版,则可使用如下命令获取证书。

mkdir -p /var/www/example
certbot certonly --webroot -w /var/www/example -d example.com -d www.example.com

--webroot 模式会在 /var/www/example 中创建 .well-known 文件夹,这个文件夹里面包含了一些验证文件,certbot 会通过访问 example.com/.well-known/acme-challenge 来验证你的域名是否绑定的这个服务器。以确定你对该域名的拥有权。

--nginx 模式时,该验证会自动通过 Nginx 的服务来实现。

这种验证方式,Let机构叫做 ACME协议。只要遵循该协议,就可以获取Let结构签发的证书。除了官方的certbot工具外,也有很多遵循 ACME协议的第三方自动化工具,如 acme.sh

对我而言,因为想获取官方的通知(如证书过期提醒等),所以加上了 --email 参数,如下。

certbot certonly --email fdfengjunjie@126.com --webroot -w /data/charlesfeng/blog -d charlesfeng.cn

最后,配置下定时任务,将结果重定向至某个文件,以便日后 debug。

15 3 * * * /usr/bin/certbot renew > /data/letsencrypt.update.log 2>&1

配置 Nginx

因为我是源码版,所以得自己修改 Nginx 文件。Mozilla 提供了一个 SSL 配置文件的生成器,特别棒!然后配置其实也没啥特别的,主要就是在 CDN 域名 cdn.charlesfeng.cn 上踩了一下坑。🥶

CDN 的坑

因为我有两个域名嘛,一个是博客的 charlesfeng.cn,一个是阿里云 CDN 的加速域名 cdn.charlesfeng.top,CDN 加速域名之前是阿里云帮忙上的 HTTPS,所以我就先取消了,想着自己配。结果怎么都不成功...后来在 SSL Lab 测了下,结果如下图。

看到我划线的部分,才反应过来 CDN 域名是直接解析到阿里云的 CDN 节点(如上图的 47.246.23.105)上的,该节点上找不到回源时才会到我的服务器,所以还是得在阿里云 CDN 界面上配置 HTTPS,保证普通用户和阿里云 CDN 节点间是 HTTPS,而回源时采取的协议可参考相关文档,对我来说,因为申请了 cdn.charlesfeng.top 的证书,所以就直接全员上 HTTPS 了。(其实是 revoke 后又申请的🤐)

此外,上文说到 HSTS 有一个不足——「用户首次访问某网站是不受 HSTS 保护的」,这可以通过 Nginx 将 HTTP 请求转发到 HTTPS 上来弥补。具体来说,我在 conf.d/ 目录下新建了一个文件 forcehttp.conf,配置如下。

server {
	listen 80;
	server_name charlesfeng.cn cdn.charlesfeng.top;
	return 301 https://$host$request_uri;
}

SSL Lab 测试结果

最开始没有配 HSTS 和 OCSP,然后评分只得了 A,后来配上 HSTS 后,评分变为 A+🥳。OCSP 的简介如下,我感觉没有太大必要,就没配了。

OCSP 装订(英语:OCSP Stapling),正式名称为 TLS证书 状态查询扩展,可代替在线证书状态协议(OCSP)来查询 X.509 证书的状态。服务器在 TLS 握手时发送事先缓存的 OCSP 响应,用户只需验证该响应的有效性而不用再向数字证书认证机构(CA)发送请求。

虽然评级为 A+ 了,但是注意到这里有一句话「This site works only in browsers with SNI support」,且测试中收到了两个证书(理想情况应该为一个),第二个证书不是本域名的并标志「No SNI」。所以好奇着继续看看吧。

SNI 服务器名称指示(英语:Server Name Indication,缩写:SNI)是 TLS 的一个扩展协议,在该协议下,在握手过程开始时客户端告诉它正在连接的服务器要连接的主机名称。这允许服务器在相同的 IP 地址TCP 端口号 上呈现多个证书,并且因此允许在相同的 IP 地址上提供多个安全(HTTPS)网站(或其他任何基于 TLS 的服务),而不需要所有这些站点使用相同的证书。它与 HTTP/1.1 基于名称的虚拟主机的概念相同,但是用于 HTTPS。所需的主机名未加密,因此窃听者可以查看请求的网站。

这个问题在这里找到了答案,当不启用 SNI 进行 TLS 连接时,SSL Lab 收到了我的第二个证书,只有非常老旧的客户端才会碰到此情况,而当今所有现代浏览器都支持 SNI,所以如果你不是真的很关心在老旧浏览器(如 IE 6 / XP、IE 8 / XP、Java 6u45、Android 2.3.7)上的工作情况,可以忽略第二个证书。(别问,问就是 A+

参考