使用 acme.sh 自动为 IP / 域名配置证书

· Technology

SSL 证书作为一个在市场上应用十几年的玩意,任何一个做 Web 相关技术的都不大可能不知道这是个啥。

常见的国内个人站长使用的 SSL 证书基本都是 Let's Encrypt、 TrustAsia、CloudFlare SSL 等,它们都提供免费的 DV SSL 域名证书。而本文中主要的应用场景是基于 ACME 协议和其实现 acme.sh 进行自动化证书签发。

环境须知

因作者个人爱好原因,本文所提供的命令均为 Ubuntu 22.04 LTS 系统下测试完成的命令,截图也将为此系统环境的截图。
如使用 Debian 等与此兼容的系统环境,可直接使用。
如使用RHEL、Cent OS等不兼容的系统环境,需要自行替换部分目录,例如:apt

关于 SSL

做网络,要是连 SSL 都不知道是啥,快去投胎吧……

SSL:一个让你花钱的同时感受到极度的快乐的玩意,尽管你花的钱通常没啥用。

Secure Sockets Layer,即 SSL,中文翻译为 安全套接层。我们目前所使用的被称之为 SSL 加密的并非是原本的 SSL,而是更新更安全的 TLS (Transport Layer Security, 传输层安全性协议)加密。

这是是一种安全协议,目的是为互联网通信提供安全及数据完整性保障。网景公司(Netscape)在1994年推出首版网页浏览器-网景导航者时,推出HTTPS协议,以SSL进行加密,这是SSL的起源。

IETF将SSL进行标准化,1999年公布TLS 1.0标准文件(RFC 2246)。随后又公布TLS 1.1(RFC 4346,2006年)、TLS 1.2(RFC 5246 ,2008年)和TLS 1.3(RFC 8446,2018年)。

SSL包含记录层(Record Layer)和传输层,记录层协议确定传输层数据的封装格式。传输层安全协议使用X.509认证,之后利用非对称加密 演算来对通信方做身份认证,之后交换对称密匙作为会谈密匙(Session key)。 这个会谈密匙是用来将通信两方交换的资料做加密,保证两个应用间通信的保密性和可靠性,使客户与服务器应用之间的通信不被攻击者窃听。

在 Web 应用程序中,我们常将 TLS 搭配 HTTP 协议进行使用(它们之间无耦合),即 HTTP Over TLS。

ACME 协议

自动证书管理环境(英语:Automatic Certificate Management Environment,缩写ACME )是一种通信协议,用于证书颁发机构与其用户的Web服务器之间的自动化交互,允许以极低成本自动化部署公钥基础设施。

该协议由互联网安全研究小组(ISRG)为 Let's Encrypt 服务设计。

是的,就是第一个做免费 SSL 的神奇非盈利性组织。

acme.sh

Repo: acmesh-official/acme.sh

acme.sh 是通过 bash 对 ACME 协议进行的实现,可以通过调用 ACME Endpoint 生成证书。

安装

我们不会提供 Windows 环境的相关教程

# 安装依赖(Debian、Ubuntu)
apt install curl socat

# 调用脚本安装
curl https://get.acme.sh  sh -s email=my@example.com

# 添加别名命令
alias acme.sh=~/.acme.sh/acme.sh

更高级、详细的安装过程请参考:https://github.com/acmesh-official/acme.sh/wiki/How-to-install

CA 选择

acme.sh 的 wiki 提供了一些可供选择的 CA:

CAMaxLifetimeECCDomain CountWildcardIPv4IPv6NotAfterIDNCN
Let’s Encrypt90Yes100YesNoNoNoYesR3
ZeroSSL90Yes100YesNoNoYesYesZeroSSL RSA Domain Secure Site CA
Google90Yes100YesNoNoYesNoGTS
Buypass180Yes5PaidNoNoNoYesBuypass Class 2 CA 5
SSL.com90Yes2PaidNoNoNoYes
HiCA180Paid10 (1 if Wildcard)YesYesYesNoYesSectigo RSA Domain Validation Secure Server CA

来自 https://github.com/acmesh-official/acme.sh/wiki/CA

GTS 证书需注意

申请 GTS 证书需要在 Google Cloud 获取对应 Token,请参考:Automate Public Certificates Lifecycle Management via RFC 8555 (ACME) & Google Public CA

你可通过 --server <acme_endpoint> 指定CA,例如:

acme.sh --issue \
        -d example.com \
        --server https://acme.hi.cn/directory

签发证书

文件验证

# 文件验证签发证书
acme.sh --issue \
        -d example.com \
        -d www.example.com \
        --webroot /data/wwwroot/example.com/

# e.q.
acme.sh --issue \
        -d ssl-test.ah-dark.tech \
        -d ssl-test2.ah-dark.tech \
        --webroot /data/wwwroot/ssl-test.ah-dark.tech/

# 使用内置 HTTP 服务器
acme.sh --issue \
        -d example.com \
        --standalone
  • 通过 --issue 指定要执行的操作是签发证书。
  • 通过 -d <domain> 指定要包含的域名,此处可以包含多个域名,若包含不支持的域名会有报错提示。
  • 通过 --webroot <path> 指定 web 服务器的根路径,你也可以不使用这项而选择使用 --standalone 让 acme.sh 自己创建一个80端口的HTTP服务器进行监听。

指定 --webroot 后,脚本会访问 <path>/.well-known/ 创建验证文件,请确保其用户权限和 Web Server 权限配置正确。

Image
Image

随后你可以在以下位置找到你的证书文件等信息(当然你也可以后续使用自动安装证书):

  • ~/.acme.sh/<domain>/fullchain.cer 全链证书公钥(部署请使用这个)
  • ~/.acme.sh/<domain>/<domain>.csr 单域名公钥
  • ~/.acme.sh/<domain>/ca.cer CA证书公钥
  • ~/.acme.sh/<domain>/<domain>.key 证书私钥(部署请使用这个)

DNS 验证

首先,acme.sh 会请求 pki 获取对应域名需添加的 txt 记录:

acme.sh --issue --dns \
        -d example.com \
        --yes-I-know-dns-manual-mode-enough-go-ahead-please

# e.q.
acme.sh --issue --dns \
        -d ssl-test.ah-dark.tech \
        --yes-I-know-dns-manual-mode-enough-go-ahead-please
Image

第一步操作反馈

而后,你需要等待 txt 记录添加并解析完成,然后执行下一步操作:

# 注意这里是 renew
acme.sh --renew \
        -d example.com \
        --yes-I-know-dns-manual-mode-enough-go-ahead-please

# e.q.
acme.sh --renew \
        -d ssl-test.ah-dark.tech \
        --yes-I-know-dns-manual-mode-enough-go-ahead-please
Image

第二步操作反馈

随后你可以在以下位置找到你的证书文件等信息(当然你也可以后续使用自动安装证书):

  • ~/.acme.sh/<domain>/fullchain.cer 全链证书公钥(部署请使用这个)
  • ~/.acme.sh/<domain>/<domain>.csr 单域名公钥
  • ~/.acme.sh/<domain>/ca.cer CA证书公钥
  • ~/.acme.sh/<domain>/<domain>.key 证书私钥(部署请使用这个)

需要注意的是,dns 方式的真正强大之处在于可以使用域名解析商提供的 api 自动添加 txt 记录完成验证。

acme.sh 目前支持 cloudflare, dnspod, cloudxns, godaddy 以及 ovh 等数十种解析商的自动集成,具体请自行查阅 https://github.com/acmesh-official/acme.sh/blob/master/dnsapi/README.md

安装证书

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

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

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

Nginx

acme.sh --install-cert -d ssl-test.ah-dark.tech \
        --key-file       /path/to/keyfile/in/nginx/key.pem  \
        --fullchain-file /path/to/fullchain/nginx/cert.pem \
        --reloadcmd     "service nginx force-reload"

# e.q.
acme.sh --install-cert -d ssl-test.ah-dark.tech \
        --key-file       /usr/local/nginx/conf/ssl/ssl-test.ah-dark.tech.key  \
        --fullchain-file /usr/local/nginx/conf/ssl/ssl-test.ah-dark.tech.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 ,即证书更新后执行的命令。

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

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

Apache

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"

查询证书信息

对于已签发的证书,可以通过下述命令查询其证书信息:

acme.sh --info -d example.com

# e.q.
acme.sh --info -d ssl-test.ah-dark.tech
Image

自动化

使用上述安装方法安装的 acme.sh 会自动添加 crontab 条目。

你也可以自行添加:

15 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

IP 证书

目前 acme.sh 提供的支持 IP SSL ACME 签发的CA仅有 HiCA。

Image

IP SSL

请务必注意,IP SSL仅能使用 PTR 反向查询记录 和 文件验证 进行签发,本人不清楚 acme.sh 是否支持PTR验证,因此建议使用文件验证。

Comments

Send Comments

Markdown supported. Please keep comments clean.