Caddy ECH 完整指南:3 步开启加密客户端 Hello,让 SNI 不再明文泄露
【免费下载链接】caddyFast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS项目地址: https://gitcode.com/GitHub_Trending/ca/caddy
连公共 WiFi 时,即使流量已走 HTTPS,握手时的 SNI 字段仍是明文——旁边的人能直接看到你要打开哪个网站。Caddy 内置了 ECH(Encrypted Client Hello,加密客户端 Hello)支持,能把这个域名也一并锁进加密层。这篇讲清 ECH 解决什么问题、原理怎么跑,以及 3 步开启它。
开启 ECH 后的区别:域名从明牌变暗牌
没有 ECH:内容加密,但"你在访问哪个域名"全程明牌。你的 ISP、公司出口、咖啡馆 WiFi 的运维,都能记下你的浏览轨迹。
有 ECH:客户端发出的 SNI 换成一个被多个站点共用的"外部域名"(类比:信封上只写某公寓的公共信箱号,真实收件人写在封了蜡的内层)。旁观者只能知道"用户连了这台服务器",无法判断具体是站内哪个站点。
注意它的价值定位:不是让连接更安全(内容本来就加密了),而是补上"域名可见"这个缺口。
Caddy ECH 原理:3 个关键点
- 一封信封两层。TLS 握手的 ClientHello 里带着 SNI。ECH 把真实 ClientHello 加密后,外面再包一层用
public_name的"外层 ClientHello"。谁看到外层 SNI,谁就只知道公共域名。 - 密钥全自动管理。Caddy 自动生成 X25519 密钥对(HPKE 加密套件),持久化在自己的存储里(
ech/configs/前缀下),每 30 天轮换一次新密钥,90 天后删除旧密钥,集群实例间用存储锁同步。你不需要自己管任何密钥。 - 浏览器要先"知道路"。客户端得提前知道某站点支持 ECH、该用哪个外部域名。主流浏览器是从 DNS 的 HTTPS 记录(SVCB RR)里读这份配置——Caddy 可以自动帮你把 ECH 配置发布成这条 DNS 记录(即配置里的
publication)。
核心实现都在 modules/caddytls/ech.go,想深挖可以顺着读。
Caddy ECH 最快配置方法:3 步跑通
ECH 配置挂在 tls 应用下。最小可用 JSON 如下,只做两件事:声明外部域名、提供 DNS API 让 Caddy 写记录:
{ "apps": { "tls": { "encrypted_client_hello": { "configs": [ { "public_name": "ech.example.com" } ], "publication": [ { "publishers": { "dns": { "provider": { "name": "cloudflare", "email": "you@example.com", "api_token": "<你的 token>" } } } } ] } } } }第 1 步:准备外部域名。public_name是对外展示的外层 SNI,用你自己控制、且解析到这台服务器的域名。Caddy 会自动为它申请证书(它只做"外壳",不承载真实流量)。
第 2 步:配好发布渠道。DNS 发布依赖自定义构建(需包含 DNS provider 模块);如果你在 tls 应用里已经给 ACME 配了 DNS provider,Caddy 会默认复用它发布 ECH,publication甚至可以省略。
第 3 步:看日志验证。启动后日志出现successfully published ECH configuration list即发布成功。浏览器端建议开 DoH 或 DoT 再测,效果才完整。
ECH 常见 6 个坑及处理
- ECH 强制 TLS 1.3。受影响的服务策略会被 Caddy 自动把最低 TLS 版本提到 1.3,配置里写了更低版本也不会生效,别当 bug。
- 不配 publication 等于白开。绝大多数浏览器读不到配置就不会走 ECH。发布是必选项,不是可选项。
- 外部域名越少越好。源码注释明确建议每台服务器只保留一个 public name——站点共用一个外部域名,"匿名集"越大,旁观者越难区分。
- CNAME 域名发不了。域名若存在 CNAME 记录,Caddy 跳过并打警告(HTTPS 记录无法与 CNAME 共存);完全没有任何 DNS 记录的域名也会被跳过,这是为了保护通配符解析不被破坏。
- On-Demand TLS 的域名要手动列。按需签发证书的域名,Caddy 在握手时才知道,来不及发布——必须在
publication[].domains里显式列出,否则首个连接仍会明文暴露域名。 - 它仍是实验特性。源码标注了 EXPERIMENTAL,字段结构可能变化;且依赖较新的 Go 版本(go.mod 要求 1.25.1),请用较新的构建。
谁适合现在就用
- 个人开发者:有域名、DNS 支持 API 写入,上面这份配置就能跑,成本接近零,隐私收益真实可测。
- 小团队 / 多子域名产品:最划算的场景——一个外部域名罩住整组子域名。
- 求稳的生产环境:建议先给非关键子域名开,观察几天再铺开。API 还在演进,CNAME、按需 TLS 等边界情况值得先验证。
回到开头的公共 WiFi:开启 ECH 后,旁观者看到的只是那个共享外部域名,具体站点不再明牌。现在就可以做的第一步:给一个子域名填上public_name和publication,等日志里那条 "successfully published" 出现,再考虑扩大范围。
【免费下载链接】caddyFast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS项目地址: https://gitcode.com/GitHub_Trending/ca/caddy
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考