Emule Kad 网络分析Word下载.docx
《Emule Kad 网络分析Word下载.docx》由会员分享,可在线阅读,更多相关《Emule Kad 网络分析Word下载.docx(15页珍藏版)》请在冰豆网上搜索。
#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
ThesenderTCPPort
1B
0x08KADEMLIA_BOOTSTRAP_RES
PacketParam:
返回20个Peer信息+自己的信息
KADEMLIA2_BOOTSTRAP_REQ
KADEMLIA2_BOOTSTRAP_RES
2.2HelloReq/Res
0x10KADEMLIA_HELLO_REQ
总共发送2B+25B,参照CKademliaUDPListener:
OP_KADEMLIAHEADER
byOpcode
0x18KADEMLIA_HELLO_RES
回应KADEMLIA_HELLO_REQ,协议包格式和KADEMLIA_HELLO_REQ一样
KADEMLIA2_HELLO_REQ
参照CKademliaUDPListener:
16B
TheSenderKadId
KADEMLIA_VERSION
TagCount
(2)
1B+32B
TAG_USER_COUNT(uint32)
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)
SearchTye
TargetHash
当前Contacting的ContactID
0x28KADEMLIA_RES
返回更接近一个hashvalue的Contact信息,
这样我们可以获得更加逼近hash的Contact信息,也就是说我们更加有可能找到含有这个hash信息的Contact〔回应方不管具体的Search类型,只是把有更接近Target的Contact发送给请求方〕
参考CKademliaUDPListener:
Process_KADEMLIA_REQ
和CKademliaUDPListener:
Process_KADEMLIA_RES
TargetUINT128
更接近Target的ContactCount
//Maxcountis32.size817..//16B+1B+25B(32)
n*25B
ContactID
IP
UDPPort
TCPPort
Type(发送这个信息时有填写ContactType值,但Response中处理的时候好像没处理)
Kad2.0
0x21KADEMLIA2_REQ
参考CSearch:
0x29KADEMLIA2_RES
Process_KADEMLIA2_REQ
Process_KADEMLIA2_RES
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~)>
<
Low.AClientHash>
Low.APort>
0x5aKADEMLIA_FINDBUDDY_RES
Low.AKadId~>
High.BClientHash>
High.BPort>
//B在接收到了FINDBUDDY_REQ之后,立即回答自己的TCPPort
Buddy之间互相保持通信联系:
OP_BUDDYPINGParam<
NULL>
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
说明
FILE
KEYWORD
NOTES
FINDSOURCE
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()
|->
SendFindValue(...)
JumpStart()
SendFindValue
ProcessResponse
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()
|->
JumpStart()
|->
StorePacket()
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.2FindBuddy过程状态图
4.3Buddy实现框架代码List:
#LowId(A)
①发送KADEMLIA_FINDBUDDY_REQ
StorePacket()
{
CaseFINDBUDDY:
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成功
ConnectionEstablished()
…
caseKS_CONNECTING_BUDDY:
SetKadState(KS_CONNECTED_BUDDY);
//Peer.BKadStatechangedtoKS_CONNECTED_BUDDY
#HighId(B)
①接收KADEMLIA_FINDBUDDY_REQ
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);
②
ConectionEstablished()
caseKS_INCOMING_BUDDY:
//Peer.AKadStatechangedtoKS_CONNECTED_BUDDY
}
五、EmuleKad数据结构分析
关于KAD的Opcodes,Kad1.0个2.0相互对应
//KADEMLIA(opcodes)(udp)
#defineKADEMLIA_BOOTSTRAP_REQ0x00//<
PEER(sender)[25]>
#defineKADEMLIA2_BOOTSTRAP_REQ0x01//
#defineKADEMLIA_BOOTSTRAP_RES0x08//<
CNT[2]>
PEER[25]>
*(CNT)
#defineKADEMLIA2_BOOTSTRAP_RES0x09//
#defineKADEMLIA_HELLO_REQ0x10//<
#defineKADEMLIA2_HELLO_REQ0x11//
#defineKADEMLIA_HELLO_RES0x18//<
PEER(receiver)[25]>
#defineKADEMLIA2_HELLO_RES0x19//
#defineKADEMLIA_REQ0x20//<
TYPE[1]>
HASH(target)[16]>
HASH(receiver)16>
#defineKADEMLIA2_REQ0x21//
#defineKADEMLIA_RES0x28//<
CNT>
#defineKADEMLIA2_RES0x29//
#defineKADEMLIA_SEARCH_REQ0x30//<
HASH(key)[16]>
ext0/1[1]>
SEARCH_TREE>
[ext]
//#defineUNUSED0x31//OldOpcode,don'
tuse.
#defineKADEMLIA_SEARCH_NOTES_REQ0x32//<
#defineKADEMLIA2_SEARCH_KEY_REQ0x33//
#defineKADEMLIA2_SEARCH_SOURCE_REQ0x34//
#defineKADEMLIA2_SEARCH_NOTES_REQ0x35//
#defineKADEMLIA_SEARCH_RES0x38//<
CNT1[2]>
(<
HASH(answer)[16]>
CNT2[2]>
META>
*(CNT2))*(CNT1)
//#defineUNUSED0x39//OldOpcode,don'
#defineKADEMLIA_SEARCH_NOTES_RES0x3A//<
#defineKADEMLIA2_SEARCH_RES0x3B//
#defineKADEMLIA_PUBLISH_REQ0x40//