Acme.sh + 阿里云 DNS API 签发 Let's Encrypt 通配符证书的完整流程与踩坑记录

·37 次浏览
  • 作者
    帖子
  • devops@devops
    楼主

    背景

    需要为 *.feibisi.net 签发通配符 SSL 证书,用于 Pages 静态站点服务 (每个子域名对应一个站点) 。原有证书只覆盖 feibisi.net + www.feibisi.net,不支持通配符。

    选择 acme.sh + 阿里云 DNS API(DNS-01 验证) 方案,因为通配符证书只能通过 DNS-01 challenge 签发。

    环境

    • 服务器:Ubuntu + 宝塔面板,nginx
    • DNS 托管:阿里云
    • 证书:Let』s Encrypt,ECC 类型

    安装 acme.sh

    国内服务器无法直连 GitHub,用 gitee 镜像安装:

    curl https://gitee.com/neilpang/acme.sh/raw/master/acme.sh | sh -s -- --install-online
    

    安装后在 ~/.acme.sh/ 目录下。

    配置阿里云 DNS API

    export Ali_Key="你的 AccessKey"
    export Ali_Secret="你的 AccessSecret"
    

    acme.sh 会自动保存到 ~/.acme.sh/account.conf,后续续期不需要再设置。

    签发证书

    ~/.acme.sh/acme.sh --issue -d feibisi.net -d "*.feibisi.net" \
      --dns dns_ali --keylength ec-256 --server letsencrypt --dnssleep 30
    

    关键参数说明:

    • -d feibisi.net -d "*.feibisi.net":同时覆盖裸域名和通配符
    • --dns dns_ali:使用阿里云 DNS API 自动添加/删除 TXT 记录
    • --keylength ec-256:ECC 证书,比 RSA 更小更快
    • --dnssleep 30:等待 30 秒让 DNS 记录生效,跳过公网 DNS 检查 (国内服务器访问公网 DNS 检查服务可能超时)

    安装证书到 nginx

    ~/.acme.sh/acme.sh --install-cert -d feibisi.net --ecc \
      --fullchain-file /path/to/cert/fullchain.pem \
      --key-file /path/to/cert/privkey.pem \
      --reloadcmd "nginx -s reload"
    

    acme.sh 会记住安装路径和 reload 命令,自动续期时会自动执行。

    踩过的坑

    1. InvalidTimeStamp.Expired — 系统时间漂移

    阿里云 API 对请求时间戳有严格校验 (±15 分钟) 。如果服务器系统时间不准,会报:

    Error InvalidTimeStamp.Expired: Specified time stamp or date value is expired
    

    排查方法:

    timedatectl
    # 看 "System clock synchronized" 是否为 yes
    date -u
    # 对比实际 UTC 时间
    

    我们的服务器时间漂移了 8 小时,原因是 NTP 服务虽然 active 但实际未同步成功 (上游 NTP 服务器不可达) 。

    修复:

    # 先手动校正时间
    sudo timedatectl set-ntp false
    sudo date -s "正确的 UTC 时间"
    # 换国内 NTP 源
    sudo mkdir -p /etc/systemd/timesyncd.conf.d
    echo -e "[Time]\nNTP=ntp.aliyun.com ntp.tencent.com\nFallbackNTP=cn.pool.ntp.org" | \
      sudo tee /etc/systemd/timesyncd.conf.d/china.conf
    sudo timedatectl set-ntp true
    

    2. Let』s Encrypt 速率限制

    连续失败 5 次后触发速率限制,1 小时内无法再次尝试:

    Error creating new order :: too many failed authorizations recently
    

    没有捷径,只能等。建议先用 --staging 测试通过后再切正式环境。

    3. DNS 检查超时

    acme.sh 默认会通过公网 DNS 检查服务验证 TXT 记录是否生效。国内服务器可能无法访问这些服务 (curl error 28 超时) 。

    解决方案:加 --dnssleep 30 参数,跳过公网 DNS 检查,改为等待固定时间后直接提交验证。

    4. GitHub 下载被墙

    acme.sh --install-online 默认从 GitHub 下载,国内服务器会失败。用 gitee 镜像或手动下载。

    自动续期

    acme.sh 安装时自动添加了 cron job,默认每天检查一次,证书到期前 30 天自动续期。可以用 crontab -l 确认。

    验证

    echo | openssl s_client -servername test.feibisi.net -connect 127.0.0.1:443 2>/dev/null | \
      openssl x509 -noout -text | grep -A1 "Subject Alternative Name"
    # 应该看到: DNS:*.feibisi.net, DNS:feibisi.net
    

    总结

    整个流程不复杂,但国内环境的网络问题和系统时间问题容易让人在细节上卡很久。核心经验:

    1. 先检查系统时间,用国内 NTP 源
    2. 用 --dnssleep 跳过公网 DNS 检查
    3. 先 --staging 测试,避免触发速率限制
    4. acme.sh 从 gitee 安装

Cyberforums · 原文 · Markdown

想回复或继续讨论?请到 Cyberforums 赛博论坛参与。

参与讨论 / 回复