(feat) user rate-limiting support for all SOGo requests
parent
bb04ce39d6
commit
9d6ab2df33
|
@ -715,6 +715,21 @@ Default value is `0`, or disabled.
|
||||||
|Number of seconds, default to `300` (or 5 minutes). Note that
|
|Number of seconds, default to `300` (or 5 minutes). Note that
|
||||||
_SOGoCacheCleanupInterval_ must be set to a value equal or higher than
|
_SOGoCacheCleanupInterval_ must be set to a value equal or higher than
|
||||||
_SOGoFailedLoginBlockInterval_.
|
_SOGoFailedLoginBlockInterval_.
|
||||||
|
|
||||||
|
|S |SOGoMaximumRequestCount
|
||||||
|
|Parameter used to control the number of requests a user can send to the SOGo
|
||||||
|
server in _SOGoMaximumRequestInterval_ seconds or more. If conditions are met
|
||||||
|
or exceeded, the user will not be able to perform requests on the SOGo server
|
||||||
|
for _SOGoRequestBlockInterval_ seconds and will receive 429 HTTP responses for
|
||||||
|
any requests being made. Default value is 0, or disabled
|
||||||
|
|
||||||
|
|S |SOGoMaximumRequestInterval
|
||||||
|
|Number of seconds, defaults to `30`.
|
||||||
|
|
||||||
|
|S |SOGoRequestBlockInterval
|
||||||
|
|Number of seconds, defaults to 300 (or 5 minutes). Note that _SOGoCacheCleanupInterval_
|
||||||
|
must be set to a value equal or higher than _SOGoRequestBlockInterval_.
|
||||||
|
|
||||||
|=======================================================================
|
|=======================================================================
|
||||||
|
|
||||||
Authentication using LDAP
|
Authentication using LDAP
|
||||||
|
|
58
Main/SOGo.m
58
Main/SOGo.m
|
@ -476,6 +476,8 @@ static BOOL debugLeaks;
|
||||||
static BOOL debugOn = NO;
|
static BOOL debugOn = NO;
|
||||||
WOResponse *resp;
|
WOResponse *resp;
|
||||||
NSDate *startDate;
|
NSDate *startDate;
|
||||||
|
NSString *path;
|
||||||
|
|
||||||
NSTimeInterval timeDelta;
|
NSTimeInterval timeDelta;
|
||||||
|
|
||||||
if (debugRequests)
|
if (debugRequests)
|
||||||
|
@ -499,6 +501,62 @@ static BOOL debugLeaks;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// We check for rate-limiting settings - ignore anything actually
|
||||||
|
// sent to /SOGo/ (so unauthenticated requests).
|
||||||
|
path = [_request requestHandlerPath];
|
||||||
|
if ([path length])
|
||||||
|
{
|
||||||
|
NSDictionary *requestCount;
|
||||||
|
NSString *username;
|
||||||
|
NSRange r;
|
||||||
|
|
||||||
|
r = [path rangeOfString: @"/"];
|
||||||
|
username = [path substringWithRange: NSMakeRange(0, r.location)];
|
||||||
|
requestCount = [cache requestCountForLogin: username];
|
||||||
|
|
||||||
|
if (requestCount)
|
||||||
|
{
|
||||||
|
SOGoSystemDefaults *sd;
|
||||||
|
|
||||||
|
unsigned int current_time, start_time, delta, block_time, request_count;
|
||||||
|
|
||||||
|
sd = [SOGoSystemDefaults sharedSystemDefaults];
|
||||||
|
|
||||||
|
current_time = [[NSCalendarDate date] timeIntervalSince1970];
|
||||||
|
start_time = [[requestCount objectForKey: @"InitialDate"] unsignedIntValue];
|
||||||
|
delta = current_time - start_time;
|
||||||
|
|
||||||
|
block_time = [sd requestBlockInterval];
|
||||||
|
request_count = [[requestCount objectForKey: @"RequestCount"] intValue];
|
||||||
|
|
||||||
|
if ( request_count >= [sd maximumRequestCount] &&
|
||||||
|
delta < [sd maximumRequestInterval] &&
|
||||||
|
delta <= block_time )
|
||||||
|
{
|
||||||
|
resp = [WOResponse responseWithRequest: _request];
|
||||||
|
[resp setStatus: 429];
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delta > block_time)
|
||||||
|
{
|
||||||
|
[cache setRequestCount: 1
|
||||||
|
forLogin: username
|
||||||
|
interval: current_time];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
[cache setRequestCount: (request_count+1)
|
||||||
|
forLogin: username
|
||||||
|
interval: start_time];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[cache setRequestCount: 1
|
||||||
|
forLogin: username
|
||||||
|
interval: 0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resp = [super dispatchRequest: _request];
|
resp = [super dispatchRequest: _request];
|
||||||
[cache killCache];
|
[cache killCache];
|
||||||
|
|
||||||
|
|
|
@ -141,6 +141,15 @@
|
||||||
forPath: (NSString *) thePath;
|
forPath: (NSString *) thePath;
|
||||||
- (NSMutableDictionary *) aclsForPath: (NSString *) thePath;
|
- (NSMutableDictionary *) aclsForPath: (NSString *) thePath;
|
||||||
|
|
||||||
|
//
|
||||||
|
// SOGo rate-limiting
|
||||||
|
//
|
||||||
|
- (void) setRequestCount: (int) theCount
|
||||||
|
forLogin: (NSString *) theLogin
|
||||||
|
interval: (unsigned int) theInterval;
|
||||||
|
|
||||||
|
- (NSDictionary *) requestCountForLogin: (NSString *) theLogin;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif /* SOGOCACHE_H */
|
#endif /* SOGOCACHE_H */
|
||||||
|
|
|
@ -727,5 +727,58 @@ static memcached_st *handle = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// SOGo request count for rate-limiting
|
||||||
|
//
|
||||||
|
- (void) setRequestCount: (int) theCount
|
||||||
|
forLogin: (NSString *) theLogin
|
||||||
|
interval: (unsigned int) theInterval
|
||||||
|
{
|
||||||
|
NSMutableDictionary *d;
|
||||||
|
NSNumber *count;
|
||||||
|
|
||||||
|
if (theCount)
|
||||||
|
{
|
||||||
|
count = [NSNumber numberWithInt: theCount];
|
||||||
|
|
||||||
|
d = [NSMutableDictionary dictionaryWithDictionary: [self requestCountForLogin: theLogin]];
|
||||||
|
|
||||||
|
if (![d objectForKey: @"InitialDate"] || theInterval == 0)
|
||||||
|
[d setObject: [NSNumber numberWithUnsignedInt: [[NSCalendarDate date] timeIntervalSince1970]] forKey: @"InitialDate"];
|
||||||
|
else
|
||||||
|
[d setObject: [NSNumber numberWithUnsignedInt: theInterval] forKey: @"InitialDate"];
|
||||||
|
|
||||||
|
[d setObject: count forKey: @"RequestCount"];
|
||||||
|
[self _cacheValues: [d jsonRepresentation]
|
||||||
|
ofType: @"requestcount"
|
||||||
|
forKey: theLogin];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[self removeValueForKey: [NSString stringWithFormat: @"%@+failedlogins", theLogin]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Returns a dictionary with two keys/values
|
||||||
|
//
|
||||||
|
// RequestCount ->
|
||||||
|
// InitialDate ->
|
||||||
|
//
|
||||||
|
- (NSDictionary *) requestCountForLogin: (NSString *) theLogin
|
||||||
|
{
|
||||||
|
NSDictionary *d;
|
||||||
|
NSString *s;
|
||||||
|
|
||||||
|
s = [self _valuesOfType: @"requestcount" forKey: theLogin];
|
||||||
|
d = nil;
|
||||||
|
|
||||||
|
if (s)
|
||||||
|
{
|
||||||
|
d = [s objectFromJSONString];
|
||||||
|
}
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -97,6 +97,11 @@
|
||||||
- (int) maximumSubmissionInterval;
|
- (int) maximumSubmissionInterval;
|
||||||
- (int) messageSubmissionBlockInterval;
|
- (int) messageSubmissionBlockInterval;
|
||||||
|
|
||||||
|
- (int) maximumRequestCount;
|
||||||
|
- (int) maximumRequestInterval;
|
||||||
|
- (int) requestBlockInterval;
|
||||||
|
|
||||||
|
|
||||||
- (int) maximumPingInterval;
|
- (int) maximumPingInterval;
|
||||||
- (int) maximumSyncInterval;
|
- (int) maximumSyncInterval;
|
||||||
- (int) internalSyncInterval;
|
- (int) internalSyncInterval;
|
||||||
|
|
|
@ -598,6 +598,42 @@ _injectConfigurationFromFile (NSMutableDictionary *defaultsDict,
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// SOGo rate-limiting
|
||||||
|
//
|
||||||
|
- (int) maximumRequestCount
|
||||||
|
{
|
||||||
|
return [self integerForKey: @"SOGoMaximumRequestCount"];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int) maximumRequestInterval
|
||||||
|
{
|
||||||
|
int v;
|
||||||
|
|
||||||
|
v = [self integerForKey: @"SOGoMaximumRequestInterval"];
|
||||||
|
|
||||||
|
if (!v)
|
||||||
|
v = 30;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int) requestBlockInterval
|
||||||
|
{
|
||||||
|
int v;
|
||||||
|
|
||||||
|
v = [self integerForKey: @"SOGoRequestBlockInterval"];
|
||||||
|
|
||||||
|
if (!v)
|
||||||
|
v = 300;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// SOGo EAS settings
|
||||||
|
//
|
||||||
- (int) maximumPingInterval
|
- (int) maximumPingInterval
|
||||||
{
|
{
|
||||||
int v;
|
int v;
|
||||||
|
|
Loading…
Reference in New Issue