Extension Flood Filter
The Extension Flood Filter provides fine grained control over the packet rate of Extension requests. This can be used to limit the number of calls per second for specific requests and automatically set rules for warning and banning spammers.
It also includes the ability to catch unknown Extension calls (i.e. requests for which there doesn't exist a request handler) and similar auto-ban rules.
Under normal circumstances, e.g. users playing with the official client app, there shouldn't be a concern about request spam. However malicious users may reverse engineer the app and make a customized clone for malicious purposes.
Not an anti-DDoS tool
NOTE: The Extension Flood Filter is a security tool that limits server spam, and possibly cheating, but it's not itended as DDoS mitigation tool. DDoS attacks can only be defeated with dedicated networking infrastructure and services such as those provided by AWS, Microsoft Azure, Cloudflare and many other hosting or cloud providers.
Overview

In the diagram above we show a bird's eye view of the filter and its position in the Extension invocation chain. For each request handler defined in our Extension code (via the addRequestHandler method) we can provide a limit expressed in number of calls per second.
For example we have defined a playerShoot request handler in our Extension and we've also set a limit of 4 requests/sec. If a client sends 50 calls in one second only the first four will be passed to the Extension while the rest gets discarded. Additionally, based on the auto-ban rules, the sender will be either warned or banned.
The Extension Flood Filter is activated via code in the Extension. Let's take a look:
public class AntiFloodTestExtension extends SFSExtension
{
static final String PLAYER_SHOOT = "pShoot";
static final String PLAYER_MOVE = "pMove";
@Override
public void init()
{
ExtensionFloodFilterConfig cfg = new ExtensionFloodFilterConfig();
cfg.banDurationMinutes = 120;
cfg.maxFloodingAttempts = 3;
cfg.secondsBeforeBan = 2;
cfg.banMessage = "You are now banned. Reason: request flooding.";
cfg.filterRules = Map.of
(
PLAYER_SHOOT, 4,
PLAYER_MOVE, 15
);
initFloodFilter(cfg);
addRequestHandler(PLAYER_SHOOT, (sender, param) -> {
trace("Shooting");
});
addRequestHandler(PLAYER_MOVE, (sender, param) -> {
trace("Moving");
});
}
}
The Extension Flood Filter is inactive by default. To activate it we need to call the initFloodFilter(...) method, available from the parent SFSExtension class.
The initializer method takes a ExtensionFloodFilterConfig object with the following properties:
- banDurationMinutes: duration of user ban. Default = 60 minutes
- secondsBeforeBan: delay before banning is executed, used to allow the user to receive the banning warning. Default = 5 seconds
- banMode: modality of ban. Can be BY_NAME or BY_ADDRESS. Default = BY_NAME
- banMessage: a text message sent by the server before banning the user
- maxFloodingAttempts: maximum flooding attempts detected before the user is banned. Default = 5
- logFloodingAttempts: logs all flooding attempts. Note: can bloat the log files and hit the performance. Default = false
- filter rules: a map of rules where the key (String) is the name of the Extension request and the value (Integer) is the maximum number of requests per second allowed
- maxUnknownReqRate: maximum rate/sec of unkown requests, i.e. requests for which there is no request handler. This is useful to defend against random requests that might be sent to probe the Extension
NOTE: when setting up the Extension we recommend to use the approach shown above, where each request name is defined as a constant and used to define both handlers and filters. This is to avoid typos that could lead to unexpected behaviors.
Limitations and suggestions
-
Based on request name: the flood filter is based on request names only. If your client is calling two Extensions at the same time (e.g. Zone and Room) with identical request names they will count as the same request in the Extension Flood Filter. If this could be a problem make sure to differentiate those names and make them unique.
-
Packet aggregation: when using TCP packets can be aggregated together if they're sent very rapidly. This is a feature known as the Nagle's algorithm. This might trigger the Flood Filter when the actual packet rate is very close to the configured limit. For this reason it is usually recommended to set the request limit one or two units higher than the wanted value. For example: we want to limit the 'shoot' request to 5/sec. We suggest to configure it as 6 requests/sec. This will avoid that the occasional packet aggregation triggers the filter unnecessarily.
There is also an alternative, which is to enable the tcpNoDelay option under server/config/core.xml.