使用 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.key
和 ca.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
。
实际应用场景
-
企业内部 CA:
大型组织可以使用acme_server
为内部服务颁发证书,避免依赖外部 CA。结合内部 DNS,Caddy 可以为私有域名(如*.internal.company.com
)颁发证书。 -
开发和测试:
开发者可以使用acme_server
在本地或测试环境中模拟 Let’s Encrypt,测试自动化证书颁发流程,而无需访问外部网络。 -
离线环境:
在没有互联网连接的环境中,acme_server
提供了一种在本地颁发和管理证书的解决方案。 -
自定义验证逻辑:
如果需要自定义域名验证逻辑(例如,通过 API 验证),可以结合 Caddy 的插件系统扩展acme_server
的功能。
注意事项
- 安全性:确保 CA 的私钥 (
ca.key
) 得到妥善保护,防止未经授权的访问。建议使用适当的文件权限和安全存储。 - 证书信任:客户端需要信任你的 CA 根证书。如果是内部使用,需要将 CA 证书导入客户端的信任存储。
- 性能:对于高负载场景,确保 Caddy 服务器有足够的资源来处理 ACME 请求。
- 兼容性:测试你的 ACME 服务器与目标客户端的兼容性,确保支持所需的挑战类型。
- 证书有效期:在生成 CA 证书时,合理设置有效期(例如,10 年),以减少频繁更换的需要。