mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-12-19 04:57:53 +00:00
Add a circuit breaker for VERB_PUSH_DIRECT_PATHS.
This commit is contained in:
parent
88b100e5d0
commit
cdc99bfee1
@ -319,11 +319,6 @@
|
|||||||
*/
|
*/
|
||||||
#define ZT_MIN_PATH_CONFIRMATION_INTERVAL 1000
|
#define ZT_MIN_PATH_CONFIRMATION_INTERVAL 1000
|
||||||
|
|
||||||
/**
|
|
||||||
* Interval between direct path pushes in milliseconds
|
|
||||||
*/
|
|
||||||
#define ZT_DIRECT_PATH_PUSH_INTERVAL 120000
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How long (max) to remember network certificates of membership?
|
* How long (max) to remember network certificates of membership?
|
||||||
*
|
*
|
||||||
@ -347,10 +342,29 @@
|
|||||||
*/
|
*/
|
||||||
#define ZT_MAX_BRIDGE_SPAM 16
|
#define ZT_MAX_BRIDGE_SPAM 16
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interval between direct path pushes in milliseconds
|
||||||
|
*/
|
||||||
|
#define ZT_DIRECT_PATH_PUSH_INTERVAL 120000
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum number of endpoints to contact per address type (to limit pushes like GitHub issue #235)
|
* Maximum number of endpoints to contact per address type (to limit pushes like GitHub issue #235)
|
||||||
*/
|
*/
|
||||||
#define ZT_PUSH_DIRECT_PATHS_MAX_ENDPOINTS_PER_TYPE 4
|
#define ZT_PUSH_DIRECT_PATHS_MAX_ENDPOINTS_PER_TYPE 5
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time horizon for push direct paths cutoff
|
||||||
|
*/
|
||||||
|
#define ZT_PUSH_DIRECT_PATHS_CUTOFF_TIME 60000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of direct path pushes within cutoff time
|
||||||
|
*
|
||||||
|
* This limits response to PUSH_DIRECT_PATHS to CUTOFF_LIMIT responses
|
||||||
|
* per CUTOFF_TIME milliseconds per peer to prevent this from being
|
||||||
|
* useful for DOS amplification attacks.
|
||||||
|
*/
|
||||||
|
#define ZT_PUSH_DIRECT_PATHS_CUTOFF_LIMIT 5
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A test pseudo-network-ID that can be joined
|
* A test pseudo-network-ID that can be joined
|
||||||
|
@ -901,6 +901,11 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
const uint64_t now = RR->node->now();
|
const uint64_t now = RR->node->now();
|
||||||
|
if (!peer->shouldRespondToDirectPathPush(now)) {
|
||||||
|
TRACE("dropped PUSH_DIRECT_PATHS from %s(%s): circuit breaker tripped",source().toString().c_str(),_remoteAddress.toString().c_str());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const Path *currentBest = peer->getBestPath(now);
|
const Path *currentBest = peer->getBestPath(now);
|
||||||
|
|
||||||
unsigned int count = at<uint16_t>(ZT_PACKET_IDX_PAYLOAD);
|
unsigned int count = at<uint16_t>(ZT_PACKET_IDX_PAYLOAD);
|
||||||
|
@ -55,6 +55,7 @@ Peer::Peer(const Identity &myIdentity,const Identity &peerIdentity)
|
|||||||
_lastAnnouncedTo(0),
|
_lastAnnouncedTo(0),
|
||||||
_lastPathConfirmationSent(0),
|
_lastPathConfirmationSent(0),
|
||||||
_lastDirectPathPushSent(0),
|
_lastDirectPathPushSent(0),
|
||||||
|
_lastDirectPathPushReceive(0),
|
||||||
_lastPathSort(0),
|
_lastPathSort(0),
|
||||||
_vProto(0),
|
_vProto(0),
|
||||||
_vMajor(0),
|
_vMajor(0),
|
||||||
@ -63,6 +64,7 @@ Peer::Peer(const Identity &myIdentity,const Identity &peerIdentity)
|
|||||||
_id(peerIdentity),
|
_id(peerIdentity),
|
||||||
_numPaths(0),
|
_numPaths(0),
|
||||||
_latency(0),
|
_latency(0),
|
||||||
|
_directPathPushCutoffCount(0),
|
||||||
_networkComs(4),
|
_networkComs(4),
|
||||||
_lastPushedComs(4)
|
_lastPushedComs(4)
|
||||||
{
|
{
|
||||||
|
@ -431,6 +431,27 @@ public:
|
|||||||
_numPaths = y;
|
_numPaths = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update direct path push stats and return true if we should respond
|
||||||
|
*
|
||||||
|
* This is a circuit breaker to make VERB_PUSH_DIRECT_PATHS not particularly
|
||||||
|
* useful as a DDOS amplification attack vector. Otherwise a malicious peer
|
||||||
|
* could send loads of these and cause others to bombard arbitrary IPs with
|
||||||
|
* traffic.
|
||||||
|
*
|
||||||
|
* @param now Current time
|
||||||
|
* @return True if we should respond
|
||||||
|
*/
|
||||||
|
inline bool shouldRespondToDirectPathPush(const uint64_t now)
|
||||||
|
{
|
||||||
|
Mutex::Lock _l(_lock);
|
||||||
|
if ((now - _lastDirectPathPushReceive) <= ZT_PUSH_DIRECT_PATHS_CUTOFF_TIME)
|
||||||
|
++_directPathPushCutoffCount;
|
||||||
|
else _directPathPushCutoffCount = 0;
|
||||||
|
_lastDirectPathPushReceive = now;
|
||||||
|
return (_directPathPushCutoffCount >= ZT_PUSH_DIRECT_PATHS_CUTOFF_LIMIT);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a common set of addresses by which two peers can link, if any
|
* Find a common set of addresses by which two peers can link, if any
|
||||||
*
|
*
|
||||||
@ -459,7 +480,7 @@ public:
|
|||||||
const unsigned int recSizePos = b.size();
|
const unsigned int recSizePos = b.size();
|
||||||
b.addSize(4); // space for uint32_t field length
|
b.addSize(4); // space for uint32_t field length
|
||||||
|
|
||||||
b.append((uint16_t)0); // version of serialized Peer data
|
b.append((uint16_t)1); // version of serialized Peer data
|
||||||
|
|
||||||
_id.serialize(b,false);
|
_id.serialize(b,false);
|
||||||
|
|
||||||
@ -470,12 +491,14 @@ public:
|
|||||||
b.append((uint64_t)_lastAnnouncedTo);
|
b.append((uint64_t)_lastAnnouncedTo);
|
||||||
b.append((uint64_t)_lastPathConfirmationSent);
|
b.append((uint64_t)_lastPathConfirmationSent);
|
||||||
b.append((uint64_t)_lastDirectPathPushSent);
|
b.append((uint64_t)_lastDirectPathPushSent);
|
||||||
|
b.append((uint64_t)_lastDirectPathPushReceive);
|
||||||
b.append((uint64_t)_lastPathSort);
|
b.append((uint64_t)_lastPathSort);
|
||||||
b.append((uint16_t)_vProto);
|
b.append((uint16_t)_vProto);
|
||||||
b.append((uint16_t)_vMajor);
|
b.append((uint16_t)_vMajor);
|
||||||
b.append((uint16_t)_vMinor);
|
b.append((uint16_t)_vMinor);
|
||||||
b.append((uint16_t)_vRevision);
|
b.append((uint16_t)_vRevision);
|
||||||
b.append((uint32_t)_latency);
|
b.append((uint32_t)_latency);
|
||||||
|
b.append((uint16_t)_directPathPushCutoffCount);
|
||||||
|
|
||||||
b.append((uint16_t)_numPaths);
|
b.append((uint16_t)_numPaths);
|
||||||
for(unsigned int i=0;i<_numPaths;++i)
|
for(unsigned int i=0;i<_numPaths;++i)
|
||||||
@ -521,7 +544,7 @@ public:
|
|||||||
const unsigned int recSize = b.template at<uint32_t>(p); p += 4;
|
const unsigned int recSize = b.template at<uint32_t>(p); p += 4;
|
||||||
if ((p + recSize) > b.size())
|
if ((p + recSize) > b.size())
|
||||||
return SharedPtr<Peer>(); // size invalid
|
return SharedPtr<Peer>(); // size invalid
|
||||||
if (b.template at<uint16_t>(p) != 0)
|
if (b.template at<uint16_t>(p) != 1)
|
||||||
return SharedPtr<Peer>(); // version mismatch
|
return SharedPtr<Peer>(); // version mismatch
|
||||||
p += 2;
|
p += 2;
|
||||||
|
|
||||||
@ -539,12 +562,14 @@ public:
|
|||||||
np->_lastAnnouncedTo = b.template at<uint64_t>(p); p += 8;
|
np->_lastAnnouncedTo = b.template at<uint64_t>(p); p += 8;
|
||||||
np->_lastPathConfirmationSent = b.template at<uint64_t>(p); p += 8;
|
np->_lastPathConfirmationSent = b.template at<uint64_t>(p); p += 8;
|
||||||
np->_lastDirectPathPushSent = b.template at<uint64_t>(p); p += 8;
|
np->_lastDirectPathPushSent = b.template at<uint64_t>(p); p += 8;
|
||||||
|
np->_lastDirectPathPushReceive = b.template at<uint64_t>(p); p += 8;
|
||||||
np->_lastPathSort = b.template at<uint64_t>(p); p += 8;
|
np->_lastPathSort = b.template at<uint64_t>(p); p += 8;
|
||||||
np->_vProto = b.template at<uint16_t>(p); p += 2;
|
np->_vProto = b.template at<uint16_t>(p); p += 2;
|
||||||
np->_vMajor = b.template at<uint16_t>(p); p += 2;
|
np->_vMajor = b.template at<uint16_t>(p); p += 2;
|
||||||
np->_vMinor = b.template at<uint16_t>(p); p += 2;
|
np->_vMinor = b.template at<uint16_t>(p); p += 2;
|
||||||
np->_vRevision = b.template at<uint16_t>(p); p += 2;
|
np->_vRevision = b.template at<uint16_t>(p); p += 2;
|
||||||
np->_latency = b.template at<uint32_t>(p); p += 4;
|
np->_latency = b.template at<uint32_t>(p); p += 4;
|
||||||
|
np->_directPathPushCutoffCount = b.template at<uint16_t>(p); p += 2;
|
||||||
|
|
||||||
const unsigned int numPaths = b.template at<uint16_t>(p); p += 2;
|
const unsigned int numPaths = b.template at<uint16_t>(p); p += 2;
|
||||||
for(unsigned int i=0;i<numPaths;++i) {
|
for(unsigned int i=0;i<numPaths;++i) {
|
||||||
@ -588,6 +613,7 @@ private:
|
|||||||
uint64_t _lastAnnouncedTo;
|
uint64_t _lastAnnouncedTo;
|
||||||
uint64_t _lastPathConfirmationSent;
|
uint64_t _lastPathConfirmationSent;
|
||||||
uint64_t _lastDirectPathPushSent;
|
uint64_t _lastDirectPathPushSent;
|
||||||
|
uint64_t _lastDirectPathPushReceive;
|
||||||
uint64_t _lastPathSort;
|
uint64_t _lastPathSort;
|
||||||
uint16_t _vProto;
|
uint16_t _vProto;
|
||||||
uint16_t _vMajor;
|
uint16_t _vMajor;
|
||||||
@ -597,6 +623,7 @@ private:
|
|||||||
Path _paths[ZT_MAX_PEER_NETWORK_PATHS];
|
Path _paths[ZT_MAX_PEER_NETWORK_PATHS];
|
||||||
unsigned int _numPaths;
|
unsigned int _numPaths;
|
||||||
unsigned int _latency;
|
unsigned int _latency;
|
||||||
|
unsigned int _directPathPushCutoffCount;
|
||||||
|
|
||||||
struct _NetworkCom
|
struct _NetworkCom
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user