Nginx配置SSL

安装CertBot

首先,克隆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 ~/.bashrcsource ~/.bash_profile,这样就可以直接使用certbot命令进行接下来的操作了。
当然,你也可以使用包管理工具安装certbot。以yum为例:

1
2
3
yum -y install yum-utils
yum-config-manager --enable rhui-REGION-rhel-server-extras rhui-REGION-rhel-server-optional
yum install certbot

其它系统的安装方式可以在Certbot官网上查询。
不过经博主测试,这种安装方式可能会产生错误,因此不建议使用。
安装完成后,可以使用

1
sudo certbot -h

查看安装是否成功。如果报错,也可以尝试使用pip install certbot
如果你使用了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 yourdomain.com,www.yourdomain.com

/path/to/your/webroot替换为nginx的根目录,yourdomain.com替换为你的域名,多个域名用逗号隔开。
如果要申请泛域名证书,将上面的命令改为:

1
sudo certbot certonly --server https://acme-v02.api.letsencrypt.org/directory --manual --preferred-challenges dns -d yourdomain.com,*.yourdomain.com

泛域名证书还需要验证TXT记录,比较麻烦。可以参考这篇文章:Let’s Encrypt现已正式支持泛域名证书
如果一切顺利,会输出以下内容:

1
2
3
4
5
6
7
8
9
10
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/yourdomain.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
11
server {
listen 80;
listen [::]:80; #监听ipv6,如果没有必要可以删去
#如果硬性要求全部走https协议,注释上两行
listen 443 ssl;
listen [::]:443 ssl; #监听ipv6,如果没有必要可以删去
server_name yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/yourdomain.com/chain.pem;
#其余内容省略,无需更改

同理,将yourdomain.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/yourdomain.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/yourdomain.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的条件为:

  • 有效的证书(如果使用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+ssl配置http和https共存
手把手教你在Nginx上使用CertBot

本文更新于2018年7月28日:
在较新版本中,ssl on不再被使用,否则会报错:[warn] the “ssl” directive is deprecated, use the “listen … ssl” directive instead;将推荐的CertBot安装方式由包管理工具改为Git项目。

🍭支持一根棒棒糖!
0%