Browse Source

add optional rate limit

Marcus Scharf 6 years ago
parent
commit
7ac0b9ccd1
3 changed files with 44 additions and 0 deletions
  1. 2 0
      README.md
  2. 2 0
      config.json.example
  3. 40 0
      ext-respondd.py

+ 2 - 0
README.md

@@ -29,6 +29,8 @@ Copy `config.json.example` to `config.json` and change it to match your server c
  * `mesh-wlan` (array of string) (Optional: Ad-Hoc batman-Mesh)
  * `mesh-vpn` (array of string) (Optional: fastd, GRE, L2TP batman-Mesh)
  * `fastd_socket` (string) (Optional: needed for uplink-flag)
+ * `rate_limit` (integer) (Optional: limit incoming requests per minutes)
+ * `rate_limit_burst` (integer) (Optional: allow burst requests)
 
 ### alias.json
 Aliases to overwrite the returned server data.  

+ 2 - 0
config.json.example

@@ -4,5 +4,7 @@
   "mesh-vpn": [ "mesh-vpn" ],
   "mesh-wlan": [ "ibss0", "mesh0" ],
   "fastd_socket": "/var/run/fastd.mesh_vpn.socket"
+  "rate_limit": 30,
+  "rate_limit_burst": 10
 }
 

+ 40 - 0
ext-respondd.py

@@ -11,6 +11,7 @@ import struct
 import subprocess
 import argparse
 import re
+import time
 
 # Force encoding to UTF-8
 import locale                                         # Ensures that subsequent open()s
@@ -41,6 +42,34 @@ def merge(a, b):
 
     return a if b is None else b
 
+class rateLimit: # rate limit like iptables limit (per minutes)
+  tLast = None
+
+  def __init__(self, _rate_limit, _rate_burst):
+    self.rate_limit = _rate_limit
+    self.rate_burst = _rate_burst
+    self.bucket = _rate_burst
+
+  def limit(self):
+    tNow = time.time()
+
+    if self.tLast is None:
+      self.tLast = tNow
+      return True
+
+    tDiff = tNow - self.tLast
+    self.tLast = tNow
+
+    self.bucket+= (tDiff / (60 / self.rate_limit))
+    if self.bucket > self.rate_burst:
+      self.bucket = self.rate_burst
+
+    if self.bucket >= 1:
+      self.bucket-= 1
+      return True
+    else:
+      return False
+
 def getGateway():
 #/sys/kernel/debug/batman_adv/bat0/gateways
     output = subprocess.check_output(["batctl", "-m", config['batman'], "gwl", "-n"])
@@ -393,6 +422,10 @@ def createNeighbours():
 def sendResponse(request, compress):
     json_data = {}
 
+    if not RateLimit is None and not RateLimit.limit():
+        print("rate limit reached!")
+        return
+
 #https://github.com/freifunk-gluon/packages/blob/master/net/respondd/src/respondd.c
     if request == 'statistics':
         json_data[request] = createStatistics()
@@ -468,6 +501,13 @@ sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
 sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, group)
 sock.bind(('::', port))
 
+if 'rate_limit' in config:
+  if not 'rate_limit_burst' in config:
+    config['rate_limit_burst'] = 10
+  RateLimit = rateLimit(config['rate_limit'], config['rate_limit_burst'])
+else:
+  RateLimit = None
+
 # =========================================================
 
 while True: