适用范围:阿里云 ECS 主机已备案,域名解析正常,但 Certbot 在执行 HTTP-01 验证时仍返回 403 Forbidden。
目标:在保持现有架构不变的前提下,成功签发一张同时覆盖多个子域名的 Let’s Encrypt 证书。
说明:文中域名均为示例(如example.com、sub1.example.com等),与真实业务无关。
一、问题现象
执行命令:
certbot certonly --standalone \
-d example.com -d www.example.com -d sub1.example.com -d sub2.example.com \
--agree-tos -m user@example.com --cert-name example.com
输出提示:
Domain: example.com
Type: unauthorized
Detail: 203.0.113.10: Invalid response from http://example.com/.well-known/acme-challenge/xxx: 403
人工测试:
curl -I http://example.com/.well-known/acme-challenge/test
结果:
HTTP/1.1 403 Forbidden
Server: Beaver
Cache-Control: no-cache
Content-Type: text/html
Content-Length: 640
Connection: close
二、原因分析
1. “Server: Beaver” 的含义
- “Beaver” 是阿里云 HTTP 网关的返回头。
- 当流量未被 ECS 上的服务进程处理、而是被阿里云入口层接管时,就会出现这一标识。
- 触发原因可能包括:
- 请求被 WAF 或 安全代理层 拦截;
- HTTP 访问被平台策略或端口策略过滤;
- 请求路径或 Header 异常(例如
.well-known/acme-challenge被安全规则误判)。
2. 与备案无直接关系
- 即使域名已经完成工信部备案,只要触发了阿里云入口的安全规则或访问策略,也可能收到 Beaver 403;
- 因此需从访问链路和验证方式两方面排查。
三、验证思路
- 确认 80 端口可直连 ECS:
sudo ss -tlnp | grep ':80 ' curl -I http://<ECS公网IP>/若 IP 访问无返回或被防火墙拒绝,则说明 ECS 未监听 80 端口或端口策略阻断。 - 测试带 Host 头访问:
curl -I -H 'Host: example.com' http://<ECS公网IP>/- 若此命令仍返回 “Server: Beaver”,说明请求在进入 ECS 前即被网关拦截;
- 若能看到自建 Nginx/Apache 响应头,则表示可直接落地。
- 确认无外层安全策略干扰
- 检查阿里云控制台 > 安全组 > 入方向规则,确保 TCP 80 端口对 0.0.0.0/0 开放;
- 若使用了 WAF 或负载均衡,需在其规则中放行
/.well-known/acme-challenge/路径。
四、解决方案(按稳定性排序)
| 方案 | 是否改动架构 | 是否依赖 80 端口 | 难度 | 特点 |
|---|---|---|---|---|
| A. DNS-01 手动 TXT | ❌ 否 | ❌ 否 | ★☆☆ | 最安全稳妥,适用于所有环境 |
| B. DNS-01 自动化(AliDNS API) | ❌ 否 | ❌ 否 | ★★☆ | 可定时自动续签 |
| C. HTTP-01 验证(迁移到境外服务器) | ✅ 是 | ✅ 是 | ★★☆ | 临时解析到境外 VPS 执行验证 |
| D. 修正规则后继续 HTTP-01 | ✅ 是 | ✅ 是 | ★★★ | 需明确入口规则及 WAF 配置 |
五、推荐实践:DNS-01 手动 TXT 模式
1. 执行命令
sudo certbot certonly --manual --preferred-challenges dns \
-d example.com -d www.example.com -d sub1.example.com -d sub2.example.com \
--agree-tos -m user@example.com --cert-name example.com
Certbot 会依次提示添加 TXT 记录,例如:
Please deploy a DNS TXT record under the name:
_acme-challenge.sub1.example.com.
with the following value:
RANDOM_TOKEN_123456
2. 在阿里云 DNS 控制台添加 TXT 记录
| 字段 | 内容 | 说明 |
|---|---|---|
| 记录类型 | TXT | 必须选择 TXT |
| 主机记录 | _acme-challenge.sub1 | 对应提示中的子域 |
| 记录值 | RANDOM_TOKEN_123456 | 原样粘贴 |
| TTL | 600 | 默认即可 |
保留所有之前的 TXT 记录,直到 Certbot 全部验证完成。
3. 验证生效
dig TXT _acme-challenge.sub1.example.com +short
若能返回 Token 值,即可在 Certbot 窗口回车继续。
4. 完成签发
当所有域名验证通过后,输出如下:
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/example.com/privkey.pem
这些文件即为正式证书,可直接配置在 Nginx 或 Apache 中。
六、一次性覆盖所有子域的通配符方式
若希望减少交互次数,可使用通配符(Wildcard):
sudo certbot certonly --manual --preferred-challenges dns \
-d example.com -d '*.example.com' \
--agree-tos -m user@example.com --cert-name example.com
此时只需在 DNS 中为 _acme-challenge.example.com 添加两条 TXT 记录,即可覆盖所有当前与未来子域名。
七、关于续签
- 手动模式下 不会自动续签;
- 证书有效期 90 天,可在到期前重复同一命令与 TXT 步骤;
- 若需无人值守续签,可安装
certbot-dns-aliyun插件,并在 crontab 或 systemd timer 中执行:certbot renew
八、结论
- 问题根源:HTTP 请求被阿里云入口层拦截(返回 Server: Beaver),非 Certbot 或防火墙配置错误。
- 验证方式选择:DNS-01 绕过所有 HTTP 链路验证,是最稳妥的方案。
- 长期策略:
- 若不依赖阿里云 WAF ,可在安全组和 Nginx 层放行
.well-known/acme-challenge; - 若追求自动化,采用 AliDNS API 插件实现自动续签。
- 若不依赖阿里云 WAF ,可在安全组和 Nginx 层放行
命令速览
# 多域名证书(手动 DNS)
certbot certonly --manual --preferred-challenges dns \
-d example.com -d www.example.com -d sub1.example.com -d sub2.example.com \
--agree-tos -m user@example.com --cert-name example.com
# 通配符 + 根域
certbot certonly --manual --preferred-challenges dns \
-d example.com -d '*.example.com' \
--agree-tos -m user@example.com --cert-name example.com
# 查看证书状态
certbot certificates
总结
即便域名已备案,阿里云的 HTTP 安全网关仍可能对某些路径或验证请求返回 403 (Beaver)。通过切换到 DNS-01 验证方式,可以彻底绕开入口层限制,顺利获得包含多个子域名的 Let’s Encrypt 证书。