• 2017-10-11 更新: renew 错误
  • 2017-10-12 更新: 使用 –webroot 更新证书

去年我写了一个太监系列 HTTPS 小白知识(一) ,其中提到使用 Let’s Encrypt 来实现 HTTPS 支持。现在是时候了。

昨天我花了半小时把我的所有网站和博客全部加入了 HTTPS 支持。整个过程非常顺利,下面拣要点说一说。

根据 Let’s Encrypt 的文档,我们需要把情况分成 拥有服务器权限没有服务器权限 两种。 我的所有网站也正好包含这两种情况。Let’s Encrypt 建议使用 Certbot 这个工具来自动请求证书。

Certbot

在服务器上操作

Certbot 的使用很简单,选择了你的 web 服务器和操作系统版本后,网站会告诉你如何下载最新版本的 Certbot 。由于我使用的是 Ubuntu 12.04 ,就直接下载 Certbot 的运行脚本 certbot-auto:

1
2
wget https://dl.eff.org/certbot-auto
chmod a+x certbot-auto
你应该使用 sudo 或者 root 用户来运行 certbot-auto

针对常用的服务器,Certbot 有 不同的插件 可以使用。例如使用 Nginx 服务器,可以用 --nginx 插件,Apache 可以使用 --apache 插件。使用插件的好处是命令下载证书后会自动修改原始的服务器配置,都不用你动手。

我是用的服务器是 Nginx 的修改版 openresty ,而且在编译的时候自定义的安装文件夹,这种情况下 Certbot 是无法找到配置文件的。因此,我使用的是 –standalone 插件。

--standalone 会在服务器上启动一个临时的 HTTP 服务,绑定 80 或者 443 端口,以验证你拥有这个服务器的权限。在请求证书期间,这个临时服务将被访问。因此,你必须保证服务器上的 80 或者 443 端口是空闲的。我们可以指定使用的端口:

  • --preferred-challenges http 指定使用 80 端口
  • --preferred-challenges tls-sni 指定脚本使用 443 端口

因为我的服务器还没监听 443,所以,我请求的命令行是这样的:

1
sudo ./certbot-auto certonly --standalone --preferred-challenges tls-sni

需要注意的是,在更新证书的时候,由于 443 和 80 端口已经被使用了,就不能再使用 –standalone 插件来下载证书了。此时应该使用 –webroot 插件,详见 下文

剩下的工作,只需要根据提示输入邮箱、域名即可。可以一次输入多个域名(空格分隔),此时 Certbot 会将多个域名的证书保存到一个文件中,路径位于 /etc/letsencrypt/live/your domain/ ,公钥名称为 fullchain.pem ,私钥名称为 privkey.pem

接下来需要修改服务器配置,监听 443 端口,并将 80 端口的请求重定向到 https 服务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
server {
listen 80;
server_name zengrong.net www.zengrong.net;
return 301 https://zengrong.net$request_uri;
}
server {
listen 443 ssl;
ssl on;
server_name zengrong.net www.zengrong.net;
error_page 497 https://$host$request_uri;
ssl_certificate /etc/letsencrypt/live/zengrong.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/zengrong.net/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
keepalive_timeout 70;
}

建议参考 Nginx 官方文档中的 Configuring HTTPS servers 对服务器进行优化。

没有服务器权限

我的博客 blog.zengrong.net 在进行了静态化之后,直接部署到了 又拍云 上。又拍云可以提供免费的 Let’s Encrypt 支持,但我还是准备申请证书。

这种情况需要使用 Certbot 的 –manual 插件,在本机安装 certbot 并执行:

遗憾的是,Certbot 目前不支持 Windows 系统。
1
2
$ brew install certbot
$ sudo certbot certonly --manual

在运行过程中,Certbot 会生成一个key,并要求你将这个 key 保存成文件,上传到你申请的网站目录 /.well-known/acme-challenge/ 中。在上传完毕后,Certbot 会访问这个文件,以验证你对网站的控制权。验证成功后,证书就会被下载到本机,路径和上面提到的一致。

