禁用于任何商业用途。
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转换。