欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

P2P协议数据识别

程序员文章站 2022-07-01 11:26:52
...
本文档的Copyleft归yfydz所有,使用GPL发布,可以*拷贝,转载,转载时请保持文档的完整性,严
禁用于任何商业用途。
msn: [email protected]
来源:http://yfydz.cublog.cn

1. 前言

目前P2P应用越来越普遍,如BT、eDonkey、eMule等,这些新一代的P2P突破了老一代数据传输如FTP协议只能两台机器之间传输的瓶颈,可以用多线程多主机/服务器间的连接,可以把网络带宽利用到极限。

由于这些应用对网络带宽带来了很大压力,因此很多场合下P2P成了运营商、网管们所痛恨的对象,运营商迫于压力不敢作限制,但很多网管在所管的防火墙上都进行了P2P的限制。
现在的P2P软件都可以使用动态端口来进行数据连接,而且也可以使用其他协议的标准端口如80等进行通信,因此普通的端口封禁很难奏效,只能从通信内容中进行判断。

netfilter的pom中提供了ipp2p匹配,可匹配很多种P2P协议,本文就是根据ipt_ipp2p.c文件说明各种p2p协议的数据特征。

以下说明都是跳过TCP/UDP头而直接到数据部分。

2. UDP

2.1 eMule/eDonkey/Kad
这几个协议用二进制数进行协商:
--------------------------------------------------------------------第一字节 | 第二字节 | 第三字节 | 其他字节 | UDP长度 | 类型
-------------------------------------------------------------------- 0xe3 | 0x9a | any | any | 26 | edonkey
0xe3 | 0x96 | any | any | 14 | edonkey
-------------------------------------------------------------------- 0xc5 | 0x91 | !0 | any | 12 | emule
0xc5 | 0x90 | !0 | any | 26 | emule
0xc5 | 0x92 | any | any | 10 | emule
0xc5 | 0x93 | any | any | 10 | emule
-------------------------------------------------------------------- 0xe4 | 0x50 | any | any | 12 | kad
0xe4 | 0x58 | !0 | any | 14 | kad
0xe4 | 0x59 | any | any | 10 | kad
0xe4 | 0x30 | any | 0x01(19) | >26 | kad
0xe4 | 0x28 | any | 0x00(69) | >76 | kad
0xe4 | 0x20 | !0 | !0(35) | 43 | kad
0xe4 | 0x00 | any | 0x00(27) | 35 | kad
0xe4 | 0x10 | any | 0x00(27) | 35 | kad
0xe4 | 0x18 | any | 0x00(27) | 35 | kad
0xe4 | 0x40 | any |1(19)0(20)| >40 | kad
--------------------------------------------------------------------

2.2 Gnutella

就是明文检查起始数据是否为"GNUTELLA "或"GND"

2.3 KaZaA

UDP数据部分的结尾6个字节是: "KaZaA\0"

2.4 BitTorrent

UDP长度24字节(含UDP头), 起始8个字节为: 00 00 04 17 27 10 19 80

3. TCP

3.1 Ares
--------------------------------------------------------------------数据长度 | 类型 | 数据内容
-------------------------------------------------------------------- 6 | 连接 | 二进制数: 03 00 5a 04 03 05
60 | 下载 | 字符串: "PUSH SHA1:", 数据结尾为"\n\n"
--------------------------------------------------------------------

3.2 SoulSeek

前8个字节格式为: xx xx 00 00 yy zz 00 00, 其中xx xx为16位负载长度-4, yy!=0, zz任意或者数据长度8字节,全0

或者数据格式为: 01 xx 00 00 00 yy .. zz 00 00 00 .., 其中负载长度大于xx+6, 负载第xx+4+1字节(zz)不为0, 而负载第xx+5+1字节, 第xx+6+1字节为0.

3.3 WinMX

负载长度为4字节时负载内容为"SEND"或负载长度为3字节时负载内容为"GET"

其他情况负载长度必须大于10, 负载必须以"SEND"或"GET"开头, 而且负载内容中出现 0x20 0x22, 之后出现 0x22 0x20.

3.4 appleJuice

负载起始数据为"ajprot\r\n"

3.5 BitTorrent

负载第一字节为0x13, 而且后续数据为: "BitTorrent protocol"

3.6 KaZaA命令

负载最后以"\r\n"结尾, 而且起始数据为: "GET /.hash="

3.7 gnutella 命令

负载最后以"\r\n"结尾, 而且

起始数据为: "GET /get/",

或者是: "GET /uri-res/",

3.8 各种类型的gnutella

负载最后以"\r\n"结尾, 而且

起始数据为: "GNUTELLA CONNECT/",

或者是: "GNUTELLA/"

或者是: "GET /get/", 或 "GET /uri-res/", 而且负载中包含"\r\nX-Gnutella-"或"\r\nX-Queue:"

3.8 各种类型的KaZaA

负载最后以"\r\n"结尾, 而且

起始数据为: "GIVE ",

或者是: "GET /", 而且负载中包含"\r\nX-Kazaa-Username: "

3.9 edonkey文件碎片传输

负载第一字节为0xe3, 第6字节为0x47

3.10 各种类型的edonkey/emule

负载第一字节为0xd4, 而且第2,3字节表示的长度等于负载长度减5, 而且第6字节为0x82

或0x15负载第一字节为0xc5, 而且第2,3字节表示的长度等于负载长度减5, 而且第6字节为0x01/0x02/0x60/
0x81/0x82/0x85/0x86/0x87/0x40/0x92/0x93/0x12

负载第一字节为0xe3, 如果第2,3字节表示的长度等于负载长度减5, 而且第6字节为0x01/0x50/0x16/
0x58/0x48/0x54/0x47/0x46/0x4c/0x4f/0x59/0x65/0x66/0x51/0x52/0x4d/0x5c/0x38/0x69/0x19/
0x42/0x34/0x94/0x1c/0x6a; 如果第2,3字节等表示的长度大于负载长度减5, 而且第4,5字节为0, 第6字节为0x01或0x4c; 如果第2,3字节等表示的长度小于负载长度减5,则负载偏移该长度字节后的第6字节为0xe3/0xc5

3.11 直接连接(Direct Connect)

负载第一字节为0x24, 之后数据为: "Send|"

3.12 各种直接连接(Direct Connect)

负载第一字节为0x24, 而且最后一个字节为0x7c, 而且从负载第2字节的数据格式为:"Lock "/"Key "/"Hello "/"MyNick "/"Search "/"Send"

4. 结论

ipt_ipp2p.c中定义了很多P2P软件的数据的判断模式, 对于二进制的数据可能误判少些, 但文本数据误判可能性就大得多,从协议标准看,eMule/eDonkey的判断应该是比较准确的, 其他的有效性没测试过。

注意程序中将网络数据转换为16位,32位整数的宏:

#define get_u16(X,O) (*(__u16 *)(X + O))
#define get_u32(X,O) (*(__u32 *)(X + O))

因为这些协议都是在Intel硬件,Microsoft操作系统实现,定义的时候就所有数据就都定义为“小头”序而不是一般网络协议中的“大头”序,所以不需要进行ntohs和ntohl转换。