接着只需要把证书在又拍云的后台进行配置即可给 CDN 开启 HTTPS 支持了。

证书更新

使用 renew 更新

Let’s Encrypt 的证书有效期为三个月,在证书到期时间还剩一个月的时候,你会收到要求更新证书的提醒邮件。

根据文档 ,更新证书相当简单。但我在更新上文中通过 certonly 申请的证书时,却碰到下面的错误:

1
2
3
4
5
6
7
8
9
10
11
$ sudo certbot --debug renew --dry-run
Saving debug log to /var/log/letsencrypt/letsencrypt.log
-------------------------------------------------------------------------------
Processing /etc/letsencrypt/renewal/blog.zengrong.net.conf
-------------------------------------------------------------------------------
Cert is due for renewal, auto-renewing...
Could not choose appropriate plugin: The manual plugin is not working; there may be problems with your existing configuration.
The error was: PluginError('An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.',)
Attempting to renew cert (blog.zengrong.net) from /etc/letsencrypt/renewal/blog.zengrong.net.conf produced an unexpected error: The manual plugin is not working; there may be problems with your existing configuration.
The error was: PluginError('An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.',). Skipping.

出现这个错误的原因是在非交互模式下, Certbot 并不知道如何确认网站是你的。我们可以自己写一个 hook 解决鉴权问题,在这个 hook 中上传鉴权文件到 web 服务器。详见: Pre and Post Validation Hooks

使用 standalone 更新

如果不愿意自己写 hook ,80 或者 443 端口有一个空余,那么可以使用 --standalone 来更新,同时使用 –preferred-challenges 来指定使用的端口。默认使用 80 端口。

1
sudo certbot certonly --debug --force-renew -a standalone -d blog.zengrong.net

使用 webroot 更新

如果 443 和 80 端口都被占用了, 我们当然不应该为了更新安全证书而停止网站服务。此时可以使用 --webroot 插件来更新证书。

zengrong.net 的证书更新为例,使用 -w 参数指定网站根目录地址,使用 -d 参数来指定域名,多个域名也没问题。

1
% certbot certonly --webroot -w /srv/www/zengrong.net -d zengrong.net -d www.zengrong.net

在上面的操作中,certbot 会自动生成鉴权文件,保存在网站根目录下,并发起一个 http 访问以确认域名的所有者是你。 注意这里默认使用的是 http 访问。所以如果你的网站仅监控了 https 请求的话,需要做一下 配置 ,或者使用 –preferred-challenges tls-sni 指定脚本使用 443 端口。

使用 manual 更新

如果没有服务器控制权,就只能使用 --manual 来更新了。Certbot 会询问你问题并将指导你上传一个文本文件到服务器目录中以证明网站是你的。参见 [没有服务器权限][noprvi] 。

1
certbot certonly --debug --force-renew -a manual -d blog.zengrong.net

您与此网站之间建立的连接并非完全安全

启用了 HTTPS 之后,可能会碰到这样的情况:

您与此网站之间建立的连接并非完全安全

这是因为该页面中可能包含非 HTTPS 内容,例如显示了一个位于 HTTP 网站上的图像,或者引用了一个 HTTP 网站上的 JS。对于 HTTPS 网站来说,其中嵌入的所有内容都必须是 HTTPS 的。

打开 Chrome 的开发者工具,可以在 console 中看到这样的 warning:

Mixed Content: The page at ‘https://blog.zengrong.net/spritesheeteditor/‘ was loaded over HTTPS, but requested an insecure image ‘http://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png‘. This content should also be served over HTTPS.

我们需要仔细查看网站中包含的图像、Javascript、CSS 等,确保其处于 HTTPS 域。如果把这些问题都解决了,那么网站的显示应该是这样的:

安全连接

检测网站安全性

使用 SSL Labs 提供 的 SSL Server Test 工具来检测自己网站的安全性,进入下面的链接,输入自己的网址即可:

https://www.ssllabs.com/ssltest/analyze.html

全文完

留言