Ver Fonte

Added rate gates for QOS and ACK packets

Joseph Henry há 7 anos atrás
pai
commit
b6d97af451
3 ficheiros alterados com 49 adições e 0 exclusões
  1. 17 0
      node/Constants.hpp
  2. 4 0
      node/IncomingPacket.cpp
  3. 28 0
      node/Peer.hpp

+ 17 - 0
node/Constants.hpp

@@ -274,6 +274,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.

+ 4 - 0
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()) {

+ 28 - 0
node/Peer.hpp

@@ -523,6 +523,30 @@ public:
 		return false;
 	}
 
+	/**
+	 * 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
 	 *
@@ -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;