Nginx 配置 SSL
安装 Certbot
Certbot 是用来申请 SSL 证书的。Certbot 的安装方式有几种,具体可以在 Certbot 官网上查询。
笔者尝试了通过 pip
进行安装,直接执行 pip install certbot
即可安装好 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
2
3
4
5
6
7
8
9
10IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/example.com/fullchain.pem. Your cert
will expire on 20XX-XX-XX. To obtain a new or tweaked version of
this certificate in the future, simply run certbot again. To
non-interactively renew *all* of your certificates, run "certbot
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/
目录下。
配置 Nginx
接下来配置 nginx.conf:1
2
3
4
5
6
7
8
9
10
11server {
listen 80;
listen [::]:80; #监听ipv6,若无必要可以删去
#如果硬性要求全部走https协议,注释上两行
listen 443 ssl;
listen [::]:443 ssl; #监听ipv6,若无必要可以删去
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
#其余内容省略,无需更改
这里同样将 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
2
3
4
5
6
7
8
9
10-------------------------------------------------------------------------------
Processing /etc/letsencrypt/renewal/example.com.conf
-------------------------------------------------------------------------------
** DRY RUN: simulating 'certbot renew' close to cert expiry
** (The test certificates below have not been saved.)
Congratulations, all renewals succeeded. The following certs have been renewed:
/etc/letsencrypt/live/example.com/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
** (The test certificates above have not been saved.)
这时就可以使用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 的条件为:
- 有效的 SSL 证书
- 将所有 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 项目。