前言
由于证书透明度日志的存在,在crt.sh等网站能够轻易查询到申请证书的子域名,造成子域名的暴露。
这种被动的子域名的暴露,存在潜在风险,也容易让有心的攻击者找到着力点。
而使用泛域名证书能够一定程度上规避这种风险。
作为轻量的个人用户,我使用Caddy来管理Web服务,而Caddy默认自动申请的是子域名证书,这代表着每一个申请证书的子域名,将永久的被暴露。
论坛内无Caddy申请泛域名证书的相关教程,故写此教程。
声明
测试的服务器为root用户,非root用户部分命令需添加sudo提权运行
本教程纯手敲,无AI
如有纰漏,请批评指正
前置
- [ ] 一台公网服务器/VPS
- [ ] 已使用/将使用Caddy作为Web服务器
- [ ] 一个已解析的域名,例如example.com,并确保你对该域名有控制权
Caddy安装DNS模块
Caddy本体默认不具备泛域名证书自动申请的能力。
泛域名证书的申请通常使用DNS-01验证,需要在域名的DNS设置中添加特定的TXT记录。而Caddy默认只支持HTTP质询和TLS-ALPN质询。
因此需要获取带有DNS模块的Caddy。
最简单的获取方法是访问caddyserver.com/download,选择对应的系统平台和模块,下载即可。
下载完成后可以获取到名称类似caddy_linux_amd64_custom的一个二进制可执行文件。
[!NOTE]
也可以使用xcaddy在本地进行编译,但需要安装Go,我嫌麻烦没使用这种方案。下面代码仅作参考
xcaddy build --with github.com/caddy-dns/cloudflare
将下载完成的caddy_linux_amd64_custom上传到目标服务器
先备份原来安装的Caddy,防止错误发生
mv /usr/bin/caddy /usr/bin/caddy.bak将刚才下载到的caddy_linux_amd64_custom替换过去
mv caddy_linux_amd64_custom /usr/bin/caddy给予执行权限
chmod +x /usr/bin/caddy重启Caddy
systemctl restart caddy查看模块是否成功安装
caddy list-modules | grep cloudflare此时应输出
dns.providers.cloudflare创建Cloudflare API令牌
前面提到,泛域名证书的申请通常使用DNS-01验证,需要在域名的DNS设置中添加特定的TXT记录。
因此要想使Caddy全自动申请,需要给它修改DNS记录的权限。
去到Cloudflare主页,点击右上角选择配置文件
来到API令牌页面,点击创建令牌,选择创建自定义令牌
按如下设置并继续
复制其中的令牌备用。
Caddyfile编辑
编辑Caddy的配置文件
nano /etc/caddy/Caddyfile在最上方指定ACME服务器
# 全局配置:指定 ACME 服务器(Let's Encrypt 生产环境,测试用 staging 地址){ acme_ca https://acme-v02.api.letsencrypt.org/directory # acme_ca https://acme-staging-v02.api.letsencrypt.org/directory # 测试环境(避免频繁申请触发限制):https://acme-staging-v02.api.letsencrypt.org/directory}在确保一切正确之前,建议先使用第二个ACME服务器,防止触发限制(限制时间累计上去还是很长的)。
添加泛域名的配置
*.yourdomain.com { tls { dns cloudflare xxxxxxxxxxxxxxxxx }}其中xxxxxxxxxxxxxxxxx即为上一节最后所复制的令牌。
这边也可以使用环境变量,更加安全
*.yourdomain.com { tls { dns cloudflare {env.CF_API_TOKEN} }}系统环境变量的添加这里不过多赘述。
之后添加的所有三级子域名就可以通用一个证书,要添加四级子域名的泛域名也是同理
*.test.yourdomain.com { tls { dns cloudflare xxxxxxxxxxxxxxxxx }}注意,不能使用*.*.yourdomain.com这种格式。
一个完整的配置文件示例
# The Caddyfile is an easy way to configure your Caddy web server.## Unless the file starts with a global options block, the first# uncommented line is always the address of your site.## To use your own domain name (with automatic HTTPS), first make# sure your domain's A/AAAA DNS records are properly pointed to# this machine's public IP, then replace ":80" below with your# domain name.# 全局配置:指定 ACME 服务器(Let's Encrypt 生产环境,测试用 staging 地址){ acme_ca https://acme-v02.api.letsencrypt.org/directory # acme_ca https://acme-staging-v02.api.letsencrypt.org/directory # 测试环境(避免频繁申请触发限制):https://acme-staging-v02.api.letsencrypt.org/directory}# 三级泛域名*.yourdomain.com { tls { dns cloudflare xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx }}# %%%%%%.yourdomain.com { header Strict-Transport-Security max-age=31536000; reverse_proxy https://127.0.0.1:10000 { header_up X-Real-IP {http.request.remote} header_up X-Forwarded-Port {http.request.port} transport http { tls_insecure_skip_verify } }}# %%%%%%.yourdomain.com { header Strict-Transport-Security max-age=31536000; reverse_proxy 127.0.0.1:10001}# %%%%%%.yourdomain.com { header Strict-Transport-Security max-age=31536000; reverse_proxy http://127.0.0.1:10002 log { output file /var/log/caddy/%%%.yourdomain.com.log }}# 四级泛域名*.%%%.yourdomain.com { tls { dns cloudflare xxxxxxxxxxxxxxxxxxxxxxxxxx }}# %%%%%%.%%%.yourdomain.com { root * /var/www/wordpress encode php_fastcgi unix//run/php/php-version-fpm.sock file_server}%%%.%%%.yourdomain.com { header Strict-Transport-Security max-age=31536000; reverse_proxy http://127.0.0.1:10004}# Refer to the Caddy docs for more information:# https://caddyserver.com/docs/caddyfile运行测试
编辑好Caddyfile文件保存好后,重启caddy
systemctl restart caddy查看caddy日志
journalctl -f -u caddy.service当出现如下日志时,说明证书申请成功
Dec 19 15:42:01 ser873368355349 caddy[1490187]: {"level":"info","ts":1766130121.0519037,"logger":"tls.obtain","msg":"certificate obtained successfully","identifier":"*.yourdomain.com","issuer":"acme-v02.api.letsencrypt.org-directory"}最后如果使用的是ACME测试服务器,记得换回去。
评论 (0)