2026 技术实测:域前置(Domain Fronting)未死?EdgeOne 的深度“奇技淫巧”
看来你的实验非常成功!在许多主流 CDN 纷纷对域前置(Domain Fronting)围追堵截的今天,腾讯云 EdgeOne (EO) 依然展现出了极高的“灵活性”。
你的测试结果证明了:即使 SNI 指向的是 geetest.com(极验),只要 HTTP Host 头部设置为你在 EdgeOne 绑定的实际域名,请求依然能成功穿透并到达目标。
以下我为你撰写了一篇技术博客草案,旨在分析这一现象背后的原理与实战价值。
2026 技术实测:域前置(Domain Fronting)未死?EdgeOne 的深度“奇技淫巧”
引言
在网络安全界,域前置 (Domain Fronting) 曾是一种被广泛用于流量伪装的神技。然而,随着 Cloudflare、AWS、Google 等大厂在 2018 年后相继收紧策略,大家普遍认为这一技术已进坟墓。
但最近的一项实测显示,腾讯云旗下的下一代 CDN 产品 EdgeOne (EO),似乎在协议栈的处理上保留了某种“兼容性”,允许我们实现完美的 SNI 伪装。
技术原理回顾
简单来说,域前置利用了 HTTPS 请求中两个不同层级的“域名”不匹配:
- TLS 层 (SNI): 暴露在明文握手中的域名(防火墙可见)。
- HTTP 层 (Host): 加密在 TLS 隧道内部的域名(防火墙不可见)。
当 CDN 节点只检查证书合法性而不强制匹配 Host 头部时,流量伪装就达成了。
实测证据:基于 EdgeOne 的伪装
我们来看博主提供的这一段硬核 curl 命令:
curl -v -I https://geetest.com \
--resolve "geetest.com:443:43.174.246.40" \
-H "host:********************************************"
关键参数解析:
https://geetest.com: 设置 TLS 握手阶段的 SNI。在中间设备看来,你正在访问一个正常的合规网站。--resolve: 强制将geetest.com解析到 EdgeOne 的边缘节点 IP(如43.174.246.40)。-H "host:...": 在加密隧道内,将真实的业务域名塞进 HTTP Host。
实验结果:
HTTP/2 200
eo-log-uuid: 12339217614574395953
eo-cache-status: HIT
server: deno/gcp-europe-west2
结论: EdgeOne 节点成功接收了 SNI 为 geetest.com 的请求,但在处理内部 HTTP 逻辑时,却根据 Host 头部将请求准确分发到了对应的后端服务(这里看起来是一个运行在 Deno 上的服务)。
为什么 EdgeOne 可以做到?
- 统一调度池: EdgeOne 的节点通常承载了海量的站点。为了效率,其边缘网关(Edge Proxy)在处理 TLS 卸载后,会重新读取 Host 字段进行路由,而没有严格执行
SNI == Host的强校验。 - 证书信任链: 在握手阶段,EdgeOne 返回的是通配符证书(如
*.cdn.myqcloud.com或站点专属证书),只要证书验证通过,TLS 链路建立,后续的 Host 头部便获得了“信任”。 - IPv6 兼容性: 根据测试,EdgeOne 的 IPv6 节点(如
240d:c010...)同样支持此特性,这为绕过某些仅监控 IPv4 流量的网关提供了新思路。
这种“发现”有什么意义?
- 蓝队/红队演练: 在渗透测试中,可以利用 EdgeOne 的高信誉度 IP 和伪装 SNI 来隐藏 C2 控制流量,规避 IDS/IPS 的检测。
- 隐私保护: 在敏感网络环境下,保护真实访问目标不被监测。
- CDN 性能调试: 验证 CDN 节点在处理非对等请求时的行为边界。
⚠️ 风险提示
尽管目前测试可行,但这种行为通常处于 CDN 服务商的“灰色地带”。
- 策略封杀: 一旦该技术被滥用,腾讯云可能会像 Cloudflare 一样引入 Error 1013 强制校验。
- 合规风险: 建议仅用于合法的技术研究和授权的安全测试。
总结
EdgeOne 作为腾讯云的明星产品,其强大的边缘处理能力无庸赘述。但对于安全研究者来说,这种“灵活性”才是最迷人的地方。
下次当你觉得某个域名被“重点关照”时,不妨试试把 EdgeOne 当作你的隐形斗篷。
博主注: 你在测试中用到的 geetest.com 也是一个 EdgeOne 的用户吗?或者说,你是否想知道如何寻找更多类似的“白名单”域名来作为前置跳板?
curl -v -I https://geetest.com --resolve "geetest.com:443:43.174.246.40" -H "host:*********************************************"
Note: Using embedded CA bundle, for proxies (230814 bytes)
* Added geetest.com:443:43.174.246.40 to DNS cache
* Hostname geetest.com was found in DNS cache
* Trying 43.174.246.40:443...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* SSL Trust Anchors:
* CAfile: E:\迅雷下载\curl-8.17.0_4-win64-mingw\bin\curl-ca-bundle.crt
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Unknown (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / [blank] / UNDEF
* ALPN: server accepted h2
* Server certificate:
* subject: CN=*.cdn.myqcloud.com
* start date: May 23 00:00:00 2025 GMT
* expire date: Jun 10 23:59:59 2026 GMT
* issuer: C=CN; O="TrustAsia Technologies, Inc."; CN=TrustAsia DV TLS RSA CA 2025
* Certificate level 0: Public key type ? (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* Certificate level 1: Public key type ? (4096/128 Bits/secBits), signed using sha256WithRSAEncryption
* Certificate level 2: Public key type ? (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* subjectAltName: "geetest.com" matches cert's "geetest.com"
* SSL certificate verified via OpenSSL.
* Established connection to geetest.com (43.174.246.40 port 443) from **************************** port 52840
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://geetest.com/
* [HTTP/2] [1] [:method: HEAD]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: *********************************************]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.17.0]
* [HTTP/2] [1] [accept: */*]
> HEAD / HTTP/2
> Host:*********************************************
> User-Agent: curl/8.17.0
> Accept: */*
>
* Request completely sent off
< HTTP/2 200
HTTP/2 200
< content-security-policy: upgrade-insecure-requests
content-security-policy: upgrade-insecure-requests
< content-type: text/html; charset=utf-8
content-type: text/html; charset=utf-8
< link: </assets/client-entry-D_I2vPol.js>; rel="modulepreload"; as="script", </assets/fresh-island__AISummary-BlpGClK3.js>; rel="modulepreload"; as="script"
link: </assets/client-entry-D_I2vPol.js>; rel="modulepreload"; as="script", </assets/fresh-island__AISummary-BlpGClK3.js>; rel="modulepreload"; as="script"
< via: http/2 edgeproxy-h
via: http/2 edgeproxy-h
< server: deno/gcp-asia-southeast1
server: deno/gcp-asia-southeast1
< accept-ranges: bytes
accept-ranges: bytes
< strict-transport-security: max-age=31104000;includeSubDomains;preload
strict-transport-security: max-age=31104000;includeSubDomains;preload
< date: Tue, 03 Feb 2026 08:06:12 GMT
date: Tue, 03 Feb 2026 08:06:12 GMT
< eo-log-uuid: 14782413020394596744
eo-log-uuid: 14782413020394596744
< eo-cache-status: MISS
eo-cache-status: MISS
< nel: {"success_fraction":0.1,"report_to":"eo-nel","max_age":604800}
nel: {"success_fraction":0.1,"report_to":"eo-nel","max_age":604800}
< report-to: {"endpoints":[{"url":"https://nel.teo-rum.com/eo-cgi/nel"}],"group":"eo-nel","max_age":604800}
report-to: {"endpoints":[{"url":"https://nel.teo-rum.com/eo-cgi/nel"}],"group":"eo-nel","max_age":604800}
<
* Connection #0 to host geetest.com:443 left intact
curl -v -I https://geetest.com --resolve geetest.com:443:[240d:c010:132:4::c6] -H "host:*********************************************"
Note: Using embedded CA bundle, for proxies (230814 bytes)
* Added geetest.com:443:[240d:c010:132:4::c6] to DNS cache
* Hostname geetest.com was found in DNS cache
* Trying [240d:c010:132:4::c6]:443...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* SSL Trust Anchors:
* CAfile: E:\迅雷下载\curl-8.17.0_4-win64-mingw\bin\curl-ca-bundle.crt
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Unknown (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / [blank] / UNDEF
* ALPN: server accepted h2
* Server certificate:
* subject: CN=*.cdn.myqcloud.com
* start date: May 23 00:00:00 2025 GMT
* expire date: Jun 10 23:59:59 2026 GMT
* issuer: C=CN; O="TrustAsia Technologies, Inc."; CN=TrustAsia DV TLS RSA CA 2025
* Certificate level 0: Public key type ? (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* Certificate level 1: Public key type ? (4096/128 Bits/secBits), signed using sha256WithRSAEncryption
* Certificate level 2: Public key type ? (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* subjectAltName: "geetest.com" matches cert's "geetest.com"
* SSL certificate verified via OpenSSL.
* Established connection to geetest.com (240d:c010:132:4::c6 port 443) from ************************************* port 51506
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://geetest.com/
* [HTTP/2] [1] [:method: HEAD]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: *********************************************]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.17.0]
* [HTTP/2] [1] [accept: */*]
> HEAD / HTTP/2
> Host:*********************************************
> User-Agent: curl/8.17.0
> Accept: */*
>
* Request completely sent off
< HTTP/2 200
HTTP/2 200
< content-security-policy: upgrade-insecure-requests
content-security-policy: upgrade-insecure-requests
< content-type: text/html; charset=utf-8
content-type: text/html; charset=utf-8
< link: </assets/client-entry-jDLWmvJY.js>; rel="modulepreload"; as="script", </assets/fresh-island__AISummary-BlpGClK3.js>; rel="modulepreload"; as="script"
link: </assets/client-entry-jDLWmvJY.js>; rel="modulepreload"; as="script", </assets/fresh-island__AISummary-BlpGClK3.js>; rel="modulepreload"; as="script"
< vary: Accept-Encoding
vary: Accept-Encoding
< server: deno/gcp-europe-west2
server: deno/gcp-europe-west2
< content-length: 18071
content-length: 18071
< accept-ranges: bytes
accept-ranges: bytes
< strict-transport-security: max-age=31104000;includeSubDomains;preload
strict-transport-security: max-age=31104000;includeSubDomains;preload
< date: Tue, 03 Feb 2026 08:05:42 GMT
date: Tue, 03 Feb 2026 08:05:42 GMT
< age: 59721
age: 59721
< eo-log-uuid: 12339217614574395953
eo-log-uuid: 12339217614574395953
< eo-cache-status: HIT
eo-cache-status: HIT
< nel: {"success_fraction":0.1,"report_to":"eo-nel","max_age":604800}
nel: {"success_fraction":0.1,"report_to":"eo-nel","max_age":604800}
< report-to: {"endpoints":[{"url":"https://nel.teo-rum.com/eo-cgi/nel"}],"group":"eo-nel","max_age":604800}
report-to: {"endpoints":[{"url":"https://nel.teo-rum.com/eo-cgi/nel"}],"group":"eo-nel","max_age":604800}
<
* Connection #0 to host geetest.com:443 left intact

浙公网安备 33010602011771号