惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Secure Thoughts
C
Check Point Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
月光博客
月光博客
博客园 - 【当耐特】
Jina AI
Jina AI
雷峰网
雷峰网
J
Java Code Geeks
腾讯CDC
博客园 - 聂微东
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - 叶小钗
aimingoo的专栏
aimingoo的专栏
Martin Fowler
Martin Fowler
The Register - Security
The Register - Security
罗磊的独立博客
V
V2EX
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Security Latest
Security Latest
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cyber Attacks, Cyber Crime and Cyber Security
有赞技术团队
有赞技术团队
The Hacker News
The Hacker News
Scott Helme
Scott Helme
T
The Blog of Author Tim Ferriss
Spread Privacy
Spread Privacy
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
The Exploit Database - CXSecurity.com
Vercel News
Vercel News
Cisco Talos Blog
Cisco Talos Blog
美团技术团队
B
Blog RSS Feed
L
LangChain Blog
大猫的无限游戏
大猫的无限游戏
SecWiki News
SecWiki News
Webroot Blog
Webroot Blog
N
News | PayPal Newsroom
D
Docker
云风的 BLOG
云风的 BLOG
Recorded Future
Recorded Future
W
WeLiveSecurity
C
CERT Recently Published Vulnerability Notes
L
Lohrmann on Cybersecurity
T
Tenable Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
阮一峰的网络日志
阮一峰的网络日志
I
Intezer
Hugging Face - Blog
Hugging Face - Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org

atpX

自建 S3 兼容对象存储服务 Garage 听风的歌 偶尔是深夜就好了 新玩具 AirPods Pro 3 公交车上的时间 从 WHOIS 到 RDAP 通过 WireGuard 访问 NFS 共享文件 自建音乐串流服务探索 我停止了探索 Fediverse 互联网背景噪音 我的数字生活降级 小城与确定性的墙 一只特立独行的猪 Fediverse 与社交 承认的勇气 mediaX - 轻量书影音记录管理工具 我的博客写作流程 网站新增 Misc 页面 擅长对线的鲍勃 在 Chroot 环境下使用 Rsync 同步 再见 JavaScript 当我玩博客时我在玩什么 为什么我的博客没有友链页面 小熊猫与大熊猫 (HDR 照片测试) 是时候为网站开启 HTTP/3 支持了吗 使用 AdGuard Home 搭建自用 DoH 服务 谈谈读书与消遣 2023 年终总结 西安两日游 从 AirPods「升级」到 EarPods Docker 搭建去中心化的微博客平台 Mastodon 聊聊 iPhone 15 Pro 使用感受 能否将 TOTP 二次验证存放在密码管理器里 认识史蒂夫·乔布斯 与“锤哥”克里斯·海姆斯沃斯一起养生 逃离爆炸的信息 你想活出怎样的人生 重温《龙珠》动画 为什么关闭评论 从域名注册商到 DNS 服务,找到自己的组合 如何提高用户网页阅读体验 从 Typecho 迁移到 Hugo 个人博客的最终归宿是静态网站吗 我选择了放弃 jQuery 关于我的小破站折腾速度优化这件事 记一次家庭网络折腾 贴一些 SmokePing 记录 我的域名邮箱选择 不存在的语录 Typecho 评论验证插件 CaptchaPlus 谈谈写字这件事 新的网站 Logo 探索 曲线解决 Typecho 图片占位抖动问题 自建 vaultwarden / bitwarden_rs 密码管理器 使用 Plausible 自建网站流量统计分析工具 如何优雅地徒手剥开火腿肠 简单的集中隔离生活记录 新玩具 M2 MacBook Air 使用 acme.sh 申请 Google 公共证书 Docker 搭建去中心化的微博客平台 Misskey 搭建 Lsky Pro 兰空图床 折腾树莓派系统的一天 我的吉卜力之旅 使用 Uptime Kuma 自建服务器/网站在线率监控 Spartan Host Review - Best Hosting & Service Support Debian 下 Nginx 配合 Fail2Ban 减少恶意扫描和攻击 升级 Typecho 到最新开发版本 v1.2.0 Linux rm 命令详解 Debian 系统安装 Docker 教程 BandwagonHost - Reliable Blog and Business VPS Hosting 使用 Isso 为 Hugo/Hexo 等静态网站添加评论功能 推荐 5 款免费开源的网站流量分析统计工具 搭建 Shynet 网站流量统计分析工具 聊聊 DDoS 攻击那些事 Hugo 使用 Fancybox 实现图片灯箱/放大功能 从 Debian 10 升级到 Debian 11 教程 使用 Umami 自建网站流量统计分析工具 Linux 一次执行多个命令的 3 种方式 Typecho 修改永久链接后旧链接 301 跳转到新链接 从不同需求推荐几家稳定可靠的 VPS 服务商 Build EchoIP service with Docker 浅谈一下这些年折腾过的 VPS 单线复用解决一根网线同时 IPTV 和宽带问题 不完全吃灰的树莓派 开发一个自己的 Telegram Bot 使用 Nginx 实现 TCP 四层反向代理 画画真难 我读村上春树 卡拉马佐夫式悲剧 安装 File Browser 轻量网盘工具 新玩具树莓派到手 Linux 定时自动备份数据到 OneDrive/Google Drive 记一次服务器崩溃 使用 rsync 同步文件 短信的消失 幻灭的艺术家 新玩具戴尔 S2721DGF 开箱 蝴蝶 用 Docker 整合 SeafilePro 搭建私人云盘 搭建自己的 kms 服务器
使用 acme.sh 自动签发和更新证书
ATP · 2020-12-17 · via atpX

