中间人如何识别代理流量
伪装终究是伪装 没有全方位完美的伪装 只有在某些角度完美的伪装
常见的中间人攻击方式
被动分析 (流量特征, PoC 漏洞)
常用于分析明文协议, 或者 TLS 握手
主动探测
一般对于 Shadows , V2 , TLS 1.3 (获取服务器 SSL 证书)
- 数据包重放
主要用于识别客户端,但对某些协议服务端的识别也会有奇效
代理流量的常见特征
只要是个代理流量,这些特征就无法(很难)被隐藏
长连接
互联网上大部分的正常流量都是短连接,正常的使用下怎么可能出现长期维持连接的情况,少有持续几小时甚至几天几个月的连接,但长连接是代理客户端位于路由器时常见的情况。
双向流
互联网中99%的Web流量 都是单向流, 一组请求对应一组响应 ( Request -> Response ), 使用WebSocket 的服务占比非常少, 在一个 Web 服务上跑双向流难道不是一种自欺欺人?
大流量
如果你认为伪装Web聊天室就可以解决上面的双向流问题, 那么请你解释一下 哪个Web聊天室的流量这么大?
连接多
如果你的流量不是很大的话, 那么又怎么解释你对着一个Web服务器开 20 – 30 个甚至几十上百个连接? 一般一个网页(聊天室, 探针)只会创建一个WebSocket连接 , 少有服务会允许客户对其并发这么多连接,。
点对点
一个用户对着一个网站域名, IP 进行连接, 跑的加密长连接,流量还几乎占了他带宽的100%, 如果你是中间人, 你会怎么觉得?
辟谣几个传闻
套 TLS 很安全, 这样就没有办法被识别了
详细请看后面的 TLS 连接风险评定
开了IP白名单, 任何探测和重放攻击都没用
中间人属于旁路设备, 你发送和接收的所有流量都要经过, 伪造任意一方的IP是一个很高深的技术吗? 相反 如果开了白名单, 是不是更可疑呢? (越不想让别人看到的东西 越更可疑啊)
我从来就没有出事过
幸存者偏差, 也许你流量小到没有分析的必要
备案域名不会出事
并不是,备案域名和未备案域名跨境传输是同等待遇,只是备案域名可以使用大陆服务器直接提供Web服务
TLS流量风险评定
客户端握手 (ClientHello)
TLS ClientHello有指纹
TLS 指纹又叫 SSL 指纹,或者 JA3 指纹,是根据客户端向服务端发送的 Client Hello 计算得到
在 TLS 握手中还有服务端响应的 Server Hello,也有特征,可以得到 JA3S 指纹
服务端会根据不同的 Client Hello 响应不同的 Server Hello,根据这个可以得到 JARM 指纹。
如果使用程序默认的指纹去访问一个网页, 且符合上述流量特征, 那么是代理的风险会很高
典型例子就是伊朗会阻止curl和wget的指纹对非白名单SNI(不要以为伪装SNI就能解决,伪装其实也很容易检测)的请求, Go TLS和浏览器指纹则正常。
有开源项目可以帮你伪装成某种浏览器的指纹,一对一使用倒还好,但是一对多使用时,你怎么解释你的web服务TLS连接,全是同一个版本号的chrome TLS指纹呢
服务器名称指示 (访问域名/SNI)
免费域名风险最高, 较为便宜的域名也有一定风险
再说一次,不要以为伪装SNI就能解决,伪装只要想,也是很容易检测的
TLS连接版本号
- TLS 1.3
风险最高的, 因为Server Hello后内容全部加密, 中间人需要主动探测才可以拿到服务器证书 -
TLS 1.2
风险为中等, 但是证书交换全部明文传输, 中间人可以直接截取来校验 -
SSL v3 / TLS 1.0 / TLS 1.1 风险最低, 已经没有多少流量了, 能拿到的流量样本少之又少 (不过这些协议公开漏洞一堆,被攻击风险高 十分不推荐)
TLS服务器证书
自签证书基本和喊“向我开炮”一样。
其次是Cloudflare免费证书和Let’s Encrypt等免费证书 因为人人可免费申请
付费证书的风险最低,因为几乎没有人会花几百几千买一个证书拿去做代理吧。这成本可不低
可用于识别FakeTLS流量的新型探测方式
分析
MTP-FakeTLS和Shadow TLS (v1/v2)都是模拟了一个可信证书的TLS握手, 两个协议的设计都是近似完美的, 在握手时可以验证是否为有效客户端
MTP FakeTLS如何验证客户端
ClientHello包除去random字段进行整包hmac, 密钥就是secret, 服务器使用相同的hmac方式可验证客户端, random有一次性处理, 失败回落到真的Web服务器
识别方法:MTP的TLS握手并不规范, 中间人可以截取到服务器发送的第三个包 (hostCert) 判断包长即可 (此处参考mtg的faketls源代码) hostCert长度为随机生成 长度在1024-4096字节
Shadow TLS v1 不会验证客户端
识别方法:直接使用curl对着服务器发送一个请求, curl会失败
Shadow TLS v2 如何验证客户端
客户端请求后, 获取服务器返回的原始数据 作为challenge(挑战)的response(响应), 使用password进行hmac, 服务器使用相同的hmac方式可验证客户端
由于服务器返回的数据有随机性, 也可以达到一次性认证, 且中间人拿不到password时无法作出challenge的response返回给服务器, 比MTP的握手更加安全
探测客户端
很多协议的安全性只是针对服务器对客户端鉴权, 客户端不会验证服务器有效性(单向鉴权)。
因此中间人可以通过伪造服务器包来探测客户端反应, 即反向探测, 来区分客户端是否为真的浏览器。
(MTP 在 ServerHello 中使用相同的 hmac 算法, 天生屏蔽此探测)
如何识别Shadow TLS v2
代理协议的服务端通常会同时有很多连接,符合前述代理的流量特征后, 随机抽取一个进行客户端探测, 就可以精准识别其客户端存在代理行为,并推测识别服务端。
随机截取一个正常的TCP连接, 在截取到TLS ClientHello后, 根据请求内容中的SNI字段, 将其流量直接发送到该SNI的真正服务器。等待TLS握手完成后, Shadow TLS客户端会在Application Data前8个字节插入服务器的challenge的response
此时由于对面服务器并不是一个Shadow TLS服务器, 而是一个真的TLS服务器, Shadow TLS客户端在握手阶段会顺利完成。但是在发送hmac后, 因为对于实际SNI服务器,这并不是TLS协商好的加密, 服务器会直接抛出Alert (Encrypted Application Data), 然后FIN或者RST掉TCP连接, 此时可以确定客户端为Shadow TLS客户端, 从而对其连接的服务端IP进行精准封杀。