利用DoH+ECH+中继代理打造抗审查网络
利用DoH+ECH+中继代理打造抗审查网络
LynxFrost本文章仅提供思路进行学习交流,具体代码因为合规问题暂不提供。
前提条件: 要访问的目标网站必须支持 ECH,并且其 CDN 的 IP 没有被全面封锁。
适用范围: 本文主要针对托管在 Cloudflare (CF) 上的网站,其他 CDN 原理类似。
核心架构: 自建智能 DoH + ECH 加密握手 + 选择性中继代理
知己知彼——防火墙是如何阻断连接的?
1. DNS 污染(最常见)
原理: 拦截 UDP 53 端口的明文 DNS 查询。
过程: 当你查询 x.com 时,防火墙识别到黑名单域名,不等上游真正返回结果,直接抢答一个虚假 IP。你连上假 IP,自然访问失败。
解决方案:使用 DoH (DNS over HTTPS)
2. IP 黑名单封禁
原理:防火墙维护着一张黑名单 IP 列表(可能是全端口封禁,也可能仅封 443 端口)。
过程:只要发现你的 TCP 数据包目标 IP 在名单内,直接丢弃或发送 RST 包重置,导致三次握手失败。
解决方案:使用 中继代理 改变目标 IP
3. SNI 检测
原理:在传统的 TLS 握手阶段(不带 ECH),ClientHello 报文中的 SNI(服务器名称指示)是明文的。
过程:防火墙抓到 TCP 443 流量,读取明文 SNI。如果命中黑名单,直接强行断开连接。
ECH 的作用:把真实 SNI 藏进加密内层 ClientHello,防火墙读取不到真实域名,无法用 SNI 规则阻断。 但注意:防火墙依然可以看到目标 IP。只要 IP 被封禁,ECH 也救不了。
解决方案:使用 ECH (Encrypted Client Hello)。把真实域名藏进加密内层,防火墙只能看到伪装的外层域名。(注意:如果CDN的公共域名也被阻断了,ECH 也救不了)。
4. 流量特征、行为检测
原理:不看 IP 和域名,专门分析协议特征(如 HTTP Host 头、TLS 握手时序、JA3/JA4 指纹,甚至数据包大小和持续时间)。
过程:当大量用户用同一个 IP 访问特定服务,或者特征高度疑似翻墙软件,直接封禁。
解决方案:纯网络层基本无解,需依赖复杂的应用层流量伪装。
| 封禁方式 | 防火墙识别依据 | ECH 能否绕过 | DoH 能否绕过 |
|---|---|---|---|
| DNS 污染 | DNS 查询域名 | 不相关 | 可以 |
| IP 封禁 | 目标 IP 地址 | 不能 | 不能 |
| SNI 检测 | TLS 握手明文 SNI | 可以 | 不相关 |
| DPI 流量特征 / JA3 | 数据包特征 | 不能 | 不能 |
核心武器库——DoH 与 ECH 解析
现代 DNS 加密协议大比拼
| 协议 | 底层传输 | 加密方式 | 默认端口 | RFC | 特点 |
|---|---|---|---|---|---|
| DNS | UDP/TCP | 明文 | 53 | 1035 | 原始,易窃听劫持 |
| DoT | TCP | TLS | TCP 853 | 7858 | DNS 直接套 TLS,端口明显,易被封 |
| DoH | TCP | HTTPS(HTTP+TLS) | TCP 443 | 8484 | 伪装成网页 HTTPS,开销大 |
| DoQ | UDP | QUIC (内置 TLS1.3) | UDP 853 | 9250 | UDP + 加密,无队头阻塞,性能最好 |
核心问答:
Q:加密 DNS 能防止域名污染吗?
A:只能保护【你 ↔ DNS 服务器】这一段不被中间人篡改。如果上游 DNS 本身就被污染了,加密也没用。
Q:哪个最难被防火墙拦截?
A:DoH。因为它走 TCP 443 端口,流量特征和普通浏览网页一模一样,防火墙很难将其从正常业务流量中剥离。
DoH(DNS over HTTPS)
中间人不能直接读到 DoH 报文里的查询域名;但依然有各种途径识别 DoH 流量,以及推断你查询的域名,只是比 DoT 更难。
DoH 本质:把 DNS 查询包装成 HTTPS 请求,走 TCP 443,HTTPS = HTTP + TLS。
DoH 加密保护了什么
TLS 加密了整个 HTTP payload: 中间人抓包看不到 HTTP 里面的内容,无法直接读取被解析的域名。 不管是 GET(域名放在 URL)还是 POST(DNS 二进制包放 body),全部被 TLS 加密。
中间人能看到什么
- 你的客户端 IP
- 目标 IP:DoH 服务器的 IP
- 目标端口:TCP 443(标准 HTTPS 端口,和普通网页一模一样)
- TLS 握手 SNI:这里 SNI 是DoH 服务本身的域名,不是你要解析的目标域名
ECH (Encrypted Client Hello):终结 SNI 明文时代
ECH 是 TLS 1.3 的扩展标准(RFC9849),用来加密 TLS 握手一开始的 ClientHello 消息,解决传统 HTTPS 里SNI 明文泄露域名的问题。
原来的痛点
普通 HTTPS TLS 握手: 浏览器发 ClientHello,里面明文 SNI,告诉服务器:我要访问 x.com。 运营商 / 防火墙抓包直接看到这个 SNI,就算后面流量全部 TLS 加密,中间人一眼知道你访问哪个域名。
ECH 核心原理:拆成两层 ClientHello
- ClientHelloInner(内层,加密) 里面放真实 SNI(目标网站域名)、TLS 版本、加密套件等全部真实握手信息,用网站 CDN 发布的 ECH 公钥(HPKE 混合公钥加密)加密。
- ClientHelloOuter(外层,明文,中间人能看到) 外层是一个伪装的正常握手,外层 SNI 是 CDN 的公共域名(比如
cloudflare-ech.com),不是你真正访问的网站; 同时把加密好的 Inner 包,塞进一个encrypted_client_hello扩展字段发给 CDN 边缘服务器。
完整流程
- 浏览器先用 DoH(推荐)查询网站的 DNS HTTPS 记录,拿到网站公布的 ECH 公钥配置;
关键点:ECH 的公钥要通过 DNS 获取,如果 DNS 被污染 / 劫持,拿到假 ECH 配置,ECH 直接失效,所以 ECH通常搭配 DoH 一起用。
浏览器构造内外两层 ClientHello,内层用拿到的公钥加密;
发给 CDN 边缘服务器;
CDN 边缘服务器持有对应的私钥,解密拿到内层 ClientHello,读取真实 SNI,再转发请求到后端网站;
建立 TLS 连接,正常传输网页内容。
中间人抓包只能看到:你连接到 CDN 的 IP,外层 SNI 是
cloudflare-ech.com,看不到你真正访问的网站域名。同一个 CDN 下成千上万个网站,ECH 握手看起来全部一模一样,无法区分。
ECH + DoH 的组合
- DoH:保护 DNS 查询,拿到真实域名解析 IP,同时安全拿到网站 ECH 公钥,防止 DNS 污染篡改 ECH 配置;
- ECH:保护后续 HTTPS 握手,隐藏 SNI,不让中间人从握手看到真实域名。
DoH 负责安全地获取真实 IP 和 ECH 公钥(防污染);ECH 负责加密后续的 TLS 握手(防 SNI 探测)。
高阶玩法——自建智能 DoH 调度中心
自己搭建DOH服务器,修改 DNS 应答,主动注入、补全 HTTPS (ECH) 记录等等。
使用ECH可能遇到的问题
1.没有配置HTTPS记录,导致ECH未开启。
很多 CF 托管网站,服务器支持 ECH,但 DNS没有 HTTPS 记录。
ECH 想要在浏览器正常启用,有两个必要条件:
- 浏览器拿到 ECH 公钥:公钥承载在 DNS 的 HTTPS 资源记录(HTTPS RR,RFC9460) 里面;
- TLS 服务端(CDN 边缘节点)持有对应的 ECH 私钥,能解密客户端发过来加密后的内层 ClientHello。
Cloudflare 所有边缘节点,默认全部部署同一套全局 ECH 公私钥对。 私钥存在 CF 的边缘服务器上;公钥是公开的。 但是!网站域名所有者,可以选择要不要在自己域名的 DNS 记录里,发布这条 HTTPS RR(携带 ECH 公钥)。 很多接入 CF 的网站,服务器侧具备解密 ECH 的能力,但是域名 DNS 没有写 HTTPS 记录 → 浏览器拿不到公钥,直接放弃 ECH,降级普通 TLS 握手(明文 SNI)。
2.Chromium内核浏览器CNAME 会导致 ECH 失效
正常DNS标准行为:
cdn.example.com CNAME 指向 example.b.cdn.cloudflare.net
- 你查询
cdn.example.com - 原始 DNS 返回 CNAME,指向 CF 二级域名,A 记录是 CF 节点 IP
- HTTPS 记录写在
example.b.cdn.cloudflare.net,而不是cdn.example.com
获取的A记录和HTTPS记录都是CNAME之后的。
Chromium(Chrome/Edge)浏览器的 ECH 规则:
HTTPS 记录 和 A 记录,必须属于同一个域名;如果域名存在 CNAME 别名解析,浏览器直接放弃 ECH。
示例: cdn.example.com CNAME 指向 example.b.cdn.cloudflare.net
- 你查询的域名
cdn.example.com - 最终 A 记录来自别名目标
example.b.cdn.cloudflare.net - 所以 A 记录归属是
example.b.cdn.cloudflare.net - 但 HTTPS RR 是挂在原始查询名
cdn.example.com
Chromium 旧 ECH 逻辑判定:A 记录的所有者 和 HTTPS 记录所有者不一致 → 放弃 ECH。
核心功能
无中生有(补充 HTTPS 记录): 很多网站在 CF 有解密能力,但站长没配 DNS。DoH 识别到 CF 托管域名后,主动注入 CF 的全局 ECH 公钥,强行“唤醒”浏览器的 ECH 功能。
拍平 CNAME(解决浏览器兼容坑): Chromium 规定 A 记录和 HTTPS 记录必须同属一个域名。遇到 CNAME 时,智能 DoH 会直接将 CNAME 链拍平,返回最终 IP 和记录,绕过浏览器的严苛限制。
自动探测更新 ECH 公钥: 针对 Meta (Instagram 等) 不公开 ECH 公钥的情况,探测机主动发起握手抓取公钥,并动态注入到 DNS 应答中。
CDN 优选 IP 池(真·ECH 探活): 抛弃传统的 TCP 测速,探测机每半小时进行“真实 ECH 握手 + HTTP 200”连通性测试。连续 12 次成功且低延迟的 IP 才会被下发。
剔除“套餐隔离”IP: 过滤掉那些只允许 CF 企业版客户访问的专属节点 IP,防止普通网站出现图片/资源 403 错误。
HTTP/3 智能开关: 国内 UDP 丢包严重。探测机确认某节点 QUIC 稳定连通后,才会在 HTTPS 记录中开启 HTTP/3 标记,否则降级 HTTP/2 保证流畅。
就近解析与并发兜底: 携带客户端网段信息进行查询,分配国内最优 CDN 节点;多上游并发查询,最快响应。
终极破局——特定敏感服务的中继路由
虽然 ECH 解决了 SNI 阻断,但如果目标 CDN IP 被封禁(或者像 ChatGPT/Grok 这样在应用层封杀中国大陆 IP),直连依然会失败。
智能分流链路
我们需要在 DoH 层面引入按需中继机制:
- 普通出海网站: DoH 返回 CF 优选 IP —> 浏览器直接 ECH 握手 —> 正常访问。
- 受限 AI 服务: DoH 识别到 ChatGPT 等域名,不返回 CDN IP,而是返回你自建的中继 VPS IP。
中继架构的流量链路: 浏览器 —>(ECH 加密握手)—> 中继 VPS —> Azure / 国际路由 —> CDN 边缘节点—> AI 服务
工作细节:
- 盲转发: 中继服务器只读取明文的外层 ECH 标签(确认是合法流量),看不到内层真实域名,不终结 TLS 握手,只做纯四层字节转发。
- 端到端加密: 真正的 TLS 加密通道建立在你的浏览器与最终的 CDN 节点之间。
- 安全加固: 中继服务器配置访问控制,仅放行携带特定外层 SNI 的 ECH 握手连接,直接拒绝普通的明文 TLS 扫描,防止被 GFW 主动探测。
- 降级 TCP: 限制中继链路仅支持 TCP (HTTP/2),并只返回 IPv4 地址,防止浏览器优先走 IPv6 UDP 直连 CDN 从而暴露身份。
中继服务器的生存法则(防主动探测)
中继 VPS 作为唯一暴露在 GFW 视线下的节点,绝对不能使用傻瓜式的纯四层盲转发,否则面对防火墙的主动探测活不过三天。必须在 VPS 部署具备 SNI 嗅探与回落 (Fallback) 能力的反代软件(如 Nginx Stream 或 Xray-core)。
中继节点的“两幅面孔”逻辑:
- SNI 嗅探识别“自己人”: 当收到 TCP 流量时,中继只读取明文的外层 ECH 标签。如果外层 SNI 匹配(例如是
cloudflare-ech.com),说明这是浏览器的合法 ECH 流量。此时不终结 TLS,直接将字节流转发给背后的 CDN 节点,实现端到端加密闭环。 - 回落伪装对付“审查员”: 如果外层 SNI 不匹配,或者收到的是乱码探测包,说明这是 GFW 的主动探测。此时中继立刻触发 Fallback,将流量路由到 VPS 本地搭建的一个极其正常的伪装网站(例如一个挂有合法证书的静态博客)。GFW 扫描器只会看到一个普通博客,从而认定该 IP 安全。
- 极简攻击面: 中继服务器仅开放 443 和 SSH 端口,转发目标严格限制为目标 CDN 的 IP 段,防止被恶意利用。
架构能力边界——死局
这套“无客户端”架构虽然惊艳,但它存在一个不可逾越的物理边界:当目标 CDN 官方指定的 ECH 公共域名(外层 SNI)本身被防火墙拉黑时,纯网络层中继将彻底失效。 典型的例子就是 Google。
防火墙的“一刀切”:直接阻断 ECH 协议特征
在某些敏感时期或特定地区的运营商网络中,GFW 根本不再费心去鉴别你要访问谁。只要其深度包检测(DPI)系统识别到 TLS 握手数据包中包含 ECH 扩展特征(如 Type 65037 字段),就会采取“宁可错杀一千”的策略,直接将数据包丢弃(Drop)。面对这种针对协议本身的物理“拔网线”,纯四层转发没有任何反抗余地。
公共域名封锁:为什么 CF 能活,而 Google 必死?
即使防火墙没有全局封杀 ECH 协议,而是通过黑名单拦截 ECH 的公共域名(外层明文 SNI),不同的 CDN 也会面临截然不同的命运。这本质上是一场关于“误杀成本”的博弈:
- Cloudflare(自带免死金牌,极难被彻底阻断): CF 的 ECH 外层域名通常是
cloudflare-ech.com。作为全球最大的 CDN 巨头,CF 承载了海量的国内出海企业、跨境电商、外贸网站,甚至部分国内站点的海外加速业务。如果 GFW 彻底将 CF 的公共域名或 Anycast IP 段加入黑名单,会导致极其严重的连带经济损失(巨大的误杀成本)。正因为这种“大到不能封”的护城河,依托 CF 的 ECH 架构往往能在夹缝中长期稳定生存。 - Google(零成本击杀,绝对的无解死局): 与 CF 截然不同,Google 使用的是纯自家的骨干网和 CDN,其 ECH 公共域名(如
echo.google.com)和 IP 节点几乎完全只服务于 YouTube、Search 等谷歌系产品。由于这些业务在中国大陆原本就不合法且被全面封杀,GFW 阻断 Google 的 ECH 域名没有任何连带成本(Zero Collateral Damage)。因此,试图用纯中继架构访问 Google,会在国境线上被毫无顾忌地精准击落。


