Merge #1278
1278: Limiter implementation r=kaiyou a=micw ## What type of PR? (Feature, enhancement, bug-fix, documentation) ## What does this PR do? Adds a custom limter based on the "limits" lirary that counts up on failed auths only ### Related issue(s) - closes #1195 - closes #634 ## Prerequistes - [X] Unless it's docs or a minor change: add [changelog](https://mailu.io/master/contributors/guide.html#changelog) entry file. Co-authored-by: Michael Wyraz <michael@wyraz.de> Co-authored-by: micw <michael@wyraz.de>master
commit
96f832835a
@ -0,0 +1,36 @@
|
||||
import limits
|
||||
import limits.storage
|
||||
import limits.strategies
|
||||
import ipaddress
|
||||
|
||||
class RateLimitExceeded(Exception):
|
||||
pass
|
||||
|
||||
class Limiter:
|
||||
|
||||
def __init__(self):
|
||||
self.storage = None
|
||||
self.limiter = None
|
||||
self.rate = None
|
||||
self.subnet = None
|
||||
self.rate_limit_subnet = True
|
||||
|
||||
def init_app(self, app):
|
||||
self.storage = limits.storage.storage_from_string(app.config["RATELIMIT_STORAGE_URL"])
|
||||
self.limiter = limits.strategies.MovingWindowRateLimiter(self.storage)
|
||||
self.rate = limits.parse(app.config["AUTH_RATELIMIT"])
|
||||
self.rate_limit_subnet = str(app.config["AUTH_RATELIMIT_SUBNET"])!='False'
|
||||
self.subnet = ipaddress.ip_network(app.config["SUBNET"])
|
||||
|
||||
def check(self,clientip):
|
||||
# disable limits for internal requests (e.g. from webmail)?
|
||||
if self.rate_limit_subnet==False and ipaddress.ip_address(clientip) in self.subnet:
|
||||
return
|
||||
if not self.limiter.test(self.rate,"client-ip",clientip):
|
||||
raise RateLimitExceeded()
|
||||
|
||||
def hit(self,clientip):
|
||||
# disable limits for internal requests (e.g. from webmail)?
|
||||
if self.rate_limit_subnet==False and ipaddress.ip_address(clientip) in self.subnet:
|
||||
return
|
||||
self.limiter.hit(self.rate,"client-ip",clientip)
|
@ -0,0 +1,2 @@
|
||||
|
||||
Ratelimit counts up on failed auth only now
|
Loading…
Reference in New Issue