09
2025
04
17:09:54

通过https握手rtt识别TCP代理(SOCKS5/HTTP/HTTPS)

目录

    • 原理

    • 未经隧道的正常的https请求

      • 简化示意图

        • 数据和分析

      • 经隧道的https 请求

      • 示意图

        • 过程简述

          • 特别部分

        • 数据和分析

    • 总结

    • 其他思考

      • http + 302 跳转测试

        • 直接连接

        • 300ms的TCP隧道

    • 关于代码或demo


最近在研究tcp 选择timestamp中,发现了其中功能之一是用来计算往返时间(rtt)。经过http隧道代理的学习后,我发现这个rtt在特定情况下可以用来识别用户是否使用了隧道代理。

原理

tcp隧道在创建时和建立后这2个状态中,会出现2种数值的rtt,如果可以准确的捕获,以此为依据则可以断定该访问使用了隧道代理。

  1. proxy 和 server 的rtt
    proxy 和 server 进行tcp握手时,可以取得对应rtt

  2. clinet 和 server 的rtt
    隧道建立后,数据由clinet经过proxy转发至server,此时可以获得对应rtt

  3. https服务端的区分方法
    访问https服务会出现2种握手,TCP握手和TLS握手。以此为标志可以取得2种rtt。

我的测试环境:

  1. 服务端是https

  2. 客户端与代理有100ms延迟

未经隧道的正常的https请求

简化示意图

clinet					server
1	=====	SYN 		======>	
2	<====	SYN,ACK		=======
3	=====	ACK		======>
4	=====   Clinet hello	======>
5	<====	ACK		=======
6	<====	Server hello	=======
7	=====	ACK		======>
8	=====	TLS handshake	======>
	……
	……

数据和分析

通过客户端抓ACK包,可以得到以下数据:
其中 rtt 由tcp的timestamp计算,clock由系统时间戳计算得到。

 	"deltas": [                    "$rtt=178, clock=0.17799997329712",		//3-1
                    "$rtt=0, clock=0.002000093460083",		//4-3
                    "$rtt=171, clock=0.16799998283386",		//7-4
                    "$rtt=10, clock=0.0099999904632568"		//8-7
                ],
  1. 其中rtt=178rtt=171,可以约为client到server的往返时间。

  2. 其中rtt=10,为第二个clinet TLS握手包距离上个ACK包的差值,
    在正常连接中可以视为握手的验证和计算时间(猜的)。
    这个时间在手机中会变大,估计是手机性能影响。

经隧道的https 请求

示意图

(简化并忽略隧道握手)

clinet					proxy					server
1	=====	SYN 		======>	
2	<====	SYN,ACK		=======
3	=====	ACK		======>
4	=====   Clinet hello	======>		
5						=====	SYN 		======>
6						<====	SYN,ACK		=======
7						=====	ACK		======>
8						=====   Clinet hello	======>
9						<====	ACK		=======
10						<====	Server hello	=======
11	<====	Server hello	=======		=====	ACK		======>
12	=====	ACK		======>		
13	=====	TLS handshake	======>		=====	TLS handshake	======>
	……
	……	

过程简述

  • 1-3
    为 client 和 proxy 建立tcp链接

  • 4
    隧道建立后,发送TLS Hello 握手包到proxy

  • 5-7
    为 proxy 和 server 建立tcp链接

  • 8
    与server建立tcp链接完成后,转发TLS Hello 握手包

  • 9-13
    隧道转发数据,其中TCP的ACK确认包不会被转发

特别部分
  • 11-12:
    proxy会在收到 Server hello 的tcp包后,会直接给server发送ACK确认包。
    同时,把数据转发给client。
    而client收到Server hello 的tcp包后,ACK确认包发给的是proxy。

  • 13
    client收到Server hello 的tcp包经过验证和计算后,往proxy发送后续的握手包。

数据和分析

通过在服务端客户端抓ACK包(实际就是 proxy 到 server ),可以得到以下数据:
其中 rtt 由tcp的timestamp计算,clock由系统时间戳计算得到。

 	"deltas": [                    "$rtt=159, clock=0.15899991989136",		//7-5
                    "$rtt=0, clock=0.00099992752075195",	//8-7
                    "$rtt=163, clock=0.16199994087219",		//11-8
                    "$rtt=109, clock=0.10900020599365"		//13-11
                ],
  1. 其中rtt=159rtt=163,可以约为proxy到server的往返时间。

  2. 其中rtt=109,为 client 到 proxy 的往返时间
    对比正常的请求,这个【13】的TLS握手包,proxy需要等clinet返回才可以发送。因而多了clinet到proxy的时间,忽略严重和计算部分,可以约为client 到 proxy 的往返时间。

