Emule Kad 网络分析.docx
《Emule Kad 网络分析.docx》由会员分享,可在线阅读,更多相关《Emule Kad 网络分析.docx(15页珍藏版)》请在冰豆网上搜索。

EmuleKad网络分析
EmuleKad协议手册
文档编写:
kernel,huby
版权所有:
emuledev@
一、概述3
二、协议参数分析3
2.1BootStrapReq/Res3
2.2HelloReq/Res4
2.3KadReq/Res4
2.4KadSearch/PublishReq/Res5
2.5KadFirewalledReq/Res6
2.6KadFindBuddyReq/Res6
2.7kadCallbackReq6
三、KADSearchAction7
3.1、SendFindValue7
3.2、StorePackt8
3.2.1GetInfo相关协议:
8
3.2.2Publish相关协议:
8
四、EmuleBuddy机制分析9
4.1网络协议包序列图:
9
五、EmuleKad数据结构分析11
附录1(OPCodeList):
12
附录2(QuestionList):
14
一、概述
Kad使用UDP协议,通过eMule软件的UDP端口发送和接收数据
这个宏定义了我能够接受的KAD最高版本
#defineKADEMLIA_VERSION0x02
在ed2k协议里面被使用
CUpDownClient:
:
SendHelloTypePacket
Kad版本:
分为1.0和2.0
区别:
使用两套独立的opcode
从2.0开始具有可扩展性,将版本信息写入协议,日后的扩展不再需要修改opcode
0.47a默认使用的版本为Kad1.0,但是支持2.0
0.47c没有测试过
KAD协议基本上是成对的一个REQ(Request)就有一个对应的RES(Respone)
所有具有KAD头的包,(有些可能是压缩的),最终被送到Kademlia:
:
Process中处理
Process处理各种不同的opcode并将这些数据送到对应的处理函数,在REQ消息的处理函数中,解析发送过来的数据,并且构造RES数据包并发送出去
二、协议参数分析
2.1BootStrapReq/Res
0x00KADEMLIA_BOOTSTRAP_REQ
发送请求,这个时候急需扩大自己的KAD网络
总共发送25B,参照CKademliaUDPListener:
:
SendMyDetails
16B
ThesenderKadID
4B
ThesenderIP
2B
ThesenderUDPPort
2B
ThesenderTCPPort
1B
0
0x08KADEMLIA_BOOTSTRAP_RES
PacketParam:
返回20个Peer信息+自己的信息
KADEMLIA2_BOOTSTRAP_REQ
KADEMLIA2_BOOTSTRAP_RES
2.2HelloReq/Res
0x10KADEMLIA_HELLO_REQ
总共发送2B+25B,参照CKademliaUDPListener:
:
SendMyDetails
1B
OP_KADEMLIAHEADER
1B
byOpcode
16B
ThesenderKadID
4B
ThesenderIP
2B
ThesenderUDPPort
2B
ThesenderTCPPort
1B
0
0x18KADEMLIA_HELLO_RES
回应KADEMLIA_HELLO_REQ,协议包格式和KADEMLIA_HELLO_REQ一样
KADEMLIA2_HELLO_REQ
参照CKademliaUDPListener:
:
SendMyDetails
1B
OP_KADEMLIAHEADER
1B
byOpcode
16B
TheSenderKadId
2B
ThesenderUDPPort
1B
KADEMLIA_VERSION
1B
TagCount
(2)
1B+32B
TAG_USER_COUNT(uint32)
1B+32B
TAG_FILE_COUNT(uint32)
KADEMLIA2_HELLO_RES
回应KADEMLIA2_HELLO_REQ,协议包格式和KADEMLIA2_HELLO_REQ一样
我们可以看到,在2.0版本中,KadHello交换数据包括了自己Kad中已知的用户数和文件数,但接收方都没有处理其中的Tag信息
2.3KadReq/Res
0x20KADEMLIA_REQ
向一个Contact发送KADSearch请求,希望得到更接近一个Hash值的Contact信息
Search类型包括:
KADEMLIA_FIND_VALUE
KADEMLIA_STORE
KADEMLIA_FIND_NODE
参考CSearch:
:
SendFindValue(CContact*pContact)
1B
OP_KADEMLIAHEADER
1B
byOpcode
1B
SearchTye
16B
TargetHash
16B
当前Contacting的ContactID
0x28KADEMLIA_RES
返回更接近一个hashvalue的Contact信息,
这样我们可以获得更加逼近hash的Contact信息,也就是说我们更加有可能找到含有这个hash信息的Contact〔回应方不管具体的Search类型,只是把有更接近Target的Contact发送给请求方〕
参考CKademliaUDPListener:
:
Process_KADEMLIA_REQ
和CKademliaUDPListener:
:
Process_KADEMLIA_RES
1B
OP_KADEMLIAHEADER
1B
byOpcode
16B
TargetUINT128
1B
更接近Target的ContactCount
//Maxcountis32.size817..//16B+1B+25B(32)
n*25B
16B
ContactID
4B
IP
2B
UDPPort
2B
TCPPort
1B
Type(发送这个信息时有填写ContactType值,但Response中处理的时候好像没处理)
Kad2.0
0x21KADEMLIA2_REQ
参考CSearch:
:
SendFindValue(CContact*pContact)
1B
OP_KADEMLIAHEADER
1B
byOpcode
1B
SearchTye
16B
TargetHash
16B
当前Contacting的ContactID
0x29KADEMLIA2_RES
参考CKademliaUDPListener:
:
Process_KADEMLIA2_REQ
和CKademliaUDPListener:
:
Process_KADEMLIA2_RES
1B
OP_KADEMLIAHEADER
1B
byOpcode
16B
TargetUINT128
1B
更接近Target的ContactCount
//Maxcountis32.size817..//16B+1B+25B(32)
n*25B
16B
ContactID
4B
IP
2B
UDPPort
2B
TCPPort
2.4KadSearch/PublishReq/Res
在kad网络内获取需要的索引信息或发布信息
GetInfo相关协议:
KADEMLIA_SEARCH_REQ//UnUsed(老的协议)
KADEMLIA_SEARCH_NOTES_REQ
KADEMLIA2_SEARCH_KEY_REQ
KADEMLIA2_SEARCH_SOURCE_REQ
KADEMLIA2_SEARCH_NOTES_REQ
KADEMLIA_SEARCH_RES
KADEMLIA_SEARCH_NOTES_RES
KADEMLIA2_SEARCH_RES
Publish相关协议:
KADEMLIA_PUBLISH_REQ//UnUsed(老的协议)
KADEMLIA_PUBLISH_NOTES_REQ
KADEMLIA2_PUBLISH_KEY_REQ
KADEMLIA2_PUBLISH_SOURCE_REQ
KADEMLIA2_PUBLISH_NOTES_REQ
KADEMLIA_PUBLISH_RES
KADEMLIA_PUBLISH_NOTES_RES
KADEMLIA2_PUBLISH_RES
2.5KadFirewalledReq/Res
请求别的Peer检测自己是否FireWalled
0x50KADEMLIA_FIREWALLED_REQ
0x58KADEMLIA_FIREWALLED_RES
2.6KadFindBuddyReq/Res
Emule中的LowId需要积极主动找HighId作自己的Buddy,以便于和其它Peer通信
Exam:
LowId(A)主动FindBuddyHighId(B)
0x51KADEMLIA_FINDBUDDY_REQ
//packetparam:
<128bitTarget(Low.AKadId~)>
0x5aKADEMLIA_FINDBUDDY_RES
//packetparam:
//B在接收到了FINDBUDDY_REQ之后,立即回答自己的TCPPort
Buddy之间互相保持通信联系:
OP_BUDDYPINGParam
OP_BUDDYPONGParam
20Minute间隔交互PINGPONG一次,并且HighId一方有防止LowId频繁发送PING(LowId至少必须间隔10Min发送一次)
2.7kadCallbackReq
0x52KADEMLIA_CALLBACK_REQ
OP_CALLBACK
三、KADSearchAction
KAD网络中的Search主要分为以下三组Action操作:
#defineKADEMLIA_FIND_VALUE0x02
#defineKADEMLIA_STORE0x04
#defineKADEMLIA_FIND_NODE0x0B
ActionType
SearchType
说明
KADEMLIA_FIND_VALUE
FILE
KEYWORD
NOTES
FINDSOURCE
KADEMLIA_STORE
STOREFILE
STOREKEYWORD
STORENOTES:
FINDBUDDY
KADEMLIA_FIND_NODE
NODE:
NODECOMPLETE:
Kad的操作又分为两个阶段
(Ⅰ)先尽量找到与Target最近的的Contact〔SendFindValue〕
(Ⅱ)直到找不到更近的Contact后,就在当前最近的Contact开始做具体的StorePacketValue操作(PublishorGetInfo)[Emule目前代码实现是:
一个Contact如果3s之内没有返回更接近Target的Contact,则可以对该Contact进行Value操作了]
3.1、SendFindValue
查找与Target更接近的的Contact:
#Trace:
KadSendFindValue(CContact*pContact)CallStack
CSearch:
:
Go()
|->CSearch:
:
SendFindValue(...)
CSearch:
:
JumpStart()
|->CSearch:
:
SendFindValue
CSearch:
:
ProcessResponse
|->CSearch:
:
SendFindValue//从Res结果中筛选出最好,继续SendFindValue
相关协议:
KADEMLIA_REQ
KADEMLIA2_REQ
KADEMLIA_RES
KADEMLIA2_RES
3.2、StorePackt
对Contact发包,完成不同Action的Value操作(主要是Publish和GetInfo)
#Trace:
Csearch:
:
StorePackt
CKademlia:
:
Process()
|->CSearchManager:
:
JumpStart()
|->CSearch:
:
JumpStart()
|->CSearch:
:
StorePacket()
3.2.1GetInfo相关协议:
KADEMLIA_SEARCH_REQ//UnUsed(老的协议)
KADEMLIA_SEARCH_NOTES_REQ
KADEMLIA2_SEARCH_KEY_REQ
KADEMLIA2_SEARCH_SOURCE_REQ
KADEMLIA2_SEARCH_NOTES_REQ
KADEMLIA_SEARCH_RES
KADEMLIA_SEARCH_NOTES_RES
KADEMLIA2_SEARCH_RES
3.2.2Publish相关协议:
KADEMLIA_PUBLISH_REQ//UnUsed(老的协议)
KADEMLIA_PUBLISH_NOTES_REQ
KADEMLIA2_PUBLISH_KEY_REQ
KADEMLIA2_PUBLISH_SOURCE_REQ
KADEMLIA2_PUBLISH_NOTES_REQ
KADEMLIA_PUBLISH_RES
KADEMLIA_PUBLISH_NOTES_RES
KADEMLIA2_PUBLISH_RES
四、EmuleBuddy机制分析
Emule中的Buddy机制是为了增进Emule中HihgId-LowId/LowId-LowId的通信,使得一个公网的Peer可以和处于NAT内的Peer之间相互通信,同时加上适当的策略,也可以让两个处于NAT内的Peer之间相互通信。
下面是关于EmuleBuddy的一些分析结论:
⏹LowId发现自己处于NAT内时,则主动开始在Kad网络内寻找Buddy,如果一个HighId没有为别的LowId做Buddy,则可以成为该LowId的Buddy。
⏹LowId的Buddy必须是HighId,反之,HighId的Buddy必须是LowId。
⏹目前,0.47c版本的Buddy机制还是一对一。
⏹LowId不是在自己的KadId周围附近找Buddy,是在KadId~方向找自己的Buddy,这样可以增进Kad网络的交互,不会引起小范围内的信息孤岛现象。
⏹一个LowId拿到HighId的Buddy后就可以向Kad网络内发布自己的Peer信息了。
〔发布信息包含:
自己的KadId~,BuddyIP,BuddyUdpPort〕
第一次的FINDBUDY必须是在程序启动后的五分钟之后,因为之后的FINDBUDDY是在丢失了BUDDY之后进行(但同时)
4.1网络协议包序列图:
4.2FindBuddy过程状态图
4.3Buddy实现框架代码List:
#LowId(A)
①发送KADEMLIA_FINDBUDDY_REQ
CSearch:
:
StorePacket()
{
CaseFINDBUDDY:
//packetparam:
<128bitTarget(Low.AKadId~)>
CKademlia:
:
GetUDPListener()->SendPacket(&m_pfileSearchTerms,KADEMLIA_FINDBUDDY_REQ,pFromContact->GetIPAddress(),pFromContact->GetUDPPort());
}
②接收KADEMLIA_FINDBUDDY_RES
CKademliaUDPListener:
:
Process_KADEMLIA_FINDBUDDY_RES(constbyte*pbyPacketData,uint32uLenPacket,uint32uIP,uint16uUDPPort)
{
theApp.clientlist->RequestBuddy(&contact);//nowPeer.BKadStateisKS_QUEUED_BUDDY
}
③Low.ATryToConnecttoHigh.B
CClietList:
:
Process(...)
{
cur_client->SetKadState(KS_CONNECTING_BUDDY);//Peer.BKadStateChangedtoKS_CONNECTING_BUDDY
cur_client->TryToConnect(true);//Low.ATryToConnecttoHigh.B
}
④Low.A连接High.B成功
CUpDownClient:
:
ConnectionEstablished()
{
…
caseKS_CONNECTING_BUDDY:
SetKadState(KS_CONNECTED_BUDDY);//Peer.BKadStatechangedtoKS_CONNECTED_BUDDY
}
#HighId(B)
①接收KADEMLIA_FINDBUDDY_REQ
CKademliaUDPListener:
:
Process_KADEMLIA_FINDBUDDY_REQ(constbyte*pbyPacketData,uint32uLenPacket,uint32uIP,uint16uUDPPort)
{
theApp.clientlist->IncomingBuddy(&contact,&BuddyID);//Peer.AKadStateisKS_INCOMING_BUDDY
//回发KADEMLIA_FINDBUDDY_RESpacket
//packetparam:
SendPacket(&fileIO2,KADEMLIA_FINDBUDDY_RES,uIP,uUDPPort);
}
②
CUpDownClient:
:
ConectionEstablished()
{
caseKS_INCOMING_BUDDY:
SetKadState(KS_CONNECTED_BUDDY);//Peer.AKadStatechangedtoKS_CONNECTED_BUDDY
}
五、EmuleKad数据结构分析
附录1(OPCodeList):
关于KAD的Opcodes,Kad1.0个2.0相互对应
//KADEMLIA(opcodes)(udp)
#defineKADEMLIA_BOOTSTRAP_REQ0x00//
#defineKADEMLIA2_BOOTSTRAP_REQ0x01//
#defineKADEMLIA_BOOTSTRAP_RES0x08//*(CNT)
#defineKADEMLIA2_BOOTSTRAP_RES0x09//
#defineKADEMLIA_HELLO_REQ0x10//
#defineKADEMLIA2_HELLO_REQ0x11//
#defineKADEMLIA_HELLO_RES0x18//
#defineKADEMLIA2_HELLO_RES0x19//
#defineKADEMLIA_REQ0x20//
#defineKADEMLIA2_REQ0x21//
#defineKADEMLIA_RES0x28//*(CNT)
#defineKADEMLIA2_RES0x29//
#defineKADEMLIA_SEARCH_REQ0x30//[ext]
//#defineUNUSED0x31//OldOpcode,don'tuse.
#defineKADEMLIA_SEARCH_NOTES_REQ0x32//
#defineKADEMLIA2_SEARCH_KEY_REQ0x33//
#defineKADEMLIA2_SEARCH_SOURCE_REQ0x34//
#defineKADEMLIA2_SEARCH_NOTES_REQ0x35//
#defineKADEMLIA_SEARCH_RES0x38//(*(CNT2))*(CNT1)
//#defineUNUSED0x39//OldOpcode,don'tuse.
#defineKADEMLIA_SEARCH_NOTES_RES0x3A//(*(CNT2))*(CNT1)
#defineKADEMLIA2_SEARCH_RES0x3B//
#defineKADEMLIA_PUBLISH_REQ0x40//