泛域名 SSL 证书如何申请|多个子域名共用证书(详细操作教程)

发布时间:2026-07-23 11:12

当你拥有一个主域名(例如 example.com),并希望旗下的所有子域名(如 blog.example.com、shop.example.com、mail.example.com)都能使用 HTTPS 加密访问时,最经济高效的方案就是申请一张 **泛域名 SSL 证书**(也叫通配符证书)。这种证书的通用名称格式为 `*.example.com`,可以保护主域名以及所有一级子域名。下面是一份完整的实操教程,从零开始带你完成申请和部署。

---

### 前言介绍

在传统方案中,如果你有 10 个子域名,就需要申请 10 张独立的 SSL 证书,管理起来非常繁琐,而且容易遗漏导致部分站点出现安全警告。泛域名证书完美解决了这个问题:一张证书覆盖所有子域名,新增子域名时无需重新申请,只要将证书复制到新服务器即可。目前主流的证书颁发机构(CA)都支持泛域名证书,包括免费版的 Let‘s Encrypt 和付费的商业证书。本教程将以 **Let’s Encrypt** 免费泛域名证书为例,使用 **acme.sh** 工具配合 **DNS API 验证** 来完成申请,因为泛域名证书无法通过简单的 HTTP 文件验证来签发,必须使用 DNS 验证来证明你对域名的所有权。

---

### 前置准备

在开始操作之前,请确保你具备以下条件:

1. **一个已注册的域名**:例如 `example.com`,并且你拥有该域名的 DNS 管理权限(可以添加、删除 TXT 记录)。

2. **一台 Linux 服务器**:可以是 CentOS 7/8、Ubuntu 20.04/22.04 或 Debian 11/12。本教程使用 Ubuntu 22.04 演示。

3. **服务器已安装 curl 和 socat**:acme.sh 依赖这两个工具。如果未安装,请先执行:

```bash

sudo apt update && sudo apt install curl socat -y

```

4. **域名 DNS 服务商 API 密钥**:因为需要自动添加 DNS TXT 记录来完成验证,你需要从你的 DNS 服务商(如阿里云、腾讯云、Cloudflare、华为云等)获取 API 访问密钥。本教程以 **Cloudflare** 为例(全球使用广泛,API 配置简单)。如果你使用其他服务商,原理完全一致,只需替换对应的 API 调用参数。

---

### 分步操作步骤

#### 步骤 1:安装 acme.sh 工具

acme.sh 是一个纯 Shell 脚本的 ACME 客户端,支持自动申请、续期和部署 Let’s Encrypt 证书。登录你的服务器,执行以下命令安装:

```bash

curl https://get.acme.sh | sh -s email=你的邮箱@example.com

```

安装完成后,脚本会自动将 acme.sh 的路径加入系统环境变量,并创建一个定时任务用于自动续期。你可以通过以下命令验证安装是否成功:

```bash

acme.sh --version

```

如果显示版本号(例如 v3.0.7),说明安装成功。如果提示命令未找到,请执行 `source ~/.bashrc` 或重新登录 SSH。

#### 步骤 2:配置 DNS 服务商 API 密钥

为了让 acme.sh 能够自动在你的 DNS 管理后台添加和删除 TXT 记录,需要将 API 密钥配置为环境变量。以 Cloudflare 为例,你需要准备:

- **Global API Key**:在 Cloudflare 仪表盘 -> 我的个人资料 -> API 令牌 中获取。

- **登录邮箱**:你的 Cloudflare 账户邮箱。

在服务器终端中设置环境变量(将 `your_email@example.com` 和 `your_global_api_key` 替换为真实值):

```bash

export CF_Email="your_email@example.com"

export CF_Key="your_global_api_key"

```

**注意**:如果你使用阿里云,需要设置 `Ali_Key` 和 `Ali_Secret`;腾讯云设置 `DP_Id` 和 `DP_Key`。具体变量名请查阅 acme.sh 的 DNS API 文档。

#### 步骤 3:申请泛域名证书

执行以下命令签发证书,将 `example.com` 替换为你的真实域名:

```bash

acme.sh --issue --dns dns_cf -d example.com -d "*.example.com"

```

参数解释:

- `--issue`:发起证书申请。

- `--dns dns_cf`:指定使用 DNS 验证方式,`dns_cf` 代表 Cloudflare。如果你用阿里云,这里写 `dns_ali`;腾讯云写 `dns_dp`。

- `-d example.com`:覆盖主域名本身。

- `-d "*.example.com"`:覆盖所有一级子域名。**注意:星号和点号必须用双引号包裹**,防止 Shell 解析错误。

执行后,acme.sh 会自动调用 Cloudflare API 添加一个 `_acme-challenge.example.com` 的 TXT 记录,等待 DNS 生效(通常几秒到几分钟),然后向 Let’s Encrypt 验证。验证通过后,证书和私钥文件会生成在 `~/.acme.sh/example.com/` 目录下。

如果过程中出现错误,常见原因是 API 密钥权限不足或域名 DNS 服务器未指向 Cloudflare。请检查 API 密钥是否拥有“编辑 DNS”权限。

#### 步骤 4:安装证书到指定目录

生成的证书文件默认在 acme.sh 的隐藏目录中,但实际使用(如配置 Nginx)时,需要将证书和私钥复制到常用路径,例如 `/etc/nginx/ssl/`。执行以下命令:

```bash

acme.sh --install-cert -d example.com \

--key-file /etc/nginx/ssl/example.com.key \

--fullchain-file /etc/nginx/ssl/example.com.crt \

--reloadcmd "systemctl reload nginx"

```

参数说明:

- `--install-cert`:安装证书。

- `-d example.com`:指定要安装的域名(泛域名证书的主域名)。

- `--key-file`:私钥文件输出路径。

- `--fullchain-file`:包含完整证书链的证书文件输出路径(推荐使用这个,而不是单独的 cert.pem)。

- `--reloadcmd`:证书安装或续期后自动执行的命令。这里让 Nginx 重新加载配置,使新证书生效。

请确保目标目录 `/etc/nginx/ssl/` 已存在,如果不存在,先执行 `sudo mkdir -p /etc/nginx/ssl`。

#### 步骤 5:配置 Nginx 使用泛域名证书

假设你的子域名 `blog.example.com` 和 `shop.example.com` 都指向这台服务器,你可以在 Nginx 配置中统一使用这张证书。编辑 Nginx 的虚拟主机配置文件(例如 `/etc/nginx/sites-available/example.com.conf`),写入以下内容:

```nginx

server {

listen 443 ssl http2;

server_name example.com *.example.com; # 匹配主域名和所有子域名

ssl_certificate /etc/nginx/ssl/example.com.crt;

ssl_certificate_key /etc/nginx/ssl/example.com.key;

# 其他 SSL 配置(建议启用)

ssl_protocols TLSv1.2 TLSv1.3;

ssl_ciphers HIGH:!aNULL:!MD5;

location / {

root /var/www/html;

index index.html;

}

}

# 可选:将 HTTP 请求重定向到 HTTPS

server {

listen 80;

server_name example.com *.example.com;

return 301 https://$host$request_uri;

}

```

配置完成后,测试 Nginx 配置是否正确:

```bash

sudo nginx -t

```

如果显示 `syntax is ok` 和 `test is successful`,则重新加载 Nginx:

```bash

sudo systemctl reload nginx

```

现在,你可以分别访问 `https://example.com`、`https://blog.example.com`、`https://shop.example.com`,浏览器地址栏应该都会显示安全锁图标。

#### 步骤 6:验证证书自动续期

Let’s Encrypt 证书有效期为 90 天。acme.sh 在安装时已经自动添加了定时任务(cron job)。你可以通过以下命令查看定时任务是否生效:

```bash

crontab -l

```

你会看到类似这样的行:

```

56 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

```

这表示每天凌晨 0:56 检查证书是否需要续期。如果需要手动测试续期流程,可以执行:

```bash

acme.sh --cron

```

该命令会检查所有已安装的证书,如果距离过期不足 30 天,会自动重新申请并执行你在 `--reloadcmd` 中指定的命令(例如重载 Nginx)。

---

### 常见问题

**Q1:申请时提示“DNS 验证失败”怎么办?**

A:最常见的原因是 DNS 记录未生效。你可以在申请前,手动添加一条 `_acme-challenge.example.com` 的 TXT 记录,值为随机字符串,然后使用 `dig _acme-challenge.example.com txt` 命令查看是否解析成功。另外,请确认你的 API 密钥是否有“编辑 DNS”权限,以及域名是否使用了 Cloudflare 的 DNS 服务器(而非仅开启 CDN 代理)。

**Q2:泛域名证书可以保护二级子域名吗?**

A:不能。`*.example.com` 只能保护 **一级子域名**(如 `blog.example.com`),无法保护 `sub.blog.example.com`(二级子域名)。如果需要保护多级子域名,需要申请 `*.blog.example.com` 或使用多域名证书(SAN 证书)手动添加每个二级域名。

**Q3:证书安装后,浏览器提示“证书无效”或“不安全”**

A:请检查 Nginx 配置中 `ssl_certificate` 是否指向了 `fullchain` 文件(包含完整证书链),而不是只包含服务器证书的 `cert.pem`。另外,确认 `server_name` 中是否包含了访问时使用的具体子域名。如果子域名未在 `server_name` 中列出,Nginx 可能匹配到其他没有证书的 server 块。

**Q4:我使用了其他 DNS 服务商,如何修改?**

A:acme.sh 支持超过 60 种 DNS 服务商。你只需要在 `--dns` 参数后指定对应的标识符(如 `dns_ali` 阿里云、`dns_dp` 腾讯云、`dns_aws` AWS Route53),并在申请前设置对应的环境变量。具体变量名请参考 acme.sh 官方文档的“DNS API”部分。

**Q5:证书到期后会自动续期吗?**

A:是的,acme.sh 的定时任务会自动检查并续期。但请确保你的 DNS API 密钥长期有效。如果更换了 API 密钥,需要重新设置环境变量并执行一次 `acme.sh --cron` 来更新凭证。

---

### 收尾总结

通过本教程,你成功使用 acme.sh 和 Let’s Encrypt 申请了一张免费的泛域名 SSL 证书,并配置 Nginx 使其保护主域名和所有一级子域名。核心流程可以总结为三步:安装 acme.sh -> 配置 DNS API 密钥 -> 签发并安装证书。整个过程无需人工干预 DNS 记录,完全自动化。后续当你新增一个子域名(如 `api.example.com`)时,无需重新申请证书,只需将 Nginx 配置的 `server_name` 加入新域名,并确保该域名解析到本服务器即可。泛域名证书不仅节省了管理成本,也避免了因证书遗漏导致的安全警告,是管理多子域名站点的最佳实践。