📄 kademliaudplistener.cpp
字号:
DebugSend(Kad2Ping, ip, port); SendNullPacket(KADEMLIA2_PING, ip, port, senderKey, NULL); } if (addedOrUpdated && !validReceiverKey && contactVersion < 7 && !HasActiveLegacyChallenge(ip)) { // we need to verify this contact but it doesn't support HELLO_RES_ACK nor keys, do a little workaround SendLegacyChallenge(ip, port, contactID, true); } // Check if firewalled if (CKademlia::GetPrefs()->GetRecheckIP()) { FirewalledCheck(ip, port, senderKey, contactVersion); }}// KADEMLIA_HELLO_RES// Used in Kad1.0 onlyvoid CKademliaUDPListener::ProcessHelloResponse(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port){ CHECK_TRACKED_PACKET(KADEMLIA_HELLO_REQ); // Verify packet is expected size CHECK_PACKET_EXACT_SIZE(25); // Add or Update contact. bool validReceiverKey = false; CUInt128 contactID; bool addedOrUpdated = AddContact(packetData, lenPacket, ip, port, 0, 0, validReceiverKey, true, &contactID); if (addedOrUpdated && !validReceiverKey) { // even though this is supposably an answer to a request from us, there are still possibilities to spoof // it, as long as the attacker knows that we would send a HELLO_REQ (which in this case is quite often), // so for old Kad Version which doesn't support keys, we need SendLegacyChallenge(ip, port, contactID, false); }}// KADEMLIA2_HELLO_RES_ACK// Used in Kad2.0 onlyvoid CKademliaUDPListener::Process2HelloResponseAck(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, bool validReceiverKey){ CHECK_PACKET_MIN_SIZE(17); CHECK_TRACKED_PACKET(KADEMLIA2_HELLO_RES); if (!validReceiverKey) { AddDebugLogLineM(false, logClientKadUDP, wxT("Receiver key is invalid! (sender: ") + Uint32toStringIP(wxUINT32_SWAP_ALWAYS(ip)) + wxT(")")); return; } // Additional packet to complete a three-way-handshake, making sure the remote contact is not using a spoofed ip. CMemFile bio(packetData, lenPacket); CUInt128 remoteID = bio.ReadUInt128(); if (!CKademlia::GetRoutingZone()->VerifyContact(remoteID, ip)) { AddDebugLogLineM(false, logKadRouting, wxT("Unable to find valid sender in routing table (sender: ") + Uint32toStringIP(wxUINT32_SWAP_ALWAYS(ip)) + wxT(")")); }#ifdef __DEBUG__ else { AddDebugLogLineM(false, logKadRouting, wxT("Verified contact (") + Uint32toStringIP(wxUINT32_SWAP_ALWAYS(ip)) + wxT(") by HELLO_RES_ACK")); }#endif}// KADEMLIA2_HELLO_RES// Used in Kad2.0 onlyvoid CKademliaUDPListener::Process2HelloResponse(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& senderKey, bool validReceiverKey){ CHECK_TRACKED_PACKET(KADEMLIA2_HELLO_REQ); // Add or Update contact. uint8_t contactVersion; CUInt128 contactID; bool sendACK = false; bool addedOrUpdated = AddContact2(packetData, lenPacket, ip, port, &contactVersion, senderKey, validReceiverKey, true, false, &sendACK, &contactID); if (sendACK) { // the client requested us to send an ACK packet, which proves that we're not a spoofed fake contact // fulfill his wish if (senderKey.IsEmpty()) { // but we don't have a valid sender key - there is no point to reply in this case // most likely a bug in the remote client AddDebugLogLineM(false, logClientKadUDP, wxT("Remote client demands ACK, but didn't send any sender key! (sender: ") + Uint32toStringIP(wxUINT32_SWAP_ALWAYS(ip)) + wxT(")")); } else { CMemFile packet(17); packet.WriteUInt128(CKademlia::GetPrefs()->GetKadID()); packet.WriteUInt8(0); // no tags at this time DebugSend(Kad2HelloResAck, ip, port); SendPacket(packet, KADEMLIA2_HELLO_RES_ACK, ip, port, senderKey, NULL); } } else if (addedOrUpdated && !validReceiverKey && contactVersion < 7) { // even though this is supposably an answer to a request from us, there are still possibilities to spoof // it, as long as the attacker knows that we would send a HELLO_REQ (which in this case is quite often), // so for old Kad Version which doesn't support keys, we need SendLegacyChallenge(ip, port, contactID, true); } // do we need to find out our extern port? if (CKademlia::GetPrefs()->GetExternalKadPort() == 0 && contactVersion > 5) { DebugSend(Kad2Ping, ip, port); SendNullPacket(KADEMLIA2_PING, ip, port, senderKey, NULL); } // Check if firewalled if (CKademlia::GetPrefs()->GetRecheckIP()) { FirewalledCheck(ip, port, senderKey, contactVersion); }}// KADEMLIA_REQ// Used in Kad1.0 onlyvoid CKademliaUDPListener::ProcessKademliaRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port){ // Verify packet is expected size CHECK_PACKET_EXACT_SIZE(33); // RecheckIP and firewall status if (CKademlia::GetPrefs()->GetRecheckIP()) { FirewalledCheck(ip, port, 0, 0); DebugSend(KadHelloReq, ip, port); SendMyDetails(KADEMLIA_HELLO_REQ, ip, port, 0, 0, NULL, false); } // Get target and type CMemFile bio(packetData, lenPacket); uint8_t type = bio.ReadUInt8();// bool flag1 = (type >> 6); //Reserved// bool flag2 = (type >> 7); //Reserved// bool flag3 = (type >> 8); //Reserved type &= 0x1F; if( type == 0 ) { throw wxString::Format(wxT("***NOTE: Received wrong type (0x%02x) in "), type) + wxString::FromAscii(__FUNCTION__); } // This is the target node trying to be found. CUInt128 target = bio.ReadUInt128(); CUInt128 distance(CKademlia::GetPrefs()->GetKadID()); distance.XOR(target); // This makes sure we are not mistaken identify. Some client may have fresh installed and have a new hash. CUInt128 check = bio.ReadUInt128(); if (CKademlia::GetPrefs()->GetKadID().CompareTo(check)) { return; } // Get required number closest to target ContactMap results; CKademlia::GetRoutingZone()->GetClosestTo(2, target, distance, type, &results); uint16_t count = (uint16_t)results.size(); // Write response // Max count is 32. size 817.. // 16 + 1 + 25(32) CMemFile packetdata(817); packetdata.WriteUInt128(target); packetdata.WriteUInt8((uint8_t)count); CContact *c; for (ContactMap::const_iterator it = results.begin(); it != results.end(); ++it) { c = it->second; packetdata.WriteUInt128(c->GetClientID()); packetdata.WriteUInt32(c->GetIPAddress()); packetdata.WriteUInt16(c->GetUDPPort()); packetdata.WriteUInt16(c->GetTCPPort()); packetdata.WriteUInt8(c->GetType()); } DebugSendF(wxString::Format(wxT("KadRes (count=%u)"), count), ip, port); SendPacket(packetdata, KADEMLIA_RES, ip, port, 0, NULL);}// KADEMLIA2_REQ// Used in Kad2.0 onlyvoid CKademliaUDPListener::ProcessKademlia2Request(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& senderKey){ // Get target and type CMemFile bio(packetData, lenPacket); uint8_t type = bio.ReadUInt8(); type &= 0x1F; if (type == 0) { throw wxString::Format(wxT("***NOTE: Received wrong type (0x%02x) in "), type) + wxString::FromAscii(__FUNCTION__); } // This is the target node trying to be found. CUInt128 target = bio.ReadUInt128(); // Convert Target to Distance as this is how we store contacts. CUInt128 distance(CKademlia::GetPrefs()->GetKadID()); distance.XOR(target); // This makes sure we are not mistaken identify. Some client may have fresh installed and have a new KadID. CUInt128 check = bio.ReadUInt128(); if (CKademlia::GetPrefs()->GetKadID() == check) { // Get required number closest to target ContactMap results; CKademlia::GetRoutingZone()->GetClosestTo(2, target, distance, type, &results); uint8_t count = (uint8_t)results.size(); // Write response // Max count is 32. size 817.. // 16 + 1 + 25(32) CMemFile packetdata(817); packetdata.WriteUInt128(target); packetdata.WriteUInt8(count); CContact *c; for (ContactMap::const_iterator it = results.begin(); it != results.end(); ++it) { c = it->second; packetdata.WriteUInt128(c->GetClientID()); packetdata.WriteUInt32(c->GetIPAddress()); packetdata.WriteUInt16(c->GetUDPPort()); packetdata.WriteUInt16(c->GetTCPPort()); packetdata.WriteUInt8(c->GetVersion()); //<- Kad Version inserted to allow backward compatibility. } DebugSendF(wxString::Format(wxT("Kad2Res (count=%u)"), count), ip, port); SendPacket(packetdata, KADEMLIA2_RES, ip, port, senderKey, NULL); }}// KADEMLIA_RES// Used in Kad1.0 onlyvoid CKademliaUDPListener::ProcessKademliaResponse(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port){ // Verify packet is expected size CHECK_PACKET_MIN_SIZE(17); CHECK_TRACKED_PACKET(KADEMLIA_REQ); // Used Pointers CRoutingZone *routingZone = CKademlia::GetRoutingZone(); if (CKademlia::GetPrefs()->GetRecheckIP()) { FirewalledCheck(ip, port, 0, 0); DebugSend(KadHelloReq, ip, port); SendMyDetails(KADEMLIA_HELLO_REQ, ip, port, 0, 0, NULL, false); } // What search does this relate to CMemFile bio(packetData, lenPacket); CUInt128 target = bio.ReadUInt128(); uint8_t numContacts = bio.ReadUInt8(); // Is this one of our legacy challenge packets? CUInt128 contactID; if (IsLegacyChallenge(target, ip, KADEMLIA_REQ, contactID)) { // yup it is, set the contact as verified if (!routingZone->VerifyContact(contactID, ip)) { AddDebugLogLineM(false, logKadRouting, wxT("Unable to find valid sender in routing table (sender: ") + Uint32toStringIP(wxUINT32_SWAP_ALWAYS(ip)) + wxT(")")); }#ifdef __DEBUG__ else { AddDebugLogLineM(false, logClientKadUDP, wxT("Verified contact with legacy challenge (KadReq) - ") + Uint32toStringIP(wxUINT32_SWAP_ALWAYS(ip))); }#endif return; // we do not actually care for its other content } // Verify packet is expected size CHECK_PACKET_EXACT_SIZE(16+1 + (16+4+2+2+1)*numContacts); CScopedPtr<ContactList> results(new ContactList); for (uint16_t i = 0; i < numContacts; i++) { CUInt128 id = bio.ReadUInt128(); uint32_t contactIP = bio.ReadUInt32(); uint16_t contactPort = bio.ReadUInt16(); uint16_t tport = bio.ReadUInt16(); bio.ReadUInt8(); uint32_t hostIP = wxUINT32_SWAP_ALWAYS(contactIP); if(::IsGoodIPPort(hostIP, contactPort) && contactPort != 53 /*No DNS Port without encryption*/) { if (!theApp->ipfilter->IsFiltered(hostIP)) { bool verified = false; // we are now setting all version for received contact to "2" which means we assume full Kad2 when adding // the contact to the routing table. If this should be an old Kad1 contact, we won't be able to keep it, but // we avoid having to send double hello packets to the 90% Kad2 nodes // This is the first step of dropping Kad1 support routingZone->AddUnfiltered(id, contactIP, contactPort, tport, 2, 0, verified, false, false, false); results->push_back(new CContact(id, contactIP, contactPort, tport, 0, 0, false, target)); } } } CSearchManager::ProcessResponse(target, ip, port, results.release());}// KADEMLIA2_RES// Used in Kad2.0 onlyvoid CKademliaUDPListener::ProcessKademlia2Response(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& WXUNUSED(senderKey)){ CHECK_TRACKED_PACKET(KADEMLIA2_REQ); // Used Pointers CRoutingZone *routingZone = CKademlia::GetRoutingZone(); // don't do firewallchecks on this opcode anymore, since we need the contacts kad version - hello opcodes are good enough// if (CKademlia::GetPrefs()->GetRecheckIP()) {// FirewalledCheck(ip, port, senderKey);// DebugSend(Kad2HelloReq, ip, port);// SendMyDetails(KADEMLIA2_HELLO_REQ, ip, port, true, senderKey, NULL);// } // What search does this relate to CMemFile bio(packetData, lenPacket); CUInt128 target = bio.ReadUInt128(); uint8_t numContacts = bio.ReadUInt8(); // Is this one of our legacy challenge packets? CUInt128 contactID; if (IsLegacyChallenge(target, ip, KADEMLIA2_REQ, contactID)) { // yup it is, set the contact as verified if (!routingZone->VerifyContact(contactID, ip)) { AddDebugLogLineM(false, logKadRouting, wxT("Unable to find valid sender in routing table (sender: ") + Uint32toStringIP(wxUINT32_SWAP_ALWAYS(ip)) + wxT(")")); }#ifdef __DEBUG__ else { AddDebugLogLineM(false, logClientKadUDP, wxT("Verified contact with legacy challenge (Kad2Req) - ") + Uint32toStringIP(wxUINT32_SWAP_ALWAYS(ip))); }#endif return; // we do not actually care for its other content } // Verify packet is expected size CHECK_PACKET_EXACT_SIZE(16+1 + (16+4+2+2+1)*numContacts); // is this a search for firewallcheck ips? bool isFirewallUDPCheckSearch = false; if (CUDPFirewallTester::IsFWCheckUDPRunning() && CSearchManager::IsFWCheckUDPSearch(target)) { isFirewallUDPCheckSearch = true; } CScopedPtr<ContactList> results(new ContactList); for (uint8_t i = 0; i < numContacts; i++) { CUInt128 id = bio.ReadUInt128(); uint32_t contactIP = bio.ReadUInt32(); uint16_t contactPort = bio.ReadUInt16(); uint16_t tport = bio.ReadUInt16(); uint8_t version = bio.ReadUInt8(); uint32_t hostIP = wxUINT32_SWAP_ALWAYS(contactIP); if (::IsGoodIPPort(hostIP, contactPort)) { if (!theApp->ipfilter->IsFiltered(hostIP) && !(contactPort == 53 && version <= 5) /*No DNS Port without encryption*/) { if (isFirewallUDPCheckSearch) { // UDP FirewallCheck searches are special. The point is we need an IP which we didn't sent an UDP message yet // (or in the near future), so we do not try to add those contacts to our routingzone and we also don't // deliver them back to the searchmanager (because he would UDP-ask them for further results), but only report // them to FirewallChecker - this will of course cripple the search but thats not the point, since we only // care for IPs and not the random set target CUDPFirewallTester::AddPossibleTestContact(id, contactIP, contactPort, tport, target, version, 0, false); } else { bool verified = false; routingZone->AddUnfiltered(id, contactIP, contactPort, tport, version, 0, verified, false, false, false); results->push_back(new CContact(id, contactIP, contactPort, tport, version, 0, false, target)); } } } } CSearchManager::ProcessResponse(target, ip, port, results.release());}void CKademliaUDPListener::Free(SSearchTerm* pSearchTerms){ if (pSearchTerms) { Free(pSearchTerms->left); Free(pSearchTerms->right); delete pSearchTerms; }}SSearchTerm* CKademliaUDPListener::CreateSearchExpressionTree(CMemFile& bio, int iLevel){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -