Nginx 配置 SSL
安装 CertBot
CertBot 是用来申请 SSL 证书的。其安装方式可以在 Certbot 官网上查询。
你可以选择以下几种不同的方法。
通过 GitHub 仓库
首先,克隆 Certbot 在 GitHub 上的仓库到本地:
1 | git clone https://github.com/certbot/certbot.git |
在 certbot 文件夹下,有一个 shell 脚本,名为 certbot-auto。你可以将其软链接为 certbot,方便进行接下来的步骤。具体操作是,在你的家目录 ~
下的.bashrc
或.bash_profile
文件中追加以下内容:
1 | alias certbot=/path/to/your/certbot/certbot-auto |
然后执行 source ~/.bashrc
或 source ~/.bash_profile
,这样就可以直接使用 certbot 命令进行接下来的操作了。
通过包管理工具
当然,你也可以使用包管理工具安装 CertBot。以 yum 为例:
1 | yum -y install yum-utils |
其它系统的安装方式同样可以在官网上找到。
不过经笔者测试,这种安装方式可能会产生错误,因此不建议使用。
通过 pip
直接执行 pip install certbot
即可。
其它
安装完成后,可以使用
1 | sudo certbot -h |
查看安装是否成功。如果报错,也可以尝试使用其它安装方式。
如果你使用了 Nginx 服务器,还可以执行
1 | yum install certbot-nginx |
安装 Certbot 的 Nginx 拓展。
配置 CertBot
执行
1 | sudo certbot --nginx |
即可自动完成配置。不过由于涉及到修改 nginx.conf,建议手动进行配置:
1 | sudo certbot certonly --webroot -w /path/to/your/webroot -d example.com,www.example.com |
将 /path/to/your/webroot
替换为 nginx 的根目录,example.com
替换为你的域名,多个域名用逗号隔开。
如果要申请泛域名证书,将上面的命令改为:
1 | sudo certbot certonly --server https://acme-v02.api.letsencrypt.org/directory --manual --preferred-challenges dns -d example.com,*.example.com |
泛域名证书还需要验证 TXT 记录,比较麻烦。可以参考这篇文章:Let's Encrypt 现已正式支持泛域名证书。
如果一切顺利,会输出以下内容:
1 | IMPORTANT NOTES: |
生成的证书将会存放在 /etc/letsencrypt/live/
目录下。
配置 Nginx
接下来配置 nginx.conf:
1 | server { |
同理,将 example.com
替换为你的域名。如果还要支持 HTTP/2,请确保编译 Nginx 时设置了参数 --with-http_v2_module
,然后在这个配置文件中,将 listen 443 ssl;
改为 listen 443 ssl http2;
,ipv6 同理。
更改完成后,执行 nginx -s reload
重新加载配置,这时就可以使用 https 访问了。
更新证书
先在命令行模拟证书更新:
1 | sudo certbot renew --dry-run |
模拟更新成功的效果如下:
1 | ------------------------------------------------------------------------------- |
如果模拟成功,就可以使用
1 | sudo certbot renew >> /var/log/le-renew.log |
手动进行更新(注:证书只有在有效期小于一个月的时候才会更新,否则 CertBot 会提示无需更新)。
当然,你也可以通过 Crontab 来启用定时任务,自动更新证书。在命令行执行:
1 | sudo crontab -e |
在打开的文件中添加配置:
1 | 30 2 * * 1 /path/to/your/certbot renew >> /var/log/le-renew.log |
这里建议使用 certbot 或 certbot-auto 的绝对地址,避免出现问题。这样,在每周一半夜 2 点 30 分就会执行 renew 任务,自动更新证书。
如果一切 OK,那么我们的配置到此结束!
关于 HSTS
如果你能够确保在未来足够长的时间内保持证书的有效性,则可以配置 HSTS。HSTS 是 HTTP Strict Transport Security 的缩写,它可以阻止基于 SSLStrip 的中间人攻击,这将增加访问的安全性。在 http 头中做出如下设置即可开启 HSTS:
1 | Strict-Transport-Security: max-age=expireTime [; includeSubDomains] [; preload] |
其中 expireTime
是过期时间,一旦用户通过 https 访问你开启了 HSTS 的站点,那么在 expireTime
之内再次访问,浏览器将强制启用 https—— 这样可以防止发送不安全的流量。但是,如果你的证书此时过期了,那么用户将无法访问你的网站,因为 http 访问会被浏览器禁止。
更进一步,你可以把自己的网站提交到 HSTS preload list 中。这是 Chrome 浏览器中的 HSTS 预载入列表,在该列表中的网站,使用 Chrome 浏览器访问时,会自动转换成 HTTPS。Firefox、Safari、Edge 浏览器也在采用这个列表。
加入 HSTS preload list 的条件为:
- 有效的证书(如果使用 SHA-1 证书,必须是 2016 年前就会过期的)
- 将所有 HTTP 流量重定向到 HTTPS
- 确保所有子域名启用 HTTPS,特别是 www 子域名
同时输出的 HSTS 响应头部需要满足以下条件:
- max-age 至少为一年,31536000 秒
- 必须指定 includeSubdomains 参数
- 必须支持 preload 参数
所以,一个典型满足 HSTS preload list 的响应头部为:
1 | Strict-Transport-Security: max-age=31536000; includeSubDomains; preload; |
通过配置 Nginx,利用 add_header
加上这个响应头,然后就可以在 HSTS preload list 的官方网站上进行申请了。从申请到审核通过,时间在几天到几周不等。申请后,你可以随时查询最新的状态,也可以在 Chrome 浏览器的地址框中输入 chrome://net-internals/#hsts
查看。从审核通过到正式加入到 Chrome 的 stable release 版本中还需要一段时间,因为还要经过 canary、dev、beta 以及 stable progression 等步骤。
参考文章:
NGINX Docs | NGINX SSL Termination
手把手教你在 Nginx 上使用 CertBot
本文更新于 2018 年 7 月 28 日:
在较新版本中,ssl on
不再被使用,否则会报错:[warn] the "ssl" directive is deprecated, use the "listen ... ssl" directive instead;将推荐的 CertBot 安装方式由包管理工具改为 Git 项目。