前言
域前置已经不是新鲜的话题,本篇文章介绍的是国内外对其理解偏差与我们如何从流量中抓取相关行为。
基础定义
维ji百科中对域前置的定义说的很明白。在明文的DNS请求和TLS服务器名称指示(SNI)中使用无害的域名来初始化连接、公布给审查者,而实际要连接的被封锁域名仅在创建 加密的HTTPS连接后发出,使其不以明文暴露给网络审查者。最基础的实现代码为
curl -v https://fastly.net -H "Host: cn.nytimes.com"
可以看到sni 与 host 的差异性。同样的,在流量行为里我们也可以看到sni,也就是server_name字段。
此时 从流量监测方看到我们只是在与 https://fastly.net 进行通信行为。只有server端拿到明文的请求以后才会看到我们的真实host是 cn.nytimes.com,然后再去其对应的源站进行拉取信息一类操作。
之所以造成此类行为能够正常交互,就是因为fastly.net与cn.nytimes.com接入了同一家CDN厂商,而回源是根据http header host进行回源操作。
国内的“域前置”
看了很多的文章。介绍的“域前置”是这样的:
只是把CNAME接入的IP ping一下,然后填写到CS的IP里。再去修改profile文件,然后指定host为某host。
先不说http的算不算得上域前置。如果按照这个思路的话,其实我们应该这么写:
(CDNIP与域名都是我乱写的,cloudflare已经不支持域前置)
因为4.x版本的CS已经支持在新建监听器时候直接指定 http/https host header了。并且该字段的优先级要比在profile中指定的要高。
所以我们为什么还每次去修改profile文件呢?并且http/https Host stager是为了二次下载载荷用到的,与hosts的属性一致。别人的域名没有解析到上面的IP,也没有与你用同款CDN。直接写别人的域名真的可以正常下发载荷吗?
所以我个人认为这个并不能算作域前置,只能算作是“CDN非法接入”,因为我国政策强制要求提供国内CDN接入必须在备案,所以选择这种方式的话可以不备案使用国内CDN。并且CDN上也可以设置回源host字段,也可以设置成已经备案过的域名。
“CDN非法接入”流量特征
此处不讨论http相关内容,直接看https的。按照“CDN非法接入”的做法,我们可以很轻易的抓到他。CS生成的木马会和https hosts、https host (stager)中填写的内容进行ssl握手。所以此时的情形类似于这样的:(此处我以腾讯云做例子)
从流量里可以很明显的看到,直接访问 https://ip 是没有 server_name字段的。所以访问到的是默认证书。也就是*.cdn.myqcloud.com
此处可以作为重要特征。发送的https请求没有server_name 且接受的证书是CDN默认证书。
域前置的国内实现
“CDN非法接入”,进一步配置即可实现真正意义上的域前置。我们需要知道CDN上都有哪些域名在解析。可以借助VT、微步等平台进行查询。
然后就可以测试发送https请求,然后就得到了一个包含servername的请求与正常握手。
在CS里我们只要这样配置:
即可完成真正意义上的“域前置”。不过弊端同时也会暴露。会产生不必要的DNS请求。
域前置如何禁止?
这点站在CDN厂商的角度来说,有几部分需要做。
1.禁止空的server_name握手
这个可以很好实现。此处借鉴cloudflare做法,将默认证书直接配置错误。例如我在nginx做如下配置:
ssl_protocols TLSv1.1 TLSv1.2; ssl_ciphers MD5;
md5算法只在TLSv1.3中可以使用,所以此时就会握手失败。
2.禁止server_name与host不同的回源
这个 暂时不清楚具体实现。
3.加强CNAME验证
已经有很多CDN厂商在做了。可以禁止掉非法接入,但是接入自己的合法域名后还是可以使用域前置。所以重点还是1.2两部分。不过如果这点加强以后,攻击者就必须使用自己的域名,增加了溯源的可能性。