# Verify error：acme.sh 域名验证失败的原因和修法

> acme.sh 输出 Verify error 表示 CA 验证域名失败。冒号后面的内容（404、403、超时、NXDOMAIN、TXT 不对）说明是 HTTP-01 还是 DNS-01 的哪一环出了问题。

Source: https://ssl.sh/zh/errors/acme-sh-verify-error/
Last updated: 2026-11-10

**`Verify error` 的意思是：CA 去验证你的域名，失败了；acme.sh 只是把 CA 的解释原样打印在冒号后面。** 关键看这段解释：HTTP 状态码（404、403）、超时、`NXDOMAIN`、`Incorrect TXT record`，各自对应不同的修法。

## 快速修复

定位问题最快的办法是在测试环境加调试参数重跑一次，失败不占正式额度：

```bash
acme.sh --issue -d example.com -w /var/www/html --staging --debug 2
```

再按冒号后面的内容查对应原因：

| `Verify error:` 后面的内容 | 最可能的原因 | 看第几节 |
|---|---|---|
| `Invalid response ...: 404` | 网站目录或 server 块不对 | 1 |
| `Invalid response ...: 403` | 拒绝规则、WAF、权限 | 2 |
| `Timeout during connect`、`Connection refused` | 80 端口不通、IP 不对 | 3 |
| `Incorrect TXT record`、`NXDOMAIN looking up TXT` | DNS-01 记录查不到 | 4 |
| `CAA record ... prevents issuance` | CAA 没允许该 CA | 5 |

staging 上成功后，去掉 `--staging`，加一次 `--force` 正式签发。

## 原因

Verify error 有 5 类原因：HTTP-01 的 404、403 和连接问题，DNS-01 记录查不到，以及 CAA 等 CA 端拒绝。最常见的是网站目录不对导致的 404。

### 1. HTTP-01 网站目录不对（404）

acme.sh 把验证文件写到 `<网站目录>/.well-known/acme-challenge/`。如果 Web 服务器给这个域名用的是另一个目录，CA 就会拿到 404。

- **确认：** `echo ok > /var/www/html/.well-known/acme-challenge/t` 后，`curl http://example.com/.well-known/acme-challenge/t` 返回 404。
- **修复：** `-w` 改成该 server 块实际使用的 `root`（用 `nginx -T | grep root` 查）；或者改用 `--nginx` / `--apache` 模式，让 acme.sh 临时改配置。反向代理站点要加一个 `location`，让验证目录在本机直接返回。宝塔站点的根目录一般是 `/www/wwwroot/<域名>`。

### 2. 被拒绝访问（403）

- **修复：** 在禁止点开头文件的规则和 WAF 规则之前，给 `/.well-known/acme-challenge/` 加例外，做法和 [Certbot 403 unauthorized](https://ssl.sh/zh/errors/certbot-unauthorized-403/) 完全一样。

### 3. 连接问题

- **修复：** 每一层防火墙（云安全组、系统防火墙、宝塔防火墙）都放行 TCP 80，删掉残留的 AAAA 记录，关闭“禁止海外访问”之类的地域屏蔽，见 [Timeout during connect](https://ssl.sh/zh/errors/certbot-timeout-during-connect/)。`--standalone` 模式需要 80 端口空闲，提示缺少 `socat` 时先安装它。

### 4. DNS-01 记录查不到

DNS API 把记录写到了错误的区域、API 密钥权限不够，或者 CA 在所有权威服务器同步前就开始验证。

- **确认：** 运行过程中用 `dig +short TXT _acme-challenge.example.com @权威服务器` 查不到，或者查到的是旧值。
- **修复：** 检查 API 环境变量（DNSPod 用 `DP_Id`/`DP_Key`，阿里云解析用 `Ali_Key`/`Ali_Secret`，Cloudflare 用 `CF_Token`），确认域名的 NS 确实指向这家服务商；同步慢就加 `--dnssleep 120`。用 CNAME 委托验证时加 `--challenge-alias`。阿里云 RAM 子账号要授予云解析的管理权限。

### 5. CAA 等 CA 端拒绝

- **修复：** 在 CAA 里加上 CA 的标识，比如 `letsencrypt.org`，ZeroSSL 以其官方文档给出的为准；见 [CAA record prevents issuance](https://ssl.sh/zh/errors/caa-record-prevents-issuance/)。

## 各环境修法

各环境的共同原则：acme.sh 数据目录要持久保存，证书用 `--install-cert` 部署，同一个域名只交给一个客户端签发。

**切换 CA：**

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

**安装证书**（让续期后的证书自动部署到 Web 服务器）：

```bash
acme.sh --install-cert -d example.com \
  --key-file /etc/nginx/ssl/example.com.key \
  --fullchain-file /etc/nginx/ssl/example.com.pem \
  --reloadcmd "systemctl reload nginx"
```

**Docker（`neilpang/acme.sh` 镜像）：** 把 `/acme.sh` 数据目录挂成卷，账户和证书才能在重启后保留；否则每次运行都是新订单，容易触发[速率限制](https://ssl.sh/zh/errors/lets-encrypt-rate-limit/)。

**通配符证书：** 必须用 DNS-01（如 `--dns dns_dp`、`--dns dns_ali`），HTTP-01 无法验证 `*.example.com`。

**升级：** 老版本遇到 CA 接口变化会出各种错，先 `acme.sh --upgrade`。

**宝塔面板：** 宝塔的证书申请底层也是 ACME 客户端，面板里看到的“验证失败”提示和 Verify error 的后半句含义相同。面板申请和命令行 acme.sh 不要同时给同一个域名签发，否则两边互相覆盖证书文件，续期时间也会错乱。

## 不要这样做

下面 3 种做法会耗光签发额度、泄露密钥，或者让服务器失去防护。

- **在定时任务里保留 `--force`。** 每次都不管是否快到期就续，额度很快耗光。
- **把 `--debug` 日志原样贴到论坛、群里。** 里面有 API 密钥和账户地址。
- **为了验证通过把防火墙或 WAF 全关掉。** 只放行验证路径，或者改用 DNS-01。