手里吃灰的域名越来越多,偶尔还是会拿来测试测试,每次手动配置证书就很麻烦,刚好最近 Let’s Encrypt Authority 也由 X3 更新为了 R3 版本,使用了新的 OCSP 地址,解决了污染问题。因此又用回 acme.sh 自动签发更新证书,官方有很详细的使用文档,这里只做简单记录。

安装

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

若后面出现 command not found,则需要手动执行以下命令:

source ~/.bashrc

生成证书

HTTP 认证方式

该方式 acme.sh 会在你的指定的网站根目录下自动生成一个文件,来验证域名所有权,然后自动完成验证并签发证书:

acme.sh --issue -d domain.tld -d www.domain.tld --webroot /home/wwwroot/domain.tld/

完成后会自动删除验证文件,无需多余操作。

DNS 认证方式(推荐)

这里为了方便,选择通过 DNS 认证方式,这种方式不需要服务器和公网 IP,只需要 DNS 的解析记录即可完成验证,一般主流域名服务商都提供 API 接口,acme.sh 目前支持包括主流的 CloudFlare、DNSPod、Aliyun、Amazon Route53 在内的多达 131 个的域名 API,你这可以在这里查看到详细的支持列表。我的 DNS 服务器一般用的是 Cloudflare,因此这里以 Cloudflare 的 API 为例验证,获取 Cloudflare API,可以自己选择全局 API 还是单域 API,我这里选择了单域 API,获取到 API 后注意保存,然后导入:

export CF_Token="xxxxxxxxxxxxxxxxxxxxxxxx"
export CF_Account_ID="xxxxxxxxxxxxxxxxxxxxxxxx"
export CF_Zone_ID="xxxxxxxxxxxxxxxxxxxxxxxx"

其中 CF_Token 为你获取到的API密钥,CF_Account_ID 和 CF_Zone_ID 可以在你域名概述页面的 API 分栏看到。

签发证书:

acme.sh --issue --dns dns_cf -d domain.tld -d www.domain.tld

若要生成通配符证书,则:

acme.sh --issue --dns dns_cf -d domain.tld -d *.domain.tld

如果要签发 ECC 证书,需要在后面加上 --keylength 选项,下面的示例是签发一张 256 位长度的 EEC 通配符证书:

acme.sh --issue --dns dns_cf -d domain.tld -d *.domain.tld --keylength ec-256

2021 年 6 月 29 日更新

今天准备签发一张证书,结果发现提示错误:

acme.sh is using ZeroSSL as default CA now.
Please update your account with an email address first.

