网站升级 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 仓库:

[[email protected]:~]# 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.

执行安装脚本

[[email protected]:~]# cd ./acme.sh/
[[email protected]:acme.sh]# crontab -l
no crontab for root
[[email protected]: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个操作:

安装过程中会自动为你创建 cronjob, 每天 0:00 点自动检测所有的证书, 如果快过期了, 需要更新, 则会自动更新证书(可执行 crontab -l 查看)。

[[email protected]:acme.sh]# crontab -l
27 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

安装后,必须关闭当前终端,然后重新打开以使别名生效。

之后可以准备颁发证书了

显示帮助信息:

[[email protected]:acme.sh]# acme.sh -h

申请签发 SSL 证书

acme.sh 实现了 acme 协议支持的所有验证协议. 一般有两种方式验证: http 和 dns 验证

本文不建议用 dns 方式申请, dns 手动模式,不能自动更新证书。在续订证书时,您必须手动向域中添加新的 txt 记录。

Nginx模式

由于网站运行的是 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

执行看到以下结果即成功

[[email protected]:~]# 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 文件

[[email protected]: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/ 文件夹中的证书文件,这些文件仅供内部使用,将来文件夹结构可能会更改。

[[email protected]:~]# 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 配置是否正确后重启

[[email protected]: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

手动验证

[[email protected]: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 的流程

[[email protected]: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; 
# 过期时间,分钟
Responses