使用 Caddyfile 的 acme_server 指令创建自定义 ACME 服务器

Caddy 是一个功能强大且易于使用的 Web 服务器,以其简单的配置和内置的自动化 HTTPS 功能而闻名。Caddy 的一个独特功能是其 acme_server 指令,允许用户将 Caddy 配置为一个自定义的 ACME(Automatic Certificate Management Environment)服务器。本文将简要探讨 acme_server 指令,介绍其用途、配置方法、生成 CA 证书的过程以及实际应用场景。

什么是 ACME 服务器?

ACME 是一种协议,用于自动化域名所有权验证和 SSL/TLS 证书的颁发与管理。著名的 Let’s Encrypt 就是使用 ACME 协议的证书颁发机构(CA)。通过 Caddy 的 acme_server 指令,你可以将 Caddy 配置为一个自定义的 ACME 服务器,颁发自己的证书。这对于内部网络、测试环境或需要自定义证书管理的场景非常有用。

为什么使用 acme_server 指令?

Caddy 的 acme_server 指令允许你运行一个轻量级的 ACME 服务器,适用于以下场景:

  • 内部 CA:为私有网络或企业内部系统颁发证书。
  • 测试环境:在开发或测试环境中模拟 Let’s Encrypt 的行为。
  • 自定义证书管理:需要对证书颁发流程进行更多控制的场景。
  • 离线环境:在没有互联网连接的环境中颁发证书。

通过 acme_server,你无需依赖外部 CA,可以完全控制证书颁发的过程。

使用 OpenSSL 生成 CA 证书

在使用 acme_server 之前,你需要生成一个 CA 根证书和私钥,用于签署由 Caddy ACME 服务器颁发的证书。以下是使用 OpenSSL 生成 CA 证书的步骤:

步骤 1:生成 CA 私钥

运行以下命令生成一个 2048 位的 RSA 私钥:

openssl genrsa -out ca.key 2048

这将生成一个名为 ca.key 的私钥文件。确保妥善保管此文件,因为它是 CA 的核心安全组件。

步骤 2:生成 CA 根证书

使用以下命令创建自签名的 CA 根证书,有效期为 10 年(可根据需要调整):

openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.cert

在执行此命令时,你需要提供以下信息:

  • 国家代码(Country Name):例如,CN
  • 州或省(State or Province Name):例如,Beijing
  • 组织名称(Organization Name):例如,Your Company
  • 通用名称(Common Name, CN):例如,Your Internal CA

生成的 ca.cert 文件是你的 CA 根证书,客户端需要信任此证书以验证由你的 ACME 服务器颁发的证书。

步骤 3:验证生成的证书

你可以检查生成的证书内容以确保正确:

openssl x509 -in ca.cert -text -noout

这将显示证书的详细信息,例如颁发者、有效期和公钥。

步骤 4:保护 CA 文件

ca.keyca.cert 存储在安全的目录中,并确保 Caddy 有权限访问它们。例如:

chmod 600 ca.key
chown caddy:caddy ca.key ca.cert
mv ca.key ca.cert /etc/caddy/

配置 acme_server 指令

Caddy 的配置文件(Caddyfile)以其简洁而直观著称。下面是一个使用 acme_server 指令的基本配置示例,结合我们刚刚生成的 CA 证书:

{
  acme_server
  ca https://your-ca.example.com
  ca_key /etc/caddy/ca.key
  ca_cert /etc/caddy/ca.cert
}

基本配置说明

  • acme_server:启用 ACME 服务器功能。
  • ca:指定此 ACME 服务器的 CA 端点 URL。这将作为客户端查找证书颁发机构的入口。
  • ca_key:指定 CA 的私钥文件路径(例如,/etc/caddy/ca.key)。
  • ca_cert:指定 CA 的证书文件路径(例如,/etc/caddy/ca.cert)。

自定义存储路径

ACME 服务器需要存储颁发的证书和相关数据。可以通过 storage 指令指定存储路径:

