浏览代码

* repeater: onAnonDataRecv(), now rejecting non-ASCII password (preparing for future request codes)
* repeater: DISCOVER requests now with a simple RateLimiter (max 4, every 2 minutes)

Scott Powell 9 月之前
父节点
当前提交
09eab330a2
共有 3 个文件被更改,包括 36 次插入4 次删除
  1. 11 4
      examples/simple_repeater/MyMesh.cpp
  2. 2 0
      examples/simple_repeater/MyMesh.h
  3. 23 0
      examples/simple_repeater/RateLimiter.h

+ 11 - 4
examples/simple_repeater/MyMesh.cpp

@@ -433,7 +433,14 @@ void MyMesh::onAnonDataRecv(mesh::Packet *packet, const uint8_t *secret, const m
     memcpy(&timestamp, data, 4);
 
     data[len] = 0;  // ensure null terminator
-    uint8_t reply_len = handleLoginReq(sender, secret, timestamp, &data[4]);
+    uint8_t reply_len;
+    if (data[0] == 0 || data[0] >= ' ') {   // is password, ie. a login request
+      reply_len = handleLoginReq(sender, secret, timestamp, &data[4]);
+    //} else if (data[0] == ANON_REQ_TYPE_*) {   // future type codes
+      // TODO
+    } else {
+      reply_len = 0;  // unknown request type
+    }
 
     if (reply_len == 0) return;   // invalid request
 
@@ -616,8 +623,7 @@ bool MyMesh::onPeerPathRecv(mesh::Packet *packet, int sender_idx, const uint8_t
 
 void MyMesh::onControlDataRecv(mesh::Packet* packet) {
   uint8_t type = packet->payload[0] & 0xF0;    // just test upper 4 bits
-  if (type == CTL_TYPE_NODE_DISCOVER_REQ && packet->payload_len >= 6) {
-    // TODO: apply rate limiting to these!
+  if (type == CTL_TYPE_NODE_DISCOVER_REQ && packet->payload_len >= 6 && discover_limiter.allow(rtc_clock.getCurrentTime())) {
     int i = 1;
     uint8_t  filter = packet->payload[i++];
     uint32_t tag;
@@ -646,7 +652,8 @@ void MyMesh::onControlDataRecv(mesh::Packet* packet) {
 MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondClock &ms, mesh::RNG &rng,
                mesh::RTCClock &rtc, mesh::MeshTables &tables)
     : mesh::Mesh(radio, ms, rng, rtc, *new StaticPoolPacketManager(32), tables),
-      _cli(board, rtc, sensors, &_prefs, this), telemetry(MAX_PACKET_PAYLOAD - 4), region_map(key_store), temp_map(key_store)
+      _cli(board, rtc, sensors, &_prefs, this), telemetry(MAX_PACKET_PAYLOAD - 4), region_map(key_store), temp_map(key_store),
+      discover_limiter(4, 120)  // max 4 every 2 minutes
 #if defined(WITH_RS232_BRIDGE)
       , bridge(&_prefs, WITH_RS232_BRIDGE, _mgr, &rtc)
 #endif

+ 2 - 0
examples/simple_repeater/MyMesh.h

@@ -33,6 +33,7 @@
 #include <helpers/StatsFormatHelper.h>
 #include <helpers/TxtDataHelpers.h>
 #include <helpers/RegionMap.h>
+#include "RateLimiter.h"
 
 #ifdef WITH_BRIDGE
 extern AbstractBridge* bridge;
@@ -92,6 +93,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
   RegionMap region_map, temp_map;
   RegionEntry* load_stack[8];
   RegionEntry* recv_pkt_region;
+  RateLimiter discover_limiter;
   bool region_load_active;
   unsigned long dirty_contacts_expiry;
 #if MAX_NEIGHBOURS

+ 23 - 0
examples/simple_repeater/RateLimiter.h

@@ -0,0 +1,23 @@
+#pragma once
+
+#include <stdint.h>
+
+class RateLimiter {
+  uint32_t _start_timestamp;
+  uint32_t _secs;
+  uint16_t _maximum, _count;
+
+public:
+  RateLimiter(uint16_t maximum, uint32_t secs): _maximum(maximum), _secs(secs), _start_timestamp(0), _count(0) { }
+
+  bool allow(uint32_t now) {
+    if (now < _start_timestamp + _secs) {
+      _count++;
+      if (_count > _maximum) return false;   // deny
+    } else {   // time window now expired
+      _start_timestamp = now;
+      _count = 1;
+    }
+    return true;
+  }
+};