public bool FindExternKadPort(bool bReset) { if (!bReset) { return(m_anExternPortIPs.Count < EXTERNAL_PORT_ASKIPS && !Kademlia.IsRunningInLANMode()); } else { m_anExternPortIPs.Clear(); m_anExternPorts.Clear(); return(true); } }
public Contact(UInt128 uClientID, uint uIp, ushort uUdpPort, ushort uTcpPort, byte uVersion, KadUDPKey cUDPKey, bool bIPVerified) { m_uClientID = uClientID; Kademlia.GetPrefs().GetKadID(ref m_uDistance); m_uDistance.Xor(uClientID); m_uIp = uIp; UDPPort = uUdpPort; TCPPort = uTcpPort; Version = uVersion; UDPKey = cUDPKey; IsIpVerified = bIPVerified; InitContact(); }
void SetKademliaFiles() { //There is no real way to know how many files are in the Kad network.. //So we first try to see how many files per user are in the ED2K network.. //If that fails, we use a set value based on previous tests.. uint nServerAverage = 0; //theApp.serverlist->GetAvgFile( nServerAverage ); uint nKadAverage = Kademlia.GetIndexed().GetFileKeyCount(); #if DEBUG string method; #endif if (nServerAverage > nKadAverage) { #if DEBUG method = $"Kad file estimate used Server avg({nServerAverage})"; #endif nKadAverage = nServerAverage; } #if DEBUG else { method = $"Kad file estimate used Kad avg({nKadAverage})"; } #endif if (nKadAverage < 108) { #if DEBUG method = "Kad file estimate used default avg(108)"; #endif nKadAverage = 108; } #if DEBUG //AddDebugLogLine(DLP_VERYLOW, false, method); #endif m_uKademliaFiles = nKadAverage * KademliaUsers; }
public static void Stop() { // Make sure we are running to begin with. if (!m_bRunning) { return; } //AddDebugLogLine(false, "Stopping Kademlia"); // Mark Kad as being in the stop state to make sure nothing else is used. m_bRunning = false; // Reset Firewallstate //UDPFirewallTester.Reset(); // Remove all active searches. //SearchManager.StopAllSearches(); // Delete all Kad Objects. m_pInstance.m_pUDPListener = null; m_pInstance.m_pRoutingZone = null; m_pInstance.m_pIndexed = null; m_pInstance.m_pPrefs = null; m_pInstance = null; while (!s_liBootstapList.IsEmpty()) { delete s_liBootstapList.RemoveHead(); } // Make sure all zones are removed. m_mapEvents.Clear(); }
protected bool InTrackListIsAllowedPacket(uint uIP, byte byOpcode, bool bValidSenderkey) { // this tracklist tacks _incoming_ request packets and acts as a general flood protection by dropping // too frequent requests from a single IP, avoiding response floods, processing time DOS attacks and slowing down // other possible attacks/behavior (scanning indexed files, fake publish floods, etc) // first figure out if this is a request packet to be tracked and its timelimits // timelimits are choosed by estimating the max. frequency of such packets on normal operation (+ buffer) // (those limits are not meant be fine to be used by normal usage, but only supposed to be a flood detection) uint iAllowedPacketsPerMinute; byte byDbgOrgOpcode = byOpcode; switch (byOpcode) { case Opcodes.KADEMLIA2_BOOTSTRAP_REQ: iAllowedPacketsPerMinute = 2; break; case Opcodes.KADEMLIA2_HELLO_REQ: iAllowedPacketsPerMinute = 3; break; case Opcodes.KADEMLIA2_REQ: iAllowedPacketsPerMinute = 10; break; case Opcodes.KADEMLIA2_SEARCH_NOTES_REQ: iAllowedPacketsPerMinute = 3; break; case Opcodes.KADEMLIA2_SEARCH_KEY_REQ: iAllowedPacketsPerMinute = 3; break; case Opcodes.KADEMLIA2_SEARCH_SOURCE_REQ: iAllowedPacketsPerMinute = 3; break; case Opcodes.KADEMLIA2_PUBLISH_KEY_REQ: iAllowedPacketsPerMinute = 3; break; case Opcodes.KADEMLIA2_PUBLISH_SOURCE_REQ: iAllowedPacketsPerMinute = 2; break; case Opcodes.KADEMLIA2_PUBLISH_NOTES_REQ: iAllowedPacketsPerMinute = 2; break; case Opcodes.KADEMLIA_FIREWALLED2_REQ: byOpcode = Opcodes.KADEMLIA_FIREWALLED_REQ; iAllowedPacketsPerMinute = 2; break; case Opcodes.KADEMLIA_FIREWALLED_REQ: iAllowedPacketsPerMinute = 2; break; case Opcodes.KADEMLIA_FINDBUDDY_REQ: iAllowedPacketsPerMinute = 2; break; case Opcodes.KADEMLIA_CALLBACK_REQ: iAllowedPacketsPerMinute = 1; break; case Opcodes.KADEMLIA2_PING: iAllowedPacketsPerMinute = 2; break; default: // not any request packets, so its a response packet - no further checks on this point return(true); } uint iSecondsPerPacket = 60 / iAllowedPacketsPerMinute; uint dwCurrentTick = (uint)Environment.TickCount; // time for cleaning up? if (dwCurrentTick - dwLastTrackInCleanup > Opcodes.MIN2MS(12)) { InTrackListCleanup(); } // check for existing entries TrackPacketsIn_Struct pTrackEntry; if (!m_mapTrackPacketsIn.ContainsKey(uIP)) { pTrackEntry = new TrackPacketsIn_Struct(); pTrackEntry.m_uIP = uIP; m_mapTrackPacketsIn[uIP] = pTrackEntry; m_liTrackPacketsIn.Insert(0, pTrackEntry); } else { pTrackEntry = m_mapTrackPacketsIn[uIP]; } // search specific request tracks for (int i = 0; i < pTrackEntry.m_aTrackedRequests.Count; i++) { if (pTrackEntry.m_aTrackedRequests[i].m_byOpcode == byOpcode) { // already tracked requests with theis opcode, remove already expired request counts TrackPacketsIn_Struct.TrackedRequestIn_Struct rCurTrackedRequest = pTrackEntry.m_aTrackedRequests[i]; if (rCurTrackedRequest.m_nCount > 0 && dwCurrentTick - rCurTrackedRequest.m_dwFirstAdded > Opcodes.SEC2MS(iSecondsPerPacket)) { uint nRemoveCount = (dwCurrentTick - rCurTrackedRequest.m_dwFirstAdded) / Opcodes.SEC2MS(iSecondsPerPacket); if (nRemoveCount > rCurTrackedRequest.m_nCount) { rCurTrackedRequest.m_nCount = 0; rCurTrackedRequest.m_dwFirstAdded = dwCurrentTick; // for the packet we just process } else { rCurTrackedRequest.m_nCount -= nRemoveCount; rCurTrackedRequest.m_dwFirstAdded += Opcodes.SEC2MS(iSecondsPerPacket) * nRemoveCount; } } // we increase the counter in any case, even if we drop the packet later rCurTrackedRequest.m_nCount++; // remember only for easier cleanup pTrackEntry.m_dwLastExpire = Math.Max(pTrackEntry.m_dwLastExpire, rCurTrackedRequest.m_dwFirstAdded + Opcodes.SEC2MS(iSecondsPerPacket) * rCurTrackedRequest.m_nCount); if (Kademlia.IsRunningInLANMode() && OtherFunctions.IsLANIP((uint)IPAddress.NetworkToHostOrder(uIP))) // no flood detection in LanMode { return(true); } // now the actualy check if this request is allowed if (rCurTrackedRequest.m_nCount > iAllowedPacketsPerMinute * 5) { // this is so far above the limit that it has to be an intentional flood / misuse in any case // so we take the next higher punishment and ban the IP //DebugLogWarning("Kad: Massive request flood detected for opcode 0x%X (0x%X) from IP %s - Banning IP", byOpcode, byDbgOrgOpcode, ipstr(ntohl(uIP))); //theApp.clientlist.AddBannedClient(IPAddress.NetworkToHostOrder(uIP)); return(false); // drop packet } else if (rCurTrackedRequest.m_nCount > iAllowedPacketsPerMinute) { // over the limit, drop the packet but do nothing else if (!rCurTrackedRequest.m_bDbgLogged) { rCurTrackedRequest.m_bDbgLogged = true; //DebugLog("Kad: Request flood detected for opcode 0x%X (0x%X) from IP %s - Droping packets with this opcode", byOpcode, byDbgOrgOpcode, ipstr(ntohl(uIP))); } return(false); // drop packet } else { rCurTrackedRequest.m_bDbgLogged = false; } return(true); } } // add a new entry for this request, no checks needed since 1 is always ok TrackPacketsIn_Struct.TrackedRequestIn_Struct curTrackedRequest; curTrackedRequest.m_byOpcode = byOpcode; curTrackedRequest.m_bDbgLogged = false; curTrackedRequest.m_dwFirstAdded = dwCurrentTick; curTrackedRequest.m_nCount = 1; // remember only for easier cleanup pTrackEntry.m_dwLastExpire = Math.Max(pTrackEntry.m_dwLastExpire, dwCurrentTick + Opcodes.SEC2MS(iSecondsPerPacket)); pTrackEntry.m_aTrackedRequests.Add(curTrackedRequest); return(true); }
public static void Start(Prefs pPrefs) { try { // If we already have a instance, something is wrong. if (m_pInstance != null) { Debug.Assert(m_pInstance.m_bRunning); Debug.Assert(m_pInstance.m_pPrefs != null); return; } // Make sure a prefs was passed in.. if (pPrefs == null) { return; } //AddDebugLogLine(false, "Starting Kademlia"); // Init jump start timer. m_tNextSearchJumpStart = DateTime.Now; // Force a FindNodeComplete within the first 3 minutes. m_tNextSelfLookup = DateTime.Now.AddMinutes(3); // Init status timer. m_tStatusUpdate = DateTime.Now; // Init big timer for Zones m_tBigTimer = DateTime.Now; // First Firewall check is done on connect, init next check. m_tNextFirewallCheck = DateTime.Now.AddHours(1); m_tNextUPnPCheck = m_tNextFirewallCheck.AddMinutes(-1); // Find a buddy after the first 5mins of starting the client. // We wait just in case it takes a bit for the client to determine firewall status.. m_tNextFindBuddy = DateTime.Now.AddMinutes(5); // Init contact consolidate timer; m_tConsolidate = DateTime.Now.AddMinutes(45); // Looking up our extern port m_tExternPortLookup = DateTime.Now; // Init bootstrap time. m_tBootstrap = DateTime.MinValue; // Init our random seed. srand((uint)DateTime.Now.Millisecond); // Create our Kad objects. m_pInstance = new Kademlia(); m_pInstance.m_pPrefs = pPrefs; m_pInstance.m_pUDPListener = null; m_pInstance.m_pRoutingZone = null; m_pInstance.m_pIndexed = new Indexed(); m_pInstance.m_pRoutingZone = new RoutingZone(); m_pInstance.m_pUDPListener = new KademliaUDPListener(); // Mark Kad as running state. m_bRunning = true; } catch (Exception e) { // Although this has never been an issue, maybe some just in case code // needs to be created here just in case things go real bad.. But if things // went real bad, the entire client most like is in bad shape, so this may // not be something to worry about as the client most likely will crap out anyway. //AddDebugLogLine(false, "%s", e.Message); } }