Certbot SSL 证书管理 & Cloudflare API 验证 🔐
🌐 使用 Cloudflare DNS API 自动验证和续签 SSL 证书,无需开放服务器端口 - 安全、高效、自动化的证书管理解决方案
📋 目录
🎯 简介
Certbot 是由 EFF (Electronic Frontier Foundation) 开发的免费开源工具,用于自动化管理和部署 Let’s Encrypt SSL 证书。
🌟 Cloudflare API 验证的优势
- ✅ 无需开放端口:不需要开放 80/443 端口,增强服务器安全性
- ✅ 支持通配符:可以申请
*.example.com
通配符证书,保护所有子域名
- ✅ 完全自动化:支持无人值守自动续签,减少人工干预
- ✅ 安全可靠:使用 API Token 而非全局密钥,遵循最小权限原则
- ✅ DNS 验证:通过 DNS TXT 记录验证域名所有权,适用于各种服务器环境
- ✅ 多域名支持:单张证书可包含多个域名和通配符
🔗 相关链接
📦 安装配置
🐧 安装 Certbot 和 Cloudflare 插件
Ubuntu/Debian 系统
1
2
3
4
5
6
7
8
9
|
# 更新系统包列表
sudo apt update
# 安装 Certbot 和 Cloudflare DNS 插件
sudo apt install -y certbot python3-certbot-dns-cloudflare
# 验证安装
certbot --version
python3 -c "import certbot_dns_cloudflare; print('✅ Cloudflare plugin installed')"
|
CentOS/RHEL 系统
1
2
3
4
5
6
7
8
9
10
11
|
# 启用 EPEL 仓库
sudo yum install -y epel-release
# 或者对于 CentOS 8/RHEL 8
sudo dnf install -y epel-release
# 安装 Certbot 和 Cloudflare DNS 插件
sudo yum install -y certbot python3-certbot-dns-cloudflare
# 或者使用 pip 安装
sudo pip3 install certbot certbot-dns-cloudflare
|
使用 Snap 安装(推荐)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
# 安装 Snap
sudo apt install -y snapd
# 确保 Snap 是最新的
sudo snap install core
sudo snap refresh core
# 安装 Certbot
sudo snap install --classic certbot
# 创建符号链接
sudo ln -s /snap/bin/certbot /usr/bin/certbot
# 安装 Cloudflare DNS 插件
sudo snap set certbot trust-plugin-with-root=ok
sudo snap install certbot-dns-cloudflare
# 验证安装
certbot --version
|
📁 创建配置目录
1
2
3
4
5
6
7
|
# 创建配置目录
sudo mkdir -p /etc/letsencrypt
sudo chmod 700 /etc/letsencrypt
# 创建日志目录
sudo mkdir -p /var/log/letsencrypt
sudo chmod 755 /var/log/letsencrypt
|
🔑 Cloudflare API 设置
🎯 获取 Cloudflare API Token
- 登录 Cloudflare 控制台:
https://dash.cloudflare.com/
- 进入 API Tokens: 点击右上角用户图标 → My Profile → API Tokens
- 创建 Token: 点击 “Create Token” → 使用 “Edit zone DNS” 模板
- 配置权限:
- 权限: Zone - DNS - Edit
- 资源: Include - All zones (或指定特定域名)
- 创建并保存 Token: 复制生成的 API Token
📝 创建配置文件
1
2
3
4
5
6
7
8
9
10
11
12
|
# 创建 Cloudflare 配置文件
sudo tee /etc/letsencrypt/cloudflare.ini > /dev/null <<'EOF'
# Cloudflare API credentials used by Certbot
dns_cloudflare_api_token = YOUR_API_TOKEN_HERE
EOF
# 设置严格权限
sudo chmod 600 /etc/letsencrypt/cloudflare.ini
sudo chown root:root /etc/letsencrypt/cloudflare.ini
# 验证配置文件
sudo cat /etc/letsencrypt/cloudflare.ini
|
⚠️ 重要:
- 使用 API Token 时只需配置
dns_cloudflare_api_token
,不需要 dns_cloudflare_api_key
和 dns_cloudflare_email
- 将
YOUR_API_TOKEN_HERE
替换为实际的 API Token
- 确保配置文件权限为 600,防止其他用户读取
📝 证书申请
🚀 申请通配符证书
1
2
3
4
5
6
7
8
9
10
11
|
# 申请通配符证书
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
--dns-cloudflare-propagation-seconds 60 \
--preferred-challenges dns-01 \
-d "example.com" \
-d "*.example.com" \
--register-unsafely-without-email \
--agree-tos \
--non-interactive
|
📋 参数说明
--dns-cloudflare
: 使用 Cloudflare DNS 验证
--dns-cloudflare-credentials
: 指定凭证文件路径
--dns-cloudflare-propagation-seconds 60
: 等待 DNS 传播的时间(秒)
--preferred-challenges dns-01
: 优先使用 DNS 挑战验证
-d
: 指定域名(支持多个域名)
--register-unsafely-without-email
: 不提供邮箱(可选)
--agree-tos
: 同意服务条款
--non-interactive
: 非交互模式,适合脚本运行
🎯 申请多域名证书
1
2
3
4
5
6
7
8
9
10
|
# 申请包含多个域名的证书
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
-d "example.com" \
-d "www.example.com" \
-d "api.example.com" \
-d "*.staging.example.com" \
--register-unsafely-without-email \
--agree-tos
|
✅ 验证申请结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# 查看证书信息
sudo certbot certificates
# 检查证书文件
sudo ls -la /etc/letsencrypt/live/example.com/
# 验证证书内容
sudo openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -text -noout | head -20
# 检查证书有效期
sudo openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -noout -dates
# 验证证书链
sudo openssl verify -CAfile /etc/letsencrypt/live/example.com/chain.pem /etc/letsencrypt/live/example.com/cert.pem
|
⚡ 自动续签
🕐 计划任务配置
方法一:简单续签命令
1
2
3
4
5
6
7
8
9
|
# 编辑 crontab
sudo crontab -e
# 添加以下内容:
# 每天凌晨 2:30 自动续签(如果证书30天内过期)
30 2 * * * /usr/bin/certbot renew --quiet --renew-hook "systemctl reload nginx"
# 或者使用绝对路径
30 2 * * * /usr/bin/certbot renew --quiet --renew-hook "/bin/systemctl reload nginx"
|
方法二:智能续签脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
# 创建智能续签脚本
sudo tee /usr/local/bin/certbot-renew-smart.sh > /dev/null <<'EOF'
#!/bin/bash
# 智能证书续签脚本
DOMAIN="example.com"
LOG_FILE="/var/log/certbot-renew.log"
CONFIG_FILE="/etc/letsencrypt/cloudflare.ini"
NGINX_CONFIG="/etc/nginx/sites-available/default"
echo "$(date): 开始证书续签检查" >> $LOG_FILE
# 检查证书是否存在
if [ ! -f "/etc/letsencrypt/live/$DOMAIN/cert.pem" ]; then
echo "错误: 证书文件不存在" >> $LOG_FILE
exit 1
fi
# 检查证书有效期
EXPIRY_DAYS=$(sudo certbot certificates | grep -A 3 "$DOMAIN" | grep "EXPIRY" | awk '{print $6}' | cut -d')' -f1)
if [ -z "$EXPIRY_DAYS" ] || [ "$EXPIRY_DAYS" -le 10 ]; then
echo "证书即将过期(剩余 ${EXPIRY_DAYS:-未知} 天),尝试续签..." >> $LOG_FILE
# 执行续签
if sudo certbot renew --dns-cloudflare --dns-cloudflare-credentials $CONFIG_FILE --force-renewal; then
echo "证书续签成功" >> $LOG_FILE
# 检查 Nginx 配置语法
if sudo nginx -t; then
# 重载 Nginx
sudo systemctl reload nginx
echo "Nginx 配置已重载" >> $LOG_FILE
else
echo "错误: Nginx 配置测试失败" >> $LOG_FILE
fi
else
echo "证书续签失败" >> $LOG_FILE
exit 1
fi
else
echo "证书有效期剩余 ${EXPIRY_DAYS} 天,无需续签" >> $LOG_FILE
fi
echo "$(date): 证书检查完成" >> $LOG_FILE
EOF
# 设置脚本权限
sudo chmod +x /usr/local/bin/certbot-renew-smart.sh
sudo chown root:root /usr/local/bin/certbot-renew-smart.sh
|
📅 添加计划任务
1
2
3
4
5
6
7
8
|
# 编辑 root 的 crontab
sudo crontab -e
# 添加智能续签任务(每天凌晨3点执行)
0 3 * * * /usr/local/bin/certbot-renew-smart.sh >> /var/log/certbot-renew.log 2>&1
# 添加日志清理任务(每月清理一次旧日志)
0 2 1 * * find /var/log -name "certbot*.log" -mtime +30 -delete
|
🔔 续签通知配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
# 添加邮件通知功能到续签脚本
sudo tee -a /usr/local/bin/certbot-renew-smart.sh > /dev/null <<'EOF'
# 发送通知函数
send_notification() {
local subject="$1"
local message="$2"
# 使用 mail 命令发送邮件
echo "$message" | mail -s "$subject" admin@example.com
# 或者使用其他通知方式(如 Slack、Telegram 等)
}
# 在适当位置添加通知
if [ $? -eq 0 ]; then
send_notification "证书续签成功" "域名 $DOMAIN 的 SSL 证书已成功续签。"
else
send_notification "证书续签失败" "域名 $DOMAIN 的 SSL 证书续签失败,请检查日志。"
fi
EOF
|
🔧 维护管理
📋 常用管理命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
# 查看所有证书
sudo certbot certificates
# 检查证书有效期
sudo openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -noout -dates
# 测试续签(不实际执行)
sudo certbot renew --dry-run
# 强制续签特定证书
sudo certbot renew --cert-name example.com --force-renewal
# 查看 Certbot 日志
sudo tail -f /var/log/letsencrypt/letsencrypt.log
# 查看证书详细信息
sudo certbot show --cert-name example.com
|
🔄 手动同步证书到 Web 服务器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
# 同步证书到 Nginx
sudo cp -f /etc/letsencrypt/live/example.com/fullchain.pem /etc/nginx/ssl/example.com.crt
sudo cp -f /etc/letsencrypt/live/example.com/privkey.pem /etc/nginx/ssl/example.com.key
# 设置正确权限
sudo chmod 644 /etc/nginx/ssl/example.com.crt
sudo chmod 600 /etc/nginx/ssl/example.com.key
sudo chown www-data:www-data /etc/nginx/ssl/example.com.*
# 测试 Nginx 配置
sudo nginx -t
# 重载 Nginx
sudo systemctl reload nginx
# 对于 Apache
sudo cp -f /etc/letsencrypt/live/example.com/fullchain.pem /etc/ssl/certs/example.com.crt
sudo cp -f /etc/letsencrypt/live/example.com/privkey.pem /etc/ssl/private/example.com.key
sudo systemctl reload apache2
|
🗑️ 撤销和删除证书
1
2
3
4
5
6
7
8
9
10
|
# 撤销证书
sudo certbot revoke --cert-path /etc/letsencrypt/live/example.com/cert.pem --reason superseded
# 删除证书配置
sudo certbot delete --cert-name example.com
# 手动删除证书文件
sudo rm -rf /etc/letsencrypt/archive/example.com
sudo rm -rf /etc/letsencrypt/live/example.com
sudo rm -rf /etc/letsencrypt/renewal/example.com.conf
|
🔍 故障排除命令
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# 检查 DNS 解析
dig TXT _acme-challenge.example.com
# 调试模式运行 Certbot
sudo certbot --debug --verbose certonly --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini -d example.com
# 检查 Cloudflare API 连接
curl -X GET "https://api.cloudflare.com/client/v4/zones" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json"
# 检查证书透明度日志
curl "https://crt.sh/?q=example.com&output=json" | jq .
|
🗑️ 完全卸载
🔄 卸载 Certbot
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
# 停止所有 Certbot 相关进程
sudo systemctl stop certbot.timer
sudo systemctl disable certbot.timer
# 卸载软件包(APT)
sudo apt remove --purge -y certbot python3-certbot-dns-cloudflare
# 卸载软件包(Snap)
sudo snap remove certbot certbot-dns-cloudflare
sudo rm -f /usr/bin/certbot
# 清理配置文件
sudo rm -rf /etc/letsencrypt/
sudo rm -rf /var/lib/letsencrypt/
sudo rm -rf /var/log/letsencrypt/
# 清理 Cron 任务
sudo crontab -l | grep -v certbot | sudo crontab -
# 删除脚本文件
sudo rm -f /usr/local/bin/certbot-renew-smart.sh
# 清理残留包
sudo apt autoremove -y
sudo apt clean
|
📊 验证卸载
1
2
3
4
5
6
7
|
# 检查是否完全卸载
which certbot || echo "✅ Certbot 已卸载"
ls /etc/letsencrypt 2>/dev/null || echo "✅ 配置目录已清理"
ps aux | grep certbot | grep -v grep || echo "✅ 无 Certbot 进程"
# 检查已安装的 Python 模块
python3 -c "import certbot_dns_cloudflare" 2>/dev/null && echo "❌ Cloudflare 插件仍在" || echo "✅ Cloudflare 插件已移除"
|
💡 最佳实践
🛡️ 安全建议
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# 定期轮换 API Token(每3-6个月)
# 为每个域名创建单独的 API Token,遵循最小权限原则
# 使用强权限保护密钥文件
sudo chmod 600 /etc/letsencrypt/cloudflare.ini
sudo chmod 700 /etc/letsencrypt/live/
sudo chmod 755 /etc/letsencrypt/archive/
# 定期备份证书和配置
sudo tar -czvf /backup/letsencrypt-backup-$(date +%Y%m%d).tar.gz /etc/letsencrypt/
# 监控证书目录的更改
sudo apt install -y auditd
sudo auditctl -w /etc/letsencrypt/ -p wa -k letsencrypt
|
📊 监控和告警
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
# 证书过期监控脚本
#!/bin/bash
DOMAIN="example.com"
WARNING_DAYS=14
ADMIN_EMAIL="admin@example.com"
EXPIRY_DATE=$(sudo openssl x509 -in /etc/letsencrypt/live/$DOMAIN/cert.pem -enddate -noout | cut -d= -f2)
EXPIRY_TS=$(date -d "$EXPIRY_DATE" +%s)
CURRENT_TS=$(date +%s)
DAYS_LEFT=$(( (EXPIRY_TS - CURRENT_TS) / 86400 ))
if [ $DAYS_LEFT -le $WARNING_DAYS ]; then
SUBJECT="SSL 证书过期警告: $DOMAIN"
MESSAGE="域名 $DOMAIN 的 SSL 证书将在 $DAYS_LEFT 天后过期($EXPIRY_DATE)。请及时续签。"
echo "$MESSAGE" | mail -s "$SUBJECT" "$ADMIN_EMAIL"
# 可选: 发送到 Slack 或其它通知系统
# curl -X POST -H 'Content-type: application/json' \
# --data "{\"text\":\"$MESSAGE\"}" \
# https://hooks.slack.com/services/XXX/XXX/XXX
fi
|
🔧 高级故障排除技巧
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# 检查 Let's Encrypt 速率限制
# 访问: https://letsencrypt.org/docs/rate-limits/
# 使用暂存环境测试
sudo certbot certonly --test-cert --dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
-d example.com
# 检查证书透明度日志
curl -s "https://crt.sh/?q=example.com&output=json" | jq -r '.[] | select(.name_value | contains("example.com")) | .not_after' | head -1
# 手动添加 DNS 记录进行验证
# 获取需要添加的 TXT 记录
sudo certbot certonly --manual --preferred-challenges dns -d example.com --dry-run
|
📝 更新和维护
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# 定期更新 Certbot
sudo apt update && sudo apt upgrade certbot python3-certbot-dns-cloudflare
# 或者使用 Snap 更新
sudo snap refresh certbot
# 检查插件兼容性
python3 -c "import pkg_resources; print('Cloudflare plugin version:', pkg_resources.get_distribution('certbot-dns-cloudflare').version)"
# 验证配置语法
sudo certbot renew --dry-run --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini
# 检查系统日志中的 Certbot 相关错误
sudo journalctl -u certbot | tail -50
|
🌐 多服务器证书同步
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# 使用 rsync 同步证书到多个服务器
#!/bin/bash
SERVERS=("server1.example.com" "server2.example.com")
DOMAIN="example.com"
for SERVER in "${SERVERS[@]}"; do
echo "同步证书到 $SERVER..."
rsync -avz -e "ssh -p 22" \
/etc/letsencrypt/live/$DOMAIN/ \
user@$SERVER:/etc/letsencrypt/live/$DOMAIN/
ssh user@$SERVER "sudo systemctl reload nginx"
done
|
🎯 提示: 建议在生产环境部署前,先在测试环境验证所有配置。定期检查日志和证书状态,确保自动化流程正常运行。
📚 扩展阅读:
🔧 紧急恢复:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# 如果自动续签失败,手动执行
sudo /usr/local/bin/certbot-renew-smart.sh
# 检查 Nginx 配置
sudo nginx -t
# 临时恢复旧证书(如果有备份)
sudo cp -rf /backup/letsencrypt-backup/live/example.com/ /etc/letsencrypt/live/
sudo systemctl reload nginx
# 紧急情况下申请新证书
sudo certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
-d example.com --force-renewal
|
💡 专业建议:
- 使用证书监控服务如
SSL Labs
定期检查证书配置
- 实施证书钉扎 (Certificate Pinning) 增强安全性
- 考虑使用双向 TLS (mTLS) 对于内部服务
- 定期进行安全审计和渗透测试
希望本指南能帮助您顺利使用 Certbot 和 Cloudflare API 管理 SSL 证书!🔐