PPPan's 平凡之路

非宁静无以致远

做一个互联网内容的贡献者。


全站 HTTPS 边做边记

没错,这是一篇可以 Step by Step 跟着做的操作指南。

keyword: Let's Encrypt, Ubuntu 14.04, Nginx

前言

关于 HTTPS 可以先看看鹅厂的这篇文章涨涨姿势。

我们知道 HTTPS 需要一个 CA 来解决信息抵赖和中间人攻击的隐患。Let's Encrypt 就是一个 CA。它的优势在于免费、被绝大多数浏览器认可、高度自动化。这么好的一个 CA 摆在这里,还多说什么呢,开搞。

环境

  • 操作系统: Ubuntu 14.04
  • 代理服务器: Nginx
  • 权限: 拥有 Shell 权限

申请证书

我们采用官方推荐的自动化工具 Certbot来进行全自动化的申请。

首先下载 Certbot, 并修改相关权限.

$ wget https://dl.eff.org/certbot-auto
chmod a+x certbot-auto  

下载完成后,先关闭 Nginx 服务。因为我们将采用独立模式来安装证书。在独立模式下,certbot-auto 需要占用 80 端口,因此我们需要先暂时关闭 Nginx 来释放 80 端口。

service nginx stop  

运行 certbot-auto 命令申请证书

$ ./path/to/certbot-auto certonly --standalone -d example.com -d www.example.com

-d 后面的参数是你需要用 HTTPS 访问的域名。这里不支持通配符,所以子域名比较多的同学得费力都填满了。

运行过程中,会弹出窗口让你填写邮箱。Let's Encrypt 的证书的有效期是 90 天。在证书过期后,他们会往这个邮箱发送提醒。

填完邮箱并接收用户协议后,就会进入如下界面。这说明开始申请并下载证书了。

稍等片刻,如果出现以下提示,则表示证书申请成功了。

IMPORTANT NOTES:  
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/shengpan.net/fullchain.pem. Your cert will
   expire on 2017-01-05. 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

你可以在上述信息中找到证书存放的位置:

/etc/letsencrypt/live/shengpan.net/fullchain.pem

这在后面的 Nginx 配置中会用到。

配置 Nginx

找到 Nginx 的配置文件,添加 ssl 配置。以我的 Ghost 博客为例:

server {  
    listen 443 ssl;
    server_name shengpan.net; 

    ssl_certificate /etc/letsencrypt/live/shengpan.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/shengpan.net/privkey.pem;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers AES256+EECDH:AES256+EDH:!aNULL;

    location / {
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   Host      $http_host;
        proxy_pass         http://127.0.0.1:2368;
   }
}

server_name 改为你的域名,ssl_certificatessl_certificate_key 分别改为你的公私钥路径。

兼容 HTTP

有可能你的网站在启用 HTTPS 之前已经在某些地方留下过 HTTP 的链接了,而你又不希望这些链接失效,就需要做一些兼容。

如果你希望全站都使用 HTTPS 访问,只需要把 HTTP 请求重定向到 HTTPS 上即可。在 Nginx 配置文件中添加如下配置:

server {  
    listen 80;
    server_name shengpan.net; 
    return 301 https://$server_name$request_uri;
}

如果你希望用户可以同时使用 HTTPS 和 HTTP 访问,只需要在配置文件中简单地添加一行:

listen 443 ssl;  
listen 80; # 添加这一行即可  
server_name shengpan.net;  

最后我们重启一下 Nginx 服务

service nginx start  

在浏览器中输入你的域名看看吧!

自动续期

Let's Encrypt 颁发的证书只有 90 天的有效期,过了有效期需要续期。幸运的是 Cerbot 已经帮我们打理好了这一切,只需要一句命令行就可以为你的证书续期。

To non-interactively renew all of your certificates, run "certbot-auto renew"

当然,这句命令行还可以交给计划任务去做,以自动续期。Linux 下我们使用 Cron 实现这一功能。

启动 cron 服务

通常 ubuntu 下自带 cron,如果没有也可以通过以下命令进行安装:

$ apt-get install cron

若已经安装,输入以下命令判断 cron 服务是否启动:

$ pgrep cron

如果有 pid (一串数字)输出则说明 cron 服务已经启动,没有任何输出说明需要手动启动 cron 服务。 启动 cron 服务:

$ service cron start

编写需要运行的脚本

首先新建一个脚本文件,为了方便识别,我们命名为 refetch-https-cer.sh,并保存到 /etc/cron.weekly/ 路径下。如果没有该路径则最新建。

refetch-https-cer.sh 中填入如下内容

#!/bin/bash
/usr/bin/service nginx stop
/root/certbot-auto renew
/usr/bin/service nginx start

#!/bin/bash 开头说明该文件是一个 shell 脚本。 下面就是需要执行的命令。这里我们只要三步就能完成 https 证书的更新:

  1. 关闭占用80端口的 nginx 服务(因为我们用 standalone 模式来使用 cerbot-auto)
  2. 用 certbot 来为证书续期
  3. 重启 HTTP 代理服务器,来使新的 https 证书生效。

需要注意的是,文件里需要写全命令路径,因为 cron 执行的时候,可能没有 PATH 的环境变量。我的 certbot 命令放在 root 文件夹下,因此是 /root/certbot-auto renew,你需要将其替换为你的 certbot 命令路径。

最后我们需要修改一下改脚本文件的权限。

$ chmod 777 /etc/cron.quarterly/refetch-https-cer.sh

编写配置文件

cron 是以载入配置文件的方式来运行计划任务的。因此,只需要编写好配置文件并将其提交到 cron 服务中,它就会按照配置定期运行相关任务。

我们新建一个配置文件,命名为 rootcron , 保存到 /var/spool/cron/。该路径是所有用户 cron 文件存放的目录。

编辑 rootcron 文件,添加如下内容:

# refetch https certificate per week
# minute hour day month week command
0 3 * * 2 /etc/cron.weekly/refetch-https-cer.sh >> /root/for_crontab/error.log  

这个配置文件的意思就是,在每周二的凌晨 3 点,执行我们先前编写的用来自动续期的脚本,并将错误日志输出到 /root/for_crontab/error.log 文件中。

你可以自定义log文件的路径,但要保证在编写这个配置文件之前,已经把 log 文件创建好了。这样你可以偶尔上来看看日志文件,确保计划任务正常运行。

你也可以根据自己证书的过期时间,自定义任务的计划时间。想要知道如何自定义自己的配置文件,请看这里

最后,我们将该配置文件提交到 cron 服务中

$ crontab /var/spool/cron/rootcron

检查一下是否已经成功将计划任务提交了

$ crontab -l

如果出现下面的提示,则说明已经成功提交了。自此,cron 会帮你打理好证书续期的事。

$ crontab -l
# refetch https certificate per week
# minute hour day month week command
0 3 * * 2 /etc/cron.weekly/refetch-https-cer.sh >> /root/for_crontab/error.log  

Have fun :)

参考资料