总结

通过以上思路,https服务端通过捕获到客户端TLS握手包往返时间去判断隧道代理是可以实现的。
当然部分情况是会尝试误判:

  1. 客户端是移动设备,TLS握手包的验证+计算时间会太大以至于干扰往返时间去判断
    例如手里的苹果xr,该时间约为20ms。远古时代里的mi5,则可以到32ms。
    如果再配合浏览器验证一次算力,也是有可能减少该值的干扰。

  2. 如果proxy到clinet直接的延迟足够低,那么也无法识别
    例如我用PC做SOCKS5转发,在同个wifi下,用手机进行隧道连接,那么得到的数据与在PC中的几乎一致。
    不过实际使用隧道转发还能可如此低延迟链接,该场景我想不太出来。难道是专门在代理ip池对应地区建个机子?
    相反,对于单机内使用ip代理做爬虫的类似的操作,都应该能准确的识别。

其他思考

关于服务端是不是一定要https才行这个问题。其他类型的协议是不是也可以比如http,ws,未作验证,纯脑洞。

http + 302 跳转测试

本地大概测试一下看数据应该可行。302 跳转是为了让上个连接走一个完整的TCP。
其中四次挥手中的2个确认包会被隧道直接返回。
测试环境为本地,TCP隧道延时是自己强加的,为300ms,不确定实际运行是否也是如此数据,有空再试。

直接连接

"deltas": [
	"$rtt=9, clock=0.002000093460083",
	"$rtt=10, clock=0.0099999904632568",
	"$rtt=4, clock=0.0039999485015869",
	"$rtt=0, clock=0",
	"$rtt=0, clock=0"
],
"info": [
	"50775 \u2192 80 [SYN] Seq=0 Win=65535 Len=0 MSS=1460 WS=32 TSval=1401643228 TSecr=0 SACK_PERM=1",
	"50775 \u2192 80 [ACK] Seq=1 Ack=1 Win=131744 Len=0 TSval=1401643237 TSecr=124477866",
	"GET \/test.php HTTP\/1.1 ",
	"50775 \u2192 80 [ACK] Seq=408 Ack=218 Win=131520 Len=0 TSval=1401643251 TSecr=124477880",
	"50775 \u2192 80 [ACK] Seq=408 Ack=219 Win=131520 Len=0 TSval=1401643251 TSecr=124477880",
	"50775 \u2192 80 [FIN, ACK] Seq=408 Ack=219 Win=131520 Len=0 TSval=1401643251 TSecr=124477880"
]

300ms的TCP隧道

"deltas": [
	"$rtt=0, clock=0",
	"$rtt=36, clock=0.03600001335144",// 接近设置的300ms
	"$rtt=3, clock=0.0019998550415039",
	"$rtt=0, clock=0.0010001659393311",
	"$rtt=27, clock=0.026999950408936"//接近设置的300ms
],
"info": [
	"65159 \u2192 80 [SYN] Seq=0 Win=65535 Len=0 MSS=65495 WS=256 SACK_PERM=1 TSval=123950403 TSecr=0",
	"65159 \u2192 80 [ACK] Seq=1 Ack=1 Win=2619136 Len=0 TSval=123950403 TSecr=123950403",
	"GET http:\/\/192.168.2.121\/test.php HTTP\/1.1 ",
	"65159 \u2192 80 [ACK] Seq=458 Ack=218 Win=2618880 Len=0 TSval=123950442 TSecr=123950441",
	"65159 \u2192 80 [ACK] Seq=458 Ack=219 Win=2618880 Len=0 TSval=123950442 TSecr=123950442",
	"65159 \u2192 80 [FIN, ACK] Seq=458 Ack=219 Win=2618880 Len=0 TSval=123950469 TSecr=123950442"
]

关于代码或demo

proxy guess demo

最后个人水平有限,有理解错误的地方还望大牛指出,虚心学习。

浏览器客户端合法性检测

结合了其他检测技术的一个demo




推荐本站淘宝优惠价购买喜欢的宝贝:

image.png

本文链接:https://zblog.hqyman.cn/post/10275.html 非本站原创文章欢迎转载,原创文章需保留本站地址!

分享到:
打赏





休息一下~~


« 上一篇 下一篇 »

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

请先 登录 再评论,若不是会员请先 注册

您的IP地址是: