使用 acme.sh 配置 let's encrypt 证书笔记

安装 acme.sh

1
$ curl  https://get.acme.sh | sh

cloudxns 添加 CAA 记录及申请接口

1
hehe.fnzoo.com. CAA 0 issue letencrypt.org

根据 dns 服务商修改相应接口验证信息(例:Cloudxns.com)

1
2
3
4
$ vi /root/.acme.sh/dnsapi/dns_cx.sh

CX_Key="f4054cae35ab6a925dd1026c9be8aa82"
CX_Secret="aae7150d6ff3b654"

生成 ECC 证书

1
2
3
4
5
6
7
$ "/root/.acme.sh"/acme.sh --issue --dns dns_cx -d hehe.fnzoo.com -k ec-256

# 成功后输出
[Mon Dec 4 14:36:38 CST 2017] Your cert is in /root/.acme.sh/hehe.fnzoo.com_ecc/hehe.fnzoo.com.cer
[Mon Dec 4 14:36:38 CST 2017] Your cert key is in /root/.acme.sh/hehe.fnzoo.com_ecc/hehe.fnzoo.com.key
[Mon Dec 4 14:36:39 CST 2017] The intermediate CA cert is in /root/.acme.sh/hehe.fnzoo.com_ecc/ca.cer
[Mon Dec 4 14:36:39 CST 2017] And the full chain certs is there: /root/.acme.sh/hehe.fnzoo.com_ecc/fullchain.cer

安装证书

1
2
3
4
5
$ /root/.acme.sh/acme.sh --ecc \
--installcert -d hehe.fnzoo.com \
--key-file /etc/cert/hehe.fnzoo.com.key \
--fullchain-file /etc/cert/fullchain.cer \
--reloadcmd "/usr/local/nginx/sbin/nginx -s reload"

使用 CA 证书生成 HPKP 证书指纹

1
2
3
4
5
$ openssl x509 -in /root/.acme.sh/hehe.fnzoo.com_ecc/ca.cer -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

# 成功后输出
writing RSA key
YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuih2=

自签名 CA 证书,用于生成备份 HPKP(证书指纹)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$ mkdir /etc/cert
$ cd /etc/cert
# 生成 1024 位加密的服务器私钥
$ openssl genrsa -out fnzoo.com.key 1024
# 制作 CSR 证书申请文件
$ openssl req -new -key fnzoo.com.key -out fnzoo.com.csr

# 制作 CSR 问题回答,红色为填写部分
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:Beijing
Locality Name (eg, city) []:Beijing
Organization Name (eg, company) [Internet Widgits Pty Ltd]:fnzoo.com
Organizational Unit Name (eg, section) []:IT
Common Name (e.g. server FQDN or YOUR name) []:hehe.fnzoo.com
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

# 自己给自己签发证书
$ openssl x509 -req -days 3650 -in fnzoo.com.csr -signkey fnzoo.com.key -out fnzoo.com.crt
# 生成备份用的 HPKP(证书指纹)
$ openssl x509 -in fnzoo.com.crt -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

# 成功后输出
writing RSA key
RsO0x8J5EdQMJChV5H+tKaTcOuRjdkv3VazWCYZId2U=

修改 nginx 配置文件并重启

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
$ vi /usr/local/nginx/conf/ssl.conf

# 启用 HSTS
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains;";
# 不允许被框架嵌套
add_header X-Frame-Options DENY;
# 失效内容类型嗅探
add_header X-Content-Type-Options nosniff;
# 防止跨站脚本 XSS
add_header X-XSS-Protection "1; mode=block";
# 启用 Cache Control
add_header Cache-Control max-age=3600;
# 启用 CSP 防止 XSS 攻击
add_header Content-Security-Policy "default-src 'self'";
# 配置 HPKP(证书指纹)
add_header Public-Key-Pins 'pin-sha256="YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg="; pin-sha256="RsO0x8J5EdQMJChV5H+tKaTcOuRjdkv3VazWCYZId+U="; max-age=15552000; includeSubDomains';

# TLS 会话恢复,简化 TLS 握手
ssl_session_cache shared:SSL:10m;
# SSL session 过期时间
ssl_session_timeout 10m;
# 开启浏览器的Session Ticket 缓存
ssl_session_tickets on;

# OCSP stapling 策略
ssl_stapling on;
# OCSP 证书路径,let's encrypt 不返回 ca 证书,所以无需设置 ssl_stapling_verify,ssl_trusted_certificate
ssl_stapling_verify on;
ssl_trusted_certificate /etc/cert/fullchain.cer;

# 用于查询 OCSP 服务器的 DNS
resolver 8.8.8.8 8.8.4.4 valid=300s;
# 查询域名超时时间
resolver_timeout 5s;

# 服务器证书和私钥路径
ssl_certificate /etc/cert/fullchain.cer;
ssl_certificate_key /etc/cert/hehe.fnzoo.com.key;

# 加密协议与算法
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:DES-CBC3-SHA;

# 在 TLSv1 握手时,使用服务端的配置项,以增强安全性
ssl_prefer_server_ciphers on;

$ nginx -s reload