summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
Diffstat (limited to 'node')
-rw-r--r--node/Constants.hpp17
-rw-r--r--node/IncomingPacket.cpp4
-rw-r--r--node/Peer.hpp28
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;