/* * Stores outgoing request to avoid receiving invalid responses */ void Utils::trackOutgoingPacket(const string& ip, const AdcCommand& cmd) { Lock l(cs); uint64_t now = GET_TICK(); switch(cmd.getCommand()) { // request packets case AdcCommand::CMD_SCH: case AdcCommand::CMD_PUB: case AdcCommand::CMD_INF: case AdcCommand::CMD_CTM: case AdcCommand::CMD_GET: case AdcCommand::CMD_PSR: OutPacket p = { ip, now, cmd.getCommand() }; sentPackets.push_back(p); break; } // clean up old items // list is sorted by time, so the first unmatched item can break the loop while(!sentPackets.empty()) { uint64_t diff = now - sentPackets.front().time; if(diff >= TIME_FOR_RESPONSE) sentPackets.pop_front(); else break; } }
/* * General flooding protection */ bool Utils::checkFlood(const string& ip, const AdcCommand& cmd) { // ignore empty commands if(cmd.getParameters().empty()) return false; // there maximum allowed request packets from one IP per minute // response packets are allowed only if request has been sent to the IP address size_t maxAllowedPacketsPerMinute = 0; uint32_t requestCmd = AdcCommand::CMD_SCH; switch(cmd.getCommand()) { // request packets case AdcCommand::CMD_SCH: maxAllowedPacketsPerMinute = 20; break; case AdcCommand::CMD_PUB: maxAllowedPacketsPerMinute = 10; break; case AdcCommand::CMD_INF: maxAllowedPacketsPerMinute = 3; break; case AdcCommand::CMD_CTM: maxAllowedPacketsPerMinute = 2; break; case AdcCommand::CMD_RCM: maxAllowedPacketsPerMinute = 2; break; case AdcCommand::CMD_GET: maxAllowedPacketsPerMinute = 2; break; case AdcCommand::CMD_PSR: maxAllowedPacketsPerMinute = 3; break; // response packets case AdcCommand::CMD_STA: return true; // STA can be response for more commands, but since it is for informative purposes only, there shouldn't be no way to abuse it case AdcCommand::CMD_SND: requestCmd = AdcCommand::CMD_GET; case AdcCommand::CMD_RES: // default value of requestCmd Lock l(cs); for(std::list<OutPacket>::iterator i = sentPackets.begin(); i != sentPackets.end(); i++) { if(i->cmd == requestCmd && i->ip == ip) { sentPackets.erase(i); return true; } } dcdebug("Received unwanted response from %s. Packet dropped.\n", ip.c_str()); return false; } Lock l(cs); std::unordered_multiset<uint32_t>& packetsPerIp = receivedPackets[ip]; packetsPerIp.insert(cmd.getCommand()); if(packetsPerIp.count(cmd.getCommand()) > maxAllowedPacketsPerMinute) { dcdebug("Request flood detected (%d) from %s. Packet dropped.\n", packetsPerIp.count(cmd.getCommand()), ip.c_str()); return false; } return true; }