申请Let's Encrypt 或ZeroSSL免费泛域名证书

59

背景

个人网站域名maplefix.top一直使用的是亚洲诚信的免费证书,支持单域名HTTPS访问,有效期一年。目前证书过期了,看了下trustasia免费的证书只支持单域名访问,泛域名证书个人一般个人用户是用不起的。忽然想起之前的Let's EncryptZeroSSL都是免费证书,虽然有效期只有三个月,但是可以通过定时脚本续期实现无限使用,查看Let's Encrypt文档发现现在已经可以支持免费的泛域名证书,好的,搞起!

Let's Encrypt: https://letsencrypt.org

ZeroSSL: https://zerossl.com

acme.sh: https://github.com/acmesh-official/acme.sh/wiki/%E8%AF%B4%E6%98%8E

How-to-install-acme: https://github.com/acmesh-official/acme.sh/wiki/How-to-install

How-to-issue-a-cert:https://github.com/acmesh-official/acme.sh/wiki/How-to-issue-a-cert

服务器环境

  • Linux服务器一台,本文使用CentOS7

  • Maplefix.top域名一个

  • DnsPod账号一个,用于解析maplefix.top域名,域名本身托管于腾讯云

需要懂得科学上网,因为要用到github下载,国内服务器可能下载过慢或者无法访问

安装acme.sh

安装很简单, 一个命令,后面-s email参数可省略,推荐加上:

curl https://get.acme.sh | sh -s email=my@example.com

这一步会用到github下载,如果国内服务器无法下载或者下载过慢参考how-to-install-acme或者下载压缩包自行上传解压。

普通用户和 root 用户都可以安装使用. 安装过程进行了以下几步:

  1. 把 acme.sh 安装到你的 home 目录下:

~/.acme.sh/

并创建 一个 shell 的 alias, 例如 .bashrc,方便你的使用: alias acme.sh=~/.acme.sh/acme.sh

2.自动为你创建 cronjob, 每天 0:00 点自动检测所有的证书, 如果快过期了, 需要更新, 则会自动更新证书.

更高级的安装选项请参考: https://github.com/Neilpang/acme.sh/wiki/How-to-install

安装过程不会污染已有的系统任何功能和文件, 所有的修改都限制在安装目录中: ~/.acme.sh/

生成证书

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

本文采用第二种的方式

1. http 方式需要在你的网站根目录下放置一个文件, 来验证你的域名所有权,完成验证. 然后就可以生成证书了.

acme.sh --issue -d mydomain.com -d www.mydomain.com --webroot /home/wwwroot/mydomain.com/

只需要指定域名, 并指定域名所在的网站根目录. acme.sh 会全自动的生成验证文件, 并放到网站的根目录, 然后自动完成验证. 最后会聪明的删除验证文件. 整个过程没有任何副作用.

如果你用的 apache服务器, acme.sh 还可以智能的从 apache的配置中自动完成验证, 你不需要指定网站根目录:

acme.sh --issue -d mydomain.com --apache

如果你用的 nginx服务器, 或者反代, acme.sh 还可以智能的从 nginx的配置中自动完成验证, 你不需要指定网站根目录:

acme.sh --issue -d mydomain.com --nginx

注意, 无论是 apache 还是 nginx 模式, acme.sh在完成验证之后, 会恢复到之前的状态, 都不会私自更改你本身的配置. 好处是你不用担心配置被搞坏, 也有一个缺点, 你需要自己配置 ssl 的配置, 否则只能成功生成证书, 你的网站还是无法访问https. 但是为了安全, 你还是自己手动改配置吧.

如果你还没有运行任何 web 服务, 80 端口是空闲的, 那么 acme.sh 还能假装自己是一个webserver, 临时听在80 端口, 完成验证:

acme.sh --issue -d mydomain.com --standalone

更高级的用法请参考: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert

2. 手动 dns 方式, 手动在域名上添加一条 txt 解析记录, 验证域名所有权

这种方式的好处是, 你不需要任何服务器, 不需要任何公网 ip, 只需要 dns 的解析记录即可完成验证. 坏处是,如果不同时配置 Automatic DNS API,使用这种方式 acme.sh 将无法自动更新证书,每次都需要手动再次重新解析验证域名所有权。

acme.sh 目前支持 cloudflare, dnspod, cloudxns, godaddy 以及 ovh 等数十种解析商的自动集成.

以 dnspod 为例, 你需要先登录到 dnspod 账号, 生成你的DNSPod Token,记录下ID和Token,分别对应 api id 和 api key。 然后:

export DP_Id="123456"
​
export DP_Key="xxxxxxxxxxxxx"
​
acme.sh --issue --dns dns_dp -d maplefix.top -d *.maplefix.top --dns  dns_dp  --log --cert-home /usr/local/nginx/cert  --dnssleep 30 --server letsencrypt

参数说明:

  • -d指定单域名,-dns dns_dp指定泛域名

  • -log打印安装日志

  • --cert-home 安装的证书目录

  • --dnssleep 30 添加完dns记录后等待30s,默认是使用国外dns来检测,国内可能访问慢或者访问不了

  • --server letsencrypt 追加后使用Let's Encrypt证书,不追加默认使用ZeroSSL颁发的证书

证书就会自动生成了. 这里给出的 api id 和 api key 会被自动记录下来, 将来你在使用 dnspod api 的时候, 就不需要再次指定了. 直接生成就好了:

acme.sh --issue -d maplefix2.com --dns  dns_dp

更详细的 api 用法: https://github.com/Neilpang/acme.sh/blob/master/dnsapi/README.md

copy或者安装证书

由于上一步已将生成的证书放到NGINX对应的证书目录,所以可以直接配置NGINX配置文件,重新加载使其生效,不过官方推荐的方式如下:

前面证书生成以后, 接下来需要把证书 copy 到真正需要用它的地方.

注意, 默认生成的证书都放在安装目录下: ~/.acme.sh/, 请不要直接使用此目录下的文件, 例如: 不要直接让 nginx/apache 的配置文件使用这下面的文件. 这里面的文件都是内部使用, 而且目录结构可能会变化.

正确的使用方法是使用 --install-cert 命令,并指定目标位置, 然后证书文件会被copy到相应的位置, 例如:

Apache example:

acme.sh --install-cert -d example.com \
--cert-file      /path/to/certfile/in/apache/cert.pem  \
--key-file       /path/to/keyfile/in/apache/key.pem  \
--fullchain-file /path/to/fullchain/certfile/apache/fullchain.pem \
--reloadcmd     "service apache2 force-reload"

Nginx example:

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     "service nginx force-reload"

(一个小提醒, 这里用的是 service nginx force-reload, 不是 service nginx reload, 据测试, reload 并不会重新加载证书, 所以用的 force-reload)

Nginx 的配置 ssl_certificate 使用 /etc/nginx/ssl/fullchain.cer ,而非 /etc/nginx/ssl/<domain>.cer ,否则 SSL Labs 的测试会报 Chain issues Incomplete 错误。

--install-cert命令可以携带很多参数, 来指定目标文件. 并且可以指定 reloadcmd, 当证书更新以后, reloadcmd会被自动调用,让服务器生效.

详细参数请参考: https://github.com/Neilpang/acme.sh#3-install-the-issued-cert-to-apachenginx-etc

值得注意的是, 这里指定的所有参数都会被自动记录下来, 并在将来证书自动更新以后, 被再次自动调用.

Nginx配置

#配置主域名指向地址
server {
    listen *:443 ssl; 
    listen [::]:443 ssl; 
    server_name maplefix.top;    
    #  ssl on;
    # 开启 OCSP Stapling ---当客户端访问时 NginX 将去指定的证书中查找 OCSP 服务的地址,获得响应内容后通过证书链下发给客户端。
    ssl_stapling on;
    # 启用OCSP响应验证,OCSP信息响应适用的证书
    ssl_stapling_verify on;
    # 证书颁发结构的中间证书+根证书
    ssl_trusted_certificate cert/maplefix.top_ecc/ca.cer;
    ssl_certificate  cert/maplefix.top_ecc/fullchain.cer;
    ssl_certificate_key  cert/maplefix.top_ecc/maplefix.top.key;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    ssl_prefer_server_ciphers on;
    location / {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;
        proxy_pass http://127.0.0.1:8090;
        proxy_redirect off;
    }
}

特别注意里面的以下配置,可加速客户端(浏览器)访问,具体可查阅 OCSP协议 相关

# 开启 OCSP Stapling ---当客户端访问时 NginX 将去指定的证书中查找 OCSP 服务的地址,获得响应内容后通过证书链下发给客户端。
ssl_stapling on;
# 启用OCSP响应验证,OCSP信息响应适用的证书
ssl_stapling_verify on;
# 证书颁发结构的中间证书+根证书
ssl_trusted_certificate cert/maplefix.top_ecc/ca.cer;

重新加载Nginx配置文件使证书生效

nginx -s reload

自动续期

在第一部安装成功后会自动添加一条crontab定时脚本,使用 crontab -l 查看最后一行添加的定时任务

目前证书在 60 天以后会自动更新, 你无需任何操作. 今后有可能会缩短这个时间, 不过都是自动的, 你不用关心.

crontab  -l
​
56 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

如果自定义了证书路径,或有新加的参数,就请修改定时任务中命令如下:

/root/.acme.sh/acme.sh --cron --home /root/.acme.sh --cert-home /usr/local/nginx/cert  --dnssleep 30 --server letsencrypt

修改后在命令行先测试下是否能自动续期,如下指定证书目录后会自动检测里面有哪些域名,然后用`crontab -e`把命令替换上去

[2023年 03月 06日 星期一 20:25:54 CST] ===Starting cron===
[2023年 03月 06日 星期一 20:25:55 CST] Renew: '*.maplefix.top'
[2023年 03月 06日 星期一 20:25:55 CST] Renew to Le_API=https://acme-v02.api.letsencrypt.org/directory
[2023年 03月 06日 星期一 20:25:55 CST] Skip, Next renewal time is: 2023-05-04T11:00:28Z
[2023年 03月 06日 星期一 20:25:55 CST] Add '--force' to force to renew.
[2023年 03月 06日 星期一 20:25:55 CST] Skipped *.maplefix.top_ecc
[2023年 03月 06日 星期一 20:25:55 CST] Renew: 'maplefix.top'
[2023年 03月 06日 星期一 20:25:55 CST] Renew to Le_API=https://acme-v02.api.letsencrypt.org/directory
[2023年 03月 06日 星期一 20:25:55 CST] Skip, Next renewal time is: 2023-05-04T11:24:29Z
[2023年 03月 06日 星期一 20:25:55 CST] Add '--force' to force to renew.
[2023年 03月 06日 星期一 20:25:55 CST] Skipped maplefix.top_ecc
[2023年 03月 06日 星期一 20:25:55 CST] ===End cron===

更新acme.sh

目前由于 acme 协议和 letsencrypt CA 都在频繁的更新, 因此 acme.sh 也经常更新以保持同步.

升级 acme.sh 到最新版 :

acme.sh --upgrade

如果你不想手动升级, 可以开启自动升级:

acme.sh --upgrade --auto-upgrade

之后, acme.sh 就会自动保持更新了.

你也可以随时关闭自动更新:

acme.sh --upgrade --auto-upgrade  0

结果验证

cert-info.png