{
  acme_server
  ca https://your-ca.example.com
  ca_key /etc/caddy/ca.key
  ca_cert /etc/caddy/ca.cert
  storage file:///var/lib/caddy/acme
}
  • storage:指定存储目录,Caddy 将在此保存 ACME 数据,如证书和账户信息。

启用特定挑战类型

ACME 协议支持多种域名验证挑战类型(如 HTTP-01、TLS-ALPN-01)。你可以通过 challenges 指令指定支持的挑战类型:

{
  acme_server
  ca https://your-ca.example.com
  ca_key /etc/caddy/ca.key
  ca_cert /etc/caddy/ca.cert
  storage file:///var/lib/caddy/acme
  challenges {
    http-01
    tls-alpn-01
  }
}
  • http-01:通过 HTTP 请求验证域名所有权。
  • tls-alpn-01:通过 TLS 协议验证域名所有权。

配置示例:完整 Caddyfile

以下是一个完整的 Caddyfile 示例,展示如何配置一个自定义 ACME 服务器:

{
  acme_server
  ca https://acme.example.com
  ca_key /etc/caddy/ca.key
  ca_cert /etc/caddy/ca.cert
  storage file:///var/lib/caddy/acme
  challenges {
    http-01
  }
}

acme.example.com {
  respond "ACME Server is running!"
}

在这个配置中:

  • Caddy 运行一个 ACME 服务器,监听 acme.example.com
  • 使用指定的 CA 证书和私钥(通过 OpenSSL 生成)颁发证书。
  • 数据存储在 /var/lib/caddy/acme 目录。
  • 仅支持 HTTP-01 挑战。
  • 根路径返回一个简单的响应,确认服务器正在运行。

使用自定义 ACME 服务器

配置好 Caddy 的 ACME 服务器后,你可以使用 ACME 客户端(如 certbot 或 Caddy 自身的 ACME 客户端)来请求证书。以下是使用 certbot 的示例:

certbot certonly \
  --server https://acme.example.com/acme/directory \
  --manual \
  --preferred-challenges http \
  -d your-domain.example.com
  • --server:指定你的 ACME 服务器的目录端点。
  • --manual:手动完成域名验证(适用于测试)。
  • --preferred-challenges:选择验证挑战类型。
  • -d:指定要颁发证书的域名。

如果你的 Caddy 服务器配置正确,certbot 将通过 HTTP-01 挑战验证域名,并从你的 Caddy ACME 服务器获取证书。

信任 CA 根证书

为了让客户端信任你的 ACME 服务器颁发的证书,你需要将 ca.cert 导入客户端的信任存储。例如,在 Linux 系统中:

sudo cp ca.cert /usr/local/share/ca-certificates/
sudo update-ca-certificates

在 Windows 或 macOS 上,可以使用系统提供的证书管理工具导入 ca.cert

实际应用场景

  1. 企业内部 CA
    大型组织可以使用 acme_server 为内部服务颁发证书,避免依赖外部 CA。结合内部 DNS,Caddy 可以为私有域名(如 *.internal.company.com)颁发证书。

  2. 开发和测试
    开发者可以使用 acme_server 在本地或测试环境中模拟 Let’s Encrypt,测试自动化证书颁发流程,而无需访问外部网络。

  3. 离线环境
    在没有互联网连接的环境中,acme_server 提供了一种在本地颁发和管理证书的解决方案。

  4. 自定义验证逻辑
    如果需要自定义域名验证逻辑(例如,通过 API 验证),可以结合 Caddy 的插件系统扩展 acme_server 的功能。

注意事项

  • 安全性:确保 CA 的私钥 (ca.key) 得到妥善保护,防止未经授权的访问。建议使用适当的文件权限和安全存储。
  • 证书信任:客户端需要信任你的 CA 根证书。如果是内部使用,需要将 CA 证书导入客户端的信任存储。
  • 性能:对于高负载场景,确保 Caddy 服务器有足够的资源来处理 ACME 请求。
  • 兼容性:测试你的 ACME 服务器与目标客户端的兼容性,确保支持所需的挑战类型。
  • 证书有效期:在生成 CA 证书时,合理设置有效期(例如,10 年),以减少频繁更换的需要。