网站升级 https 及优化,Nginx安装 SSL 证书篇
SSL 介绍
https 早已成为当今 web 主流,最近给自己的网站升级了 https。
Let’s Encrypt是一个非盈利性的证书颁发机构,为1.8亿个网站提供TLS证书。它是开源,并且完全免费的,它颁发的证书已经被几乎所有的浏览器所认可。
本文用到的脚本是 acmesh-official/acme.sh
准备
环境
操作环境:Ubuntu 18.04 x64
webserver:Nginx
域名
需要自己在服务商购买域名,本文不表
安装脚本 acmesh-official/acme.sh
在线安装
curl https://get.acme.sh | sh
官方推荐的方法,如果担心网站被运营商劫持,可以使用以下 git 方法
从 git 仓库安装
clone git 仓库:
[root@Ubuntu:~]# git clone https://github.com/acmesh-official/acme.sh.git
Cloning into 'acme.sh'...
remote: Enumerating objects: 49, done.
remote: Counting objects: 100% (49/49), done.
remote: Compressing objects: 100% (34/34), done.
remote: Total 10098 (delta 30), reused 30 (delta 15), pack-reused 10049
Receiving objects: 100% (10098/10098), 3.92 MiB | 18.41 MiB/s, done.
Resolving deltas: 100% (5951/5951), done.
执行安装脚本
[root@Ubuntu:~]# cd ./acme.sh/
[root@Ubuntu:acme.sh]# crontab -l
no crontab for root
[root@Ubuntu:acme.sh]# ./acme.sh --install
[Thu Feb 20 01:55:27 CST 2020] It is recommended to install socat first.
[Thu Feb 20 01:55:27 CST 2020] We use socat for standalone server if you use standalone mode.
[Thu Feb 20 01:55:27 CST 2020] If you don't use standalone mode, just ignore this warning.
[Thu Feb 20 01:55:27 CST 2020] Installing to /root/.acme.sh
[Thu Feb 20 01:55:27 CST 2020] Installed to /root/.acme.sh/acme.sh
[Thu Feb 20 01:55:27 CST 2020] Installing alias to '/root/.bashrc'
[Thu Feb 20 01:55:27 CST 2020] OK, Close and reopen your terminal to start using acme.sh
[Thu Feb 20 01:55:27 CST 2020] Installing cron job
no crontab for root
no crontab for root
[Thu Feb 20 01:55:27 CST 2020] Good, bash is found, so change the shebang to use bash as preferred.
[Thu Feb 20 01:55:28 CST 2020] OK
安装详情
执行此安装脚本不要求必须使用 root 用户,建议使用。
当前用户至少要有执行 nginx 权限
安装程序将执行3个操作:
- 创建和复制acme.sh到你的主目录($HOME)
~/.acme.sh/
所有证书也将放置在此文件夹中。 - 创建别名:
acme.sh=~/.acme.sh/acme.sh
. - 如果需要,创建每日Cron作业以检查并更新证书。
安装过程中会自动为你创建 cronjob, 每天 0:00 点自动检测所有的证书, 如果快过期了, 需要更新, 则会自动更新证书(可执行 crontab -l
查看)。
[root@Ubuntu:acme.sh]# crontab -l
27 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
安装后,必须关闭当前终端,然后重新打开以使别名生效。
之后可以准备颁发证书了
显示帮助信息:
[root@Ubuntu:acme.sh]# acme.sh -h
申请签发 SSL 证书
acme.sh 实现了 acme 协议支持的所有验证协议. 一般有两种方式验证: http 和 dns 验证
本文不建议用 dns 方式申请, dns 手动模式,不能自动更新证书。在续订证书时,您必须手动向域中添加新的 txt 记录。
由于网站运行的是 nginx 服务器,acme.sh 可以使用 nginx 服务器颁发证书。颁发证书后,acme.sh 会还原 nginx conf
,请放心。
官方提供以下命令
acme.sh --issue -d example.com --nginx
有时,无法自动找到nginx conf文件,您可以指定以下文件之一:
acme.sh --issue -d example.com --nginx /etc/nginx/nginx.conf
您还可以指定网站conf:
acme.sh --issue -d example.com --nginx /etc/nginx/conf.d/example.com.conf
执行看到以下结果即成功
[root@Ubuntu:~]# acme.sh --issue -d www.kangxuanpeng.com --nginx
[Thu Feb 20 01:59:28 CST 2020] Creating domain key
[Thu Feb 20 01:59:28 CST 2020] The domain key is here: /root/.acme.sh/www.kangxuanpeng.com/www.kangxuanpeng.com.key
[Thu Feb 20 01:59:28 CST 2020] Single domain='www.kangxuanpeng.com'
[Thu Feb 20 01:59:28 CST 2020] Getting domain auth token for each domain
[Thu Feb 20 01:59:29 CST 2020] Getting webroot for domain='www.kangxuanpeng.com'
[Thu Feb 20 01:59:29 CST 2020] Verifying: www.kangxuanpeng.com
[Thu Feb 20 01:59:29 CST 2020] Nginx mode for domain:www.kangxuanpeng.com
[Thu Feb 20 01:59:29 CST 2020] Found conf file: /etc/nginx/sites-enabled/www.kangxuanpeng.com.conf
[Thu Feb 20 01:59:29 CST 2020] Backup /etc/nginx/sites-enabled/www.kangxuanpeng.com.conf to /root/.acme.sh/www.kangxuanpeng.com/backup/www.kangxuanpeng.com.nginx.conf
[Thu Feb 20 01:59:29 CST 2020] Check the nginx conf before setting up.
[Thu Feb 20 01:59:29 CST 2020] OK, Set up nginx config file
[Thu Feb 20 01:59:29 CST 2020] nginx conf is done, let's check it again.
[Thu Feb 20 01:59:29 CST 2020] Reload nginx
[Thu Feb 20 01:59:34 CST 2020] Success
[Thu Feb 20 01:59:34 CST 2020] Restoring from /root/.acme.sh/www.kangxuanpeng.com/backup/www.kangxuanpeng.com.nginx.conf to /etc/nginx/sites-enabled/www.kangxuanpeng.com.conf
[Thu Feb 20 01:59:34 CST 2020] Reload nginx
[Thu Feb 20 01:59:34 CST 2020] Verify finished, start to sign.
[Thu Feb 20 01:59:34 CST 2020] Lets finalize the order, Le_OrderFinalize: https://acme-v02.api.letsencrypt.org/acme/finalize/78572851/2382115231
[Thu Feb 20 01:59:35 CST 2020] Download cert, Le_LinkCert: https://acme-v02.api.letsencrypt.org/acme/cert/03e350b1498cdf3776887b8ffebf902dc4b7
[Thu Feb 20 01:59:35 CST 2020] Cert success.
...
-----END CERTIFICATE-----
[Thu Feb 20 01:59:35 CST 2020] Your cert is in /root/.acme.sh/www.kangxuanpeng.com/www.kangxuanpeng.com.cer
[Thu Feb 20 01:59:35 CST 2020] Your cert key is in /root/.acme.sh/www.kangxuanpeng.com/www.kangxuanpeng.com.key
[Thu Feb 20 01:59:35 CST 2020] The intermediate CA cert is in /root/.acme.sh/www.kangxuanpeng.com/ca.cer
[Thu Feb 20 01:59:35 CST 2020] And the full chain certs is there: /root/.acme.sh/www.kangxuanpeng.com/fullchain.cer
生成 dhparam.pem
文件
[root@Ubuntu:sites-enabled]# openssl dhparam -out /root/.acme.sh/dhparam.pem 2048
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
...
ssl_dhparam 之后要 restart nginx,不能用nginx -s reload
将证书安装到 Nginx
官方不建议直接使用以上生成的证书 生成证书后,您可能希望将证书安装/复制到Apache / Nginx或其他服务器。您必须使用此命令将证书复制到目标文件,请勿使用 ~/.acme.sh/ 文件夹中的证书文件,这些文件仅供内部使用,将来文件夹结构可能会更改。
[root@Ubuntu:~]# acme.sh --install-cert -d www.kangxuanpeng.com \
> --keypath /etc/nginx/ssl-key-files/www.kangxuanpeng.com.key \
> --fullchainpath /etc/nginx/ssl-key-files/www.kangxuanpeng.com.key.pem \
> --reloadcmd "nginx -s reload"
[Thu Feb 20 02:30:33 CST 2020] Installing key to:/etc/nginx/ssl-key-files/www.kangxuanpeng.com.key
[Thu Feb 20 02:30:33 CST 2020] Installing full chain to:/etc/nginx/ssl-key-files/www.kangxuanpeng.com.key.pem
[Thu Feb 20 02:30:33 CST 2020] Run reload cmd: nginx -s reload
[Thu Feb 20 02:30:33 CST 2020] Reload success
命令格式为:
acme.sh --install-cert -d example.com \ --key-file /path/to/keyfile/in/nginx/key.pem \ --fullchain-file /path/to/fullchain/nginx/cert.pem \ --reloadcmd "nginx -s reload"
只有域名是必需的,所有其他参数都是可选的。
现有文件的所有权和许可信息将保留。您可以预先创建文件以定义所有权和权限。
将证书/密钥安装/复制到生产Apache或Nginx路径。
默认情况下,证书将每60天更新一次(可配置)。一旦证书被更新,在Apache / Nginx的服务将自动被重新装载命令:nginx -s reload
请注意:reloadcmd非常重要。该证书可以自动更新,但是如果没有正确的“ reloadcmd”,该证书可能无法刷新到您的服务器(例如nginx或apache),那么您的网站将无法在60天内显示更新的证书。
更改 Nginx 配置
启用 SSL,监听 443端口并且配置证书位置
http {
...
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
...
}
server {
listen 80;
listen 443 ssl;
server_name www.kangxuanpeng.com;
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
ssl_certificate_key /etc/nginx/ssl-key-files/www.kangxuanpeng.com.key;
ssl_certificate /etc/nginx/ssl-key-files/www.kangxuanpeng.com.key.pem;
# ssl_dhparam
ssl_dhparam /etc/nginx/ssl-key-files/dhparam.pem;
...
}
检查 Nginx 配置是否正确后重启
[root@Ubuntu:sites-enabled]# nginx -s reload //或者 service nginx restart
验证 SSL
访问 ssllabs.com 输入你的域名,检查 SSL 的配置是否都正常:
https://www.ssllabs.com/ssltest/analyze.html?d=www.kangxuanpeng.com&hideResults=on&latest
确保验证结果有 A 以上,否则根据提示调整问题
image.png
自动续期
Let's Encrypt 的证书有效期是 90 天的,你需要定期 renew
重新申请,这部分 acme.sh 以及帮你做了,在安装的时候往 crontab 增加了一行每天执行的命令 acme.sh --cron
:
27 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
手动验证
[root@Ubuntu:nginx]# "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh"
[Thu Feb 20 17:08:49 CST 2020] ===Starting cron===
[Thu Feb 20 17:08:49 CST 2020] Renew: 'blog.kangxuanpeng.com'
[Thu Feb 20 17:08:49 CST 2020] Skip, Next renewal time is: Sun Apr 19 18:00:48 UTC 2020
[Thu Feb 20 17:08:49 CST 2020] Add '--force' to force to renew.
[Thu Feb 20 17:08:49 CST 2020] Skipped blog.kangxuanpeng.com
[Thu Feb 20 17:08:49 CST 2020] Renew: 'kangxuanpeng.com'
[Thu Feb 20 17:08:49 CST 2020] Skip invalid cert for: kangxuanpeng.com
[Thu Feb 20 17:08:49 CST 2020] Skipped kangxuanpeng.com
[Thu Feb 20 17:08:49 CST 2020] Renew: 'me.kangxuanpeng.com'
[Thu Feb 20 17:08:49 CST 2020] Skip, Next renewal time is: Sun Apr 19 19:04:51 UTC 2020
[Thu Feb 20 17:08:49 CST 2020] Add '--force' to force to renew.
[Thu Feb 20 17:08:49 CST 2020] Skipped me.kangxuanpeng.com
[Thu Feb 20 17:08:49 CST 2020] Renew: 'www.kangxuanpeng.com'
[Thu Feb 20 17:08:49 CST 2020] Skip, Next renewal time is: Sun Apr 19 17:59:35 UTC 2020
[Thu Feb 20 17:08:49 CST 2020] Add '--force' to force to renew.
[Thu Feb 20 17:08:49 CST 2020] Skipped www.kangxuanpeng.com
[Thu Feb 20 17:08:49 CST 2020] ===End cron===
验证 acme.sh --cron
的流程
[root@Ubuntu:nginx]# acme.sh --cron -f
[Thu Feb 20 17:10:57 CST 2020] ===Starting cron===
[Thu Feb 20 17:10:57 CST 2020] Renew: 'blog.kangxuanpeng.com'
[Thu Feb 20 17:10:58 CST 2020] Single domain='blog.kangxuanpeng.com'
[Thu Feb 20 17:10:58 CST 2020] Getting domain auth token for each domain
[Thu Feb 20 17:10:59 CST 2020] Getting webroot for domain='blog.kangxuanpeng.com'
[Thu Feb 20 17:10:59 CST 2020] blog.kangxuanpeng.com is already verified, skip http-01.
[Thu Feb 20 17:10:59 CST 2020] Verify finished, start to sign.
[Thu Feb 20 17:10:59 CST 2020] Lets finalize the order, Le_OrderFinalize: https://acme-v02.api.letsencrypt.org/acme/finalize/78572851/2388621838
[Thu Feb 20 17:11:00 CST 2020] Download cert, Le_LinkCert: https://acme-v02.api.letsencrypt.org/acme/cert/0425b2165b01e91823130a37ee094b60fb66
...
[Thu Feb 20 17:11:06 CST 2020] Your cert is in /root/.acme.sh/www.kangxuanpeng.com/www.kangxuanpeng.com.cer
[Thu Feb 20 17:11:06 CST 2020] Your cert key is in /root/.acme.sh/www.kangxuanpeng.com/www.kangxuanpeng.com.key
[Thu Feb 20 17:11:06 CST 2020] The intermediate CA cert is in /root/.acme.sh/www.kangxuanpeng.com/ca.cer
[Thu Feb 20 17:11:06 CST 2020] And the full chain certs is there: /root/.acme.sh/www.kangxuanpeng.com/fullchain.cer
[Thu Feb 20 17:11:06 CST 2020] Installing key to:/etc/nginx/ssl-key-files/www.kangxuanpeng.com.key
[Thu Feb 20 17:11:06 CST 2020] Installing full chain to:/etc/nginx/ssl-key-files/www.kangxuanpeng.com.key.pem
[Thu Feb 20 17:11:06 CST 2020] Run reload cmd: nginx -s reload
[Thu Feb 20 17:11:06 CST 2020] Reload success
[Thu Feb 20 17:11:06 CST 2020] ===End cron===
至此配置 SSL 已完成
SSL 优化
chrome 证书缓存
如果配置不正确的时候用 chrome 打开网站,浏览器会缓存证书,证书配置正确后验证则需要清除浏览器证书缓存
chrome://net-internals
DNS CAA
添加一条 CAA 记录
CAA data 填写 0 issue "证书颁发机构域名"
。
用 Let's Encrypt 颁发的免费证书,CAA data
部分直接填写 0 issue "letsencrypt.org"
即可。
ssl 缓存
修改配置 nginx 增加缓存配置
ssl_session_cache shared:SSL:20m;
# SSL session 缓存区大小
# 这条语句加在server段里话,在SSL Lab的测试中识别不出来,因为它假设客户端不支持SNI协议,但实际上是可以加在server段的
ssl_session_tickets on;
# 开启浏览器的 Session Ticket 缓存
ssl_session_timeout 60m;
# 过期时间,分钟