P2P协议数据识别

本文档的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转换。

你可能感兴趣的:(多线程,应用服务器,网络协议,网络应用,软件测试)