Add a rate limiting circuit breaker to the network controller to prevent flooding attacks and race conditions.

This commit is contained in:
Adam Ierymenko 2015-07-23 10:10:17 -07:00
parent 3ba54c7e35
commit b3516c599b
4 changed files with 20 additions and 1 deletions

View File

@ -64,6 +64,10 @@
// API version reported via JSON control plane
#define ZT_NETCONF_CONTROLLER_API_VERSION 1
// Drop requests for a given peer and network ID that occur more frequently
// than this (ms).
#define ZT_NETCONF_MIN_REQUEST_PERIOD 5000
namespace ZeroTier {
namespace {
@ -316,6 +320,15 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co
return NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR;
}
// Check rate limit
{
uint64_t &lrt = _lastRequestTime[std::pair<Address,uint64_t>(identity.address(),nwid)];
uint64_t lrt2 = lrt;
if (((lrt = OSUtils::now()) - lrt2) <= ZT_NETCONF_MIN_REQUEST_PERIOD)
return NetworkController::NETCONF_QUERY_IGNORE;
}
NetworkRecord network;
memset(&network,0,sizeof(network));
Utils::snprintf(network.id,sizeof(network.id),"%.16llx",(unsigned long long)nwid);

View File

@ -98,6 +98,8 @@ private:
std::string _dbPath;
std::string _instanceId;
std::map< std::pair<Address,uint64_t>,uint64_t > _lastRequestTime;
sqlite3 *_db;
sqlite3_stmt *_sGetNetworkById;

View File

@ -717,6 +717,9 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
TRACE("NETWORK_CONFIG_REQUEST failed: internal error: %s",netconf.get("error","(unknown)").c_str());
break;
case NetworkController::NETCONF_QUERY_IGNORE:
break;
default:
TRACE("NETWORK_CONFIG_REQUEST failed: invalid return value from NetworkController::doNetworkConfigRequest()");
break;

View File

@ -54,7 +54,8 @@ public:
NETCONF_QUERY_OK = 0,
NETCONF_QUERY_OBJECT_NOT_FOUND = 1,
NETCONF_QUERY_ACCESS_DENIED = 2,
NETCONF_QUERY_INTERNAL_SERVER_ERROR = 3
NETCONF_QUERY_INTERNAL_SERVER_ERROR = 3,
NETCONF_QUERY_IGNORE = 4
};
NetworkController() {}