然后去 Github 上项目看了下,发现一篇公告,说是从 8 月 1 日起,默认 CA 将换成 ZeroSSL,不过这不是还没到 8 月 1 日么…虽然 ZeroSSL 以前了解过也不错,同样支持免费签发 90 天期限的证书,包括通配符和 ECC 证书,甚至还支持 IP 证书,不过需要注册账号才行。至于为什么变成了 ZeroSSL,从这篇公告来看,应该是 acme.sh 被 apilayer 收购了。不过我还是习惯了 Let’s Encrypt 的方便,想要继续使用 Let’s Encrypt 证书,公告里也给出了两种解决方案。

第一种是签发证书时指定 CA:

acme.sh --issue --dns dns_cf -d domain.tld --server letsencrypt

另一种是直接更改默认 CA:

acme.sh --set-default-ca --server letsencrypt

如果设置了默认的 CA,以后就算版本升级也将一直默认使用指定的 CA。


大概 30s 左右就能成功签发证书,证书生成后会将你前面提供的 API 信息自动记录下来,将来在使用的时候就不需要再次指定了,直接生成:

acme.sh --issue -d mydomain2.com --dns dns_cf

安装证书

默认生成的证书都放在安装目录下:~/.acme.sh/,建议使用 --install-cert 命令指定目标位置,将证书文件复制到相应的位置,这里用 Nginx 示例:

acme.sh --install-cert -d domain.tld \
--key-file       /path/to/ssl/private.key  \
--fullchain-file /path/to/ssl/fullchain.pem \
--capath         /path/to/ssl/ca.pem  \
--reloadcmd      "service nginx reload"

如果是安装 ECC 证书:

acme.sh --install-cert -d domain.tld --ecc \
--key-file       /path/to/ssl/private.key  \
--fullchain-file /path/to/ssl/fullchain.pem \
--capath         /path/to/ssl/ca.pem  \
--reloadcmd      "service nginx reload"

这里指定的所有参数都会被自动记录下来,并在将来证书自动更新以后,被再次自动调用,目前证书在 60 天以后会自动更新,无需任何操作。

如果要撤销一个证书,使用:

acme.sh --list
acme.sh --revoke -d domain.tld
acme.sh --revoke -d domain.tld --ecc

如果要删除一个证书,使用:

acme.sh --list
acme.sh --remove -d domain.tld
acme.sh --remove -d domain.tld --ecc

更新 acme.sh

升级 acme.sh 到最新版:

acme.sh --upgrade

开启自动升级:

acme.sh  --upgrade  --auto-upgrade

关闭自动更新:

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

关于自动更新证书失败

可能会有多种情况导致更新失败,一是如果时国内服务器自动更新可能会遇到各种玄学网络问题,二是前面提到的 acme.sh 更换了默认的 CA,如果你手动签发一次会发现相关的错误信息,解决办法已在前文提及,而我主要遇到的时另一种情况。

其实以前就发现过自动更新证书失败的情况,但服务器和域名比较多,有的成功有的失败就没太在意。因为我基本上都用的 Cloudflare API 进行签发,最近发现有部分域名 DNS 设置里面出现了几十条用于认证的 TXT 记录(吐槽一下,Cloudflare 不能多选删除,一条一条的删累死了…),于是准备研究一下问题出在哪里。

通过前面大量的 TXT 记录可以推断出 API 是调用成功了的,但却签发失败了,于是直接打开 .acme.sh/account.conf 文件,发现里面记录的 API Token 居然只有一个域名的,然后在 Github 上的一条 issue 中发现了问题所在,acme.sh 默认只会保留最新的域名 Token 信息,如果你在一台服务器上设置了多个域名,那么新设置的域名 Token 就会直接覆盖掉前面的,导致前面的域名更新证书时调用的是新域名的 Token,自然就会认证失败,而且由于失败后多次尝试,也会在最新域名的 DNS 里留下大量的 TXT 记录。

简单来说就是同一个 DNS 服务商通过 API 签发证书,只能保存一个域名的 Token 信息。而解决方法有三种,推荐前两种:

  1. 使用不同的 Linux 用户进行证书申请。

  2. 签发时指定 home 文件路径,通过添加 --config-home 参数实现:

mkdir /root/.acme2
acme.sh --config-home /root/.acme2 --issue --dns dns_cf -d domain.tld

此时你的 crontab 自动任务也要做出对应的修改,新增一个任务,并且时间最好和默认的 acme.sh 任务错开:

# 默认任务
20 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
# 新增任务
40 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" --config-home "/root/.acme2" > /dev/null
  1. 签发证书时指定配置文件,通过添加 --accountconf 参数实现:
acme.sh --issue --dns dns_cf -d domain.tld --accountconf /root/.acme.sh/account-custom.conf

同样,crontab 自动任务也要做出对应的修改。

一个完整的演示

为了使整个流程更加清晰方便自己操作,这里贴一个自己平时使用 acme.sh 申请证书的完整流程。

  • 申请方式:DNS 认证(使用 Cloudflare API)
  • 申请证书 CA:Let’s Encrypt
  • 申请证书类型:RSA + ECC 两个通配符证书
  • * 同一台主机多个域名的情况
# 安装 acme.sh
curl  https://get.acme.sh | sh

# 刷新 shell 变量配置
source ~/.bashrc

# 导入 Cloudflare API Token
export CF_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export CF_Account_ID="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export CF_Zone_ID="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

# 设置默认 CA 为 Let's Encrypt
acme.sh --set-default-ca --server letsencrypt

# 签发 RSA 证书
acme.sh --issue --dns dns_cf -d domain.tld -d *.domain.tld --keylength 2048

# 安装 RSA 证书到指定路径
acme.sh --install-cert -d domain.tld \
--key-file       /path/to/ssl/domain.tld_private.key  \
--fullchain-file /path/to/ssl/domain.tld_chain.pem \
--capath         /path/to/ssl/domain.tld_ca.pem  \
--reloadcmd      "service nginx reload"

# 签发 ECC 证书,若不需要,跳过即可
acme.sh --issue --dns dns_cf -d domain.tld -d *.domain.tld --keylength ec-256

# 安装 ECC 证书到指定路径
acme.sh --install-cert -d domain.tld --ecc \
--key-file       /path/to/ssl/ecc_domain.tld_private.key  \
--fullchain-file /path/to/ssl/ecc_domain.tld_chain.pem \
--capath         /path/to/ssl/ecc_domain.tld_ca.pem  \
--reloadcmd      "service nginx reload"

# 取消环境变量
unset CF_Token
unset CF_Account_ID
unset CF_Zone_ID

# 至此证书安装完毕
# 下面是同一台主机申请第二个域名证书

# 导入另一个 Cloudflare API Token
export CF_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export CF_Account_ID="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export CF_Zone_ID="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

# 新建一个文件夹作为 config home,默认会把所有文件存在这里
mkdir /root/.acme2

# 设置默认 CA 为 Let's Encrypt
acme.sh --config-home /root/.acme2 --set-default-ca --server letsencrypt

# 签发 RSA 证书
acme.sh --config-home /root/.acme2 --issue --dns dns_cf -d domain.tld -d *.domain.tld --keylength 2048

# 安装 RSA 证书到指定路径
acme.sh --config-home /root/.acme2 \
--install-cert -d domain.tld \
--key-file       /path/to/ssl/domain.tld_private.key  \
--fullchain-file /path/to/ssl/domain.tld_chain.pem \
--capath         /path/to/ssl/domain.tld_ca.pem  \
--reloadcmd      "service nginx reload"

# 签发 ECC 证书,若不需要,跳过即可
acme.sh --config-home /root/.acme2 --issue --dns dns_cf -d domain.tld -d *.domain.tld --keylength ec-256

# 安装 ECC 证书到指定路径
acme.sh --config-home /root/.acme2 \
--install-cert -d domain.tld --ecc \
--key-file       /path/to/ssl/ecc_domain.tld_private.key  \
--fullchain-file /path/to/ssl/ecc_domain.tld_chain.pem \
--capath         /path/to/ssl/ecc_domain.tld_ca.pem  \
--reloadcmd      "service nginx reload"

# 手动添加另一个 cron 任务
# crontab -e
50 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh"  --config-home "/root/.acme2" > /dev/null