相关概念

  • Let’s Encrypt - 提供免费的 HTTPS 证书,但需要定期更新
  • lego - Go 语言实现的 Let’s Encrypt 客户端及 ACME 库
  • certbot - Let’s Encrypt 官方推荐的客户端

目标需求

  • 注册可以所有子域名共用的通配符证书,包含 *.jiagou.comjiagou.com
  • 能够定期自动更新证书
  • 域名的 DNS 服务器在 阿里云、Godaddy 上
  • 反向代理服务器使用的是 Nginx

方案选择

  • 为什么用通配符证书?
    普通证书 - 每个域名分别对应一个证书,有效期更久
    通配符证书 - 根域名统一使用一个证书,有效期更短,但不用没新增一个子域名就去申请新证书

  • 为什么用 lego,而不用 certbot?
    对应通配符证书,certbot 的自动更新只支持有限的 DNS 服务器,阿里云和 Godaddy 都不在之列

  • 为什么用 DNS 方式验证域名?
    HTTP 方式 - 在域名对应的网站指定目录下放验证文件,不支持通配符证书验证
    DNS 方式 - 在域名 DNS 中添加 TXT 记录解析验证文本,都支持,但如果要实现自动更新,需要 DNS 服务器提供 API

自动验证域名

根据 阿里云 DNS 代理配置说明 得知需要去阿里云申请 API 授权,得到参数
登陆阿里云控制台

访问控制 > 用户 > 新建用户

登陆名: dns
显示名: dns
访问方式: OpenAPI 调用访问

创建后,添加权限: AliyunDNSFullAccess
最终得到 AccessKey ID、AccessKeySecret

mkdir -p /data/cert && cd /data/cert

# 下载
wget https://github.com/go-acme/lego/releases/download/v4.18.0/lego_v4.18.0_linux_amd64.tar.gz

# 解压包中的lego文件
tar -xvf lego_v4.18.0_linux_amd64.tar.gz lego

# 查看帮助
./lego -h


# ALICLOUD_ACCESS_KEY、ALICLOUD_SECRET_KEY 设置为对应的 API 参数
# --path 为配置和证书生成目录,如果不指定默认为 `./.lego`
# --dns 为 DNS 服务器 Code
# --email 为注册邮箱,用于接收证书过期提醒邮件
ALICLOUD_ACCESS_KEY=LTAI4FtPNv... \
ALICLOUD_SECRET_KEY=ULv4Y7Ac... \
./lego --email="email@jiagou.com" --domains="*.jiagou.com" --domains="jiagou.com" --path="./jiagou.com"  --dns="alidns" run

## 成功输出为
#Server responded with a certificate.

## 错误输出 Incorrect TXT record,TXT 更新慢导致的,多执行几次就好了
#acme: error: 403 :: urn:ietf:params:acme:error:unauthorized :: Incorrect TXT record "null" found at \_acme-challenge.crowxxx.com, url:


#刷新证书,30天内进行续期
ALICLOUD_ACCESS_KEY=LTAI4FtPNv... \
ALICLOUD_SECRET_KEY=ULv4Y7Ac... \
./lego --email="email@jiagou.com" --domains="*.jiagou.com" --domains="jiagou.com" --path="./jiagou.com" renew --days=30 

# 也可以crontab做个定时任务自动更新.

手动验证域名

有些时候,并不想开放dns的API权限,可以使用手动验证的方式

mkdir -p /data/cert && cd /data/cert

# 下载
wget https://github.com/go-acme/lego/releases/download/v4.18.0/lego_v4.18.0_linux_amd64.tar.gz

# 解压包中的lego文件
tar -xvf lego_v4.18.0_linux_amd64.tar.gz lego

#初始化Lego并获取挑战信息,指定 --dns manual 选项,生成必要的账户信息和一个未完成的证书请求.
./lego --email="email@jiagou.com" --domains="*.jiagou.com" --domains="jiagou.com" --path="./jiagou.com"  --dns=manual --accept-tos run

# 成功后,会输出如下信息
lego: Please create the following TXT record in your jiagou.com. zone:
_acme-challenge.jiagou.com. 120 IN TXT "8abGHhhgEUj14st1O_OId9aj_6OriGyvb5Cwrj9PPDO"
lego: Press 'Enter' when you are done

# 登陆域名 DNS 服务器,添加 TXT 记录解析验证文本
TXT记录: _acme-challenge.jiagou.com. 
值: 8abGHhhgEUj14st1O_OId9aj_6OriGyvb5Cwrj9PPDO
TTL: 120 (最短的时间,尽快生效)

# DNS设置成功之后,按回车.等待 DNS 记录生效.如果无法识别就反复多设置几次

HTTP文件验证

通过http访问文件进行验证单个域名,不修改DNS.需要 http://jiagou.com/.well-known/acme-challenge/ 访问到 http.webroot (/data/cert/) 目录下的 .well-known/acme-challenge/

 ### nginx配置解析
 #location ~ ^/.well-known/acme-challenge/ {
 #      root /data/cert;
 #}

mkdir -p /data/cert && cd /data/cert

# 下载
wget https://github.com/go-acme/lego/releases/download/v4.18.0/lego_v4.18.0_linux_amd64.tar.gz

# 解压包中的lego文件
tar -xvf lego_v4.18.0_linux_amd64.tar.gz lego

#创建目录,用于存放生成的证书文件
mkdir -p /data/cert/.well-known/acme-challenge/

./lego  --email="email@jiagou.com" --domains="jiagou.com" --path="./jiagou.com" --http --http.webroot "/data/cert/" run

#注意: http.webroot 是存放的目录,不要带 /.well-known/acme-challenge/

配置Nginx

ssl_certificate /data/cert/jiagou.com/certificates/_.jiagou.com.crt;
ssl_certificate_key /data/cert/jiagou.com/certificates/_.jiagou.com.key;