ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

使用 Caddy 为 Fleet 搭建公网 mTLS 反向代理:测试 mTLS 的完整实战指南

2026/9/20 14:24:08 拓冰建站 浏览量
使用 Caddy 为 Fleet 搭建公网 mTLS 反向代理:测试 mTLS 的完整实战指南 使用 Caddy 为 Fleet 搭建公网 mTLS 反向代理测试 mTLS 的完整实战指南【免费下载链接】fleetOpen device management项目地址: https://gitcode.com/GitHub_Trending/fl/fleet导读本文以 Fleet 开源设备管理项目的开发者测试场景为核心完整讲解如何在一台云主机上使用 Caddy 搭建一个支持**双向 TLSmTLS**的公网反向代理并把经过客户端证书校验的请求转发到 ngrok 隧道背后的 Fleet 服务器。读完本文你将掌握从创建云主机、配置 DNS、签发/放置 CA 证书到编写 Caddyfile 强制客户端证书认证、向后端注入X-Client-Cert系列头以及配合 Fleet 的conditional_access.cert_serial_format配置实现 Okta 条件访问联调的全流程。为什么需要公网 mTLS 反向代理Fleet 的 mTLS 相关能力如 fleetd-mTLS 认证、Okta 条件访问需要客户端在 TLS 握手中出示由受信任 CA 签发的客户端证书。在本地开发与联调阶段你通常没有现成的、对公网开放的 mTLS 端点而本指南正是为解决这一测试痛点而生把本地的 Fleet 服务器通过 ngrok 暴露到公网获得一个稳定的https://...ngrok.io隧道地址在云主机上用 Caddy 前置一层 mTLS 网关只放行持有合法客户端证书的请求Caddy 将客户端证书的叶子证书、序列号、Subject、Issuer 等信息以 HTTP 头转发给后端让 Fleet或其后的 Okta 条件访问逻辑能够识别调用者身份。整个架构可以用下面的流程图概括从源码视角看Fleet 官方将这类测试场景沉淀在了 mtls-reverse-proxy-setup.md 中并配套了 okta-conditional-access-testing.md 用于后续条件访问的联调验证二者共同构成一条完整的测试链路。前提与假设开始前请确认你满足以下条件本文使用example.site与my-fleet-server.ngrok.io作为占位符请全部替换为你自己的真实值你拥有一个域名例如example.site或其他任意域名你将使用一个子域名例如mtls.example.site可自行选择你有一份客户端 CA 证书根 CA 或中间 CA如client-ca.crt用于签发所有合法客户端证书你有一个想要转发的后端地址ngrok URL例如https://my-fleet-server.ngrok.io你拥有 DigitalOcean 或其他云厂商账号能创建一台公网虚拟机准备好ssh-keygen生成的 SSH 密钥对推荐。提示客户端证书通常以client-cert.pem/client-key.pem的形式保存在测试客户端上用于后续curl验证。Step 1在 DigitalOcean或其他云厂商创建 Droplet登录 DigitalOcean 控制台在 Dashboard 中点击Create → Droplet选择操作系统镜像例如 Ubuntu 24.04 LTS 是一个不错的默认选择选择套餐仅用于测试的话最低配即可例如 Basic1 vCPU / 1 GB RAM选择数据中心区域尽量靠近你的用户或开发位置添加 SSH 密钥推荐这样你可以安全地通过 SSH 登录如果没有 SSH 密钥可先执行ssh-keygen生成并把公钥粘贴到控制台完成主机名、备份等其余设置点击Create Droplet。稍等片刻你会得到一个带公网 IP 的 Droplet示例中以203.0.113.45为例。Step 2配置 DNS让子域名指向 Droplet你需要让子域名解析到该 Droplet 的 IP在 DigitalOcean 控制台进入Networking → Domains或DNS在域名记录页添加一条 A 记录TypeAHostnamemtls完整主机名即mtls.example.site可按需修改Value / Points toDroplet 的公网 IP例如203.0.113.45TTL保持默认想更快生效可以调低等待 DNS 传播可能需要几分钟可用dig mtls.example.site或ping mtls.example.site验证是否解析到 Droplet IP。一旦生效客户端访问mtls.example.site时就会到达你的 Droplet。Step 3SSH 登录并安装 CaddySSH 登录ssh root203.0.113.45更新系统软件包apt update apt upgrade -y安装 CaddyUbuntu 上推荐通过官方仓库方式# 安装所需依赖包 apt install -y debian-keyring debian-archive-keyring apt-transport-https # 添加 Caddy 官方稳定版仓库 curl -1sLf https://dl.cloudsmith.io/public/caddy/stable/gpg.key | apt-key add - curl -1sLf https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt | tee /etc/apt/sources.list.d/caddy-stable.list apt update apt install -y caddy安装完成后你会得到一个系统服务caddy它可以管理配置并支持自动重载systemctl reload caddy不需要手动重启整个进程。Step 4把 mTLS CA 证书放到服务器上你需要把签署客户端证书的 CA 公钥证书例如client-ca.crt放到 Caddy 可读取的位置在本地机器上把 CA 证书文件复制到 Dropletscp client-ca.crt root203.0.113.45:/etc/caddy/client-ca.crt在 Droplet 上确认 Caddy 可读设置权限chmod 644 /etc/caddy/client-ca.crt chown root:root /etc/caddy/client-ca.crt注意这里放置的是 CA 的公钥证书不是私钥。Caddy 只依赖它来校验客户端证书的签发链不需要也不应接触私钥。Step 5配置 CaddyTLS mTLS 反向代理 请求头转发你需要的Caddyfile位于/etc/caddy/Caddyfile应实现以下能力监听mtls.example.site启用 TLSCaddy 会自动通过 Lets Encrypt 申请证书要求客户端证书认证并信任你的 CA将收到的请求反向代理到后端 ngrok URL把客户端的叶子证书与序列号等信息作为 HTTP 头注入给后端。下面是可以直接使用的示例Caddyfilemtls.example.site { # 启用 TLSCaddy 自动 HTTPS tls { # mTLS客户端认证配置 client_auth { mode require_and_verify trusted_ca_cert_file /etc/caddy/client-ca.crt } } # 反向代理到你的 ngrok 后端 reverse_proxy https://my-fleet-server.ngrok.io { # 让 ngrok 开心 header_up Host my-fleet-server.ngrok.io # 转发客户端证书相关信息头 # 使用 DER base64 编码PEM 含换行符会破坏 HTTP 头。 # 注意AWS ALB 在 X-Amzn-Mtls-Clientcert-Leaf 中发送的是 URL 编码的 PEM。 header_up X-Client-Cert {http.request.tls.client.certificate_der_base64} header_up X-Client-Cert-Serial {http.request.tls.client.serial} header_up X-Client-Cert-Subject {http.request.tls.client.subject} header_up X-Client-Cert-Issuer {http.request.tls.client.issuer} } }保存该Caddyfile后进入下一步。Step 6重载 Caddy 并验证 mTLS 链路修改完/etc/caddy/Caddyfile后重载 Caddy 使配置生效systemctl reload caddy实时查看日志排查 TLS / 客户端认证错误journalctl -u caddy -f如果一切正常Caddy 应能做到自动从 Lets Encrypt 为mtls.example.site申请 TLS 证书在该主机名上接受 HTTPS 连接要求连接方出示由你的 CA 签发的合法客户端证书客户端证书校验通过后把请求代理到https://my-fleet-server.ngrok.io向后端转发X-Client-Cert客户端证书的 PEM与X-Client-Cert-Serial序列号等请求头。在持有合法证书的客户端上用curl验证curl --cert client-cert.pem --key client-key.pem https://mtls.example.site/healthz你应该能看到来自后端的响应经 ngrok 转发回来且后端应收到如下请求头X-Client-Cert: MIIDXTCCAkWgAwIBAgIJAK... (base64-encoded DER certificate) X-Client-Cert-Serial: 542242443644849078027064623851697342324729218861 X-Client-Cert-Subject: CNvictordev X-Client-Cert-Issuer: CNMy CA如果你使用未由你的 CA 签发的证书或不带证书TLS 握手应当直接失败客户端被拒绝。Okta 条件访问注意事项Caddy 以**十进制decimal格式发送证书序列号如上例所示而 AWS ALB 以十六进制hexadecimal**格式发送。如果使用本 Caddy 方案配合 Okta 条件访问你需要在 Fleet 中将序列号解析格式配置为十进制即设置conditional_access.cert_serial_format为decimal。Step 7验证与排障清单测试 DNS 是否正确解析分别用正确证书与错误/缺失证书执行curl确认握手行为符合预期查看 Caddy 日志中的 TLS 握手错误如果后端ngrok拒绝某些请求头或看到意外的主机名可能需要调整header_up Host或其他请求头配置。与 Fleet 配置的衔接cert_serial_format 详解上面提到Caddy 转发证书序列号时使用十进制而 AWS ALB 使用十六进制。Fleet 服务器通过conditional_access.cert_serial_format配置项来适配这两种格式从而正确解析X-Client-Cert-Serial请求头中的序列号。在 Fleet 的服务器配置文档 fleet-server-configuration.md 中对此有明确说明默认值hex环境变量FLEET_CONDITIONAL_ACCESS_CERT_SERIAL_FORMAT配置文件格式conditional_access: cert_serial_format: decimal该配置的含义是指定在 Okta 条件访问认证期间从X-Client-Cert-Serial请求头解析证书序列号所用的格式。由于不同负载均衡器/反向代理发送的序列号格式不同AWS ALB 发送十六进制例如序列号 10 表示为ACaddy 发送十进制例如序列号 10 表示为10此配置可以让 Fleet 无论前置代理是谁都能正确解析序列号。源码实现佐证Fleet 的 Go 源码在 server/config/config.go 中定义了该配置项及其校验逻辑定义了两种合法取值常量CertSerialFormatHex hex与CertSerialFormatDecimal decimalConditionalAccessConfig结构体server/config/config.go中的CertSerialFormat字段对应 YAML 键cert_serial_formatValidate方法server/config/config.go会校验取值必须为hex或decimal之一否则在启动时直接触发致命错误conditional_access.cert_serial_format。对应的单元测试 server/config/config_test.go 覆盖了四种场景合法的hex、合法的decimal、非法字符串invalid以及空字符串其中后两者会触发校验错误。这套测试从侧面印证了该配置项是 Fleet 服务器启动时强校验的、用于 Okta 条件访问的正式配置项而不是测试专用的临时开关。总结通过本指南你已经在云主机上完成了一个可对外提供服务的 mTLS 反向代理创建了具备公网 IP 的云主机Droplet将子域名通过 A 记录指向该主机安装并配置 Caddy启用require_and_verify客户端证书认证将经过认证的请求反向代理到 ngrok 隧道背后的 Fleet 服务器同时转发客户端证书信息头依据前置代理的序列号格式Caddy 为十进制、AWS ALB 为十六进制正确设置 Fleet 的conditional_access.cert_serial_format。至此你的测试客户端只需持有由受信 CA 签发的证书即可安全访问 Fleet任何未持有合法证书的连接都会在 TLS 握手阶段被拒绝——这正是生产环境中 mTLS 防护模型在开发/测试环境里的最小可复现版本。你可以在此基础上继续深入 okta-conditional-access-testing.md 验证 Fleet 的 Okta 条件访问集成。【免费下载链接】fleetOpen device management项目地址: https://gitcode.com/GitHub_Trending/fl/fleet创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考