diff options
Diffstat (limited to 'node')
-rw-r--r-- | node/Constants.hpp | 17 | ||||
-rw-r--r-- | node/IncomingPacket.cpp | 4 | ||||
-rw-r--r-- | node/Peer.hpp | 28 |
3 files changed, 49 insertions, 0 deletions
diff --git a/node/Constants.hpp b/node/Constants.hpp index fddfce6a..b85c1b93 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -275,6 +275,23 @@ #define ZT_MULTIPATH_BINDER_REFRESH_PERIOD 5000 /** + * Time horizon for VERB_QOS_MEASUREMENT and VERB_ACK packet processesing cutoff + */ +#define ZT_PATH_QOS_ACK_CUTOFF_TIME 30000 + +/** + * Maximum number of VERB_QOS_MEASUREMENT and VERB_ACK packets allowed to be + * processesed within cutoff time. Separate totals are kept for each type but + * the limit is the same for both. + * + * This limits how often this peer will compute statistical estimates + * of various QoS measures from a VERB_QOS_MEASUREMENT or VERB_ACK packets to + * CUTOFF_LIMIT times per CUTOFF_TIME milliseconds per peer to prevent + * this from being useful for DOS amplification attacks. + */ +#define ZT_PATH_QOS_ACK_CUTOFF_LIMIT 16 + +/** * Path choice history window size. This is used to keep track of which paths were * previously selected so that we can maintain a target allocation over time. */ diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index c6d19021..70dcff5d 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -204,6 +204,8 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar bool IncomingPacket::_doACK(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer) { + if (!peer->rateGateACK(RR->node->now())) + return true; /* Dissect incoming ACK packet. From this we can estimate current throughput of the path, establish known * maximums and detect packet loss. */ if (peer->localMultipathSupport()) { @@ -220,6 +222,8 @@ bool IncomingPacket::_doACK(const RuntimeEnvironment *RR,void *tPtr,const Shared } bool IncomingPacket::_doQOS_MEASUREMENT(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer) { + if (!peer->rateGateQoS(RR->node->now())) + return true; /* Dissect incoming QoS packet. From this we can compute latency values and their variance. * The latency variance is used as a measure of "jitter". */ if (peer->localMultipathSupport()) { diff --git a/node/Peer.hpp b/node/Peer.hpp index 6e2f1d08..8c2c496b 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -524,6 +524,30 @@ public: } /** + * Rate limit gate for VERB_QOS_MEASUREMENT + */ + inline bool rateGateQoS(const int64_t now) + { + if ((now - _lastQoSReceive) <= ZT_PATH_QOS_ACK_CUTOFF_TIME) + ++_QoSCutoffCount; + else _QoSCutoffCount = 0; + _lastQoSReceive = now; + return (_QoSCutoffCount < ZT_PATH_QOS_ACK_CUTOFF_LIMIT); + } + + /** + * Rate limit gate for VERB_ACK + */ + inline bool rateGateACK(const int64_t now) + { + if ((now - _lastACKReceive) <= ZT_PATH_QOS_ACK_CUTOFF_TIME) + ++_ACKCutoffCount; + else _ACKCutoffCount = 0; + _lastACKReceive = now; + return (_ACKCutoffCount < ZT_PATH_QOS_ACK_CUTOFF_LIMIT); + } + + /** * Serialize a peer for storage in local cache * * This does not serialize everything, just non-ephemeral information. @@ -620,6 +644,8 @@ private: int64_t _lastComRequestSent; int64_t _lastCredentialsReceived; int64_t _lastTrustEstablishedPacketReceived; + int64_t _lastQoSReceive; + int64_t _lastACKReceive; int64_t _lastSentFullHello; int64_t _lastPathPrune; @@ -635,6 +661,8 @@ private: unsigned int _directPathPushCutoffCount; unsigned int _credentialsCutoffCount; + unsigned int _QoSCutoffCount; + unsigned int _ACKCutoffCount; AtomicCounter __refCount; |