13
0
geforkt von Mirrors/Velocity

Merge pull request #28 from MatrixTunnel/feature/ratelime-config

Add login ratelimit configuration
Dieser Commit ist enthalten in:
Andrew Steinborn 2018-08-10 21:57:58 -04:00 committet von GitHub
Commit 7130942032
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 4AEE18F83AFDEB23
5 geänderte Dateien mit 44 neuen und 11 gelöschten Zeilen

Datei anzeigen

@ -72,7 +72,7 @@ public class VelocityServer implements ProxyServer {
return true;
}
};
private final Ratelimiter ipAttemptLimiter = new Ratelimiter(3000); // TODO: Configurable.
private Ratelimiter ipAttemptLimiter;
private VelocityServer() {
commandManager.registerCommand("velocity", new VelocityCommand());
@ -127,6 +127,8 @@ public class VelocityServer implements ProxyServer {
serverKeyPair = EncryptionUtils.createRsaKeyPair(1024);
ipAttemptLimiter = new Ratelimiter(configuration.getLoginRatelimit());
httpClient = new NettyHttpClient(this);
this.cm.bind(configuration.getBind());

Datei anzeigen

@ -34,6 +34,7 @@ public class VelocityConfiguration {
private final List<String> attemptConnectionOrder;
private final int compressionThreshold;
private final int compressionLevel;
private final int loginRatelimit;
private final boolean queryEnabled;
private final int queryPort;
@ -46,8 +47,8 @@ public class VelocityConfiguration {
private VelocityConfiguration(String bind, String motd, int showMaxPlayers, boolean onlineMode,
PlayerInfoForwarding playerInfoForwardingMode, Map<String, String> servers,
List<String> attemptConnectionOrder, int compressionThreshold,
int compressionLevel, boolean queryEnabled, int queryPort,
byte[] forwardingSecret) {
int compressionLevel, int loginRatelimit, boolean queryEnabled,
int queryPort, byte[] forwardingSecret) {
this.bind = bind;
this.motd = motd;
this.showMaxPlayers = showMaxPlayers;
@ -57,6 +58,7 @@ public class VelocityConfiguration {
this.attemptConnectionOrder = attemptConnectionOrder;
this.compressionThreshold = compressionThreshold;
this.compressionLevel = compressionLevel;
this.loginRatelimit = loginRatelimit;
this.queryEnabled = queryEnabled;
this.queryPort = queryPort;
this.forwardingSecret = forwardingSecret;
@ -140,6 +142,11 @@ public class VelocityConfiguration {
logger.warn("ALL packets going through the proxy are going to be compressed. This may hurt performance.");
}
if (loginRatelimit < 0) {
logger.error("Invalid login ratelimit {}", loginRatelimit);
valid = false;
}
loadFavicon();
return valid;
@ -211,6 +218,10 @@ public class VelocityConfiguration {
return compressionLevel;
}
public int getLoginRatelimit() {
return loginRatelimit;
}
public Favicon getFavicon() {
return favicon;
}
@ -231,6 +242,7 @@ public class VelocityConfiguration {
", attemptConnectionOrder=" + attemptConnectionOrder +
", compressionThreshold=" + compressionThreshold +
", compressionLevel=" + compressionLevel +
", loginRatelimit=" + loginRatelimit +
", queryEnabled=" + queryEnabled +
", queryPort=" + queryPort +
", motdAsComponent=" + motdAsComponent +
@ -267,6 +279,7 @@ public class VelocityConfiguration {
toml.getTable("servers").getList("try"),
toml.getTable("advanced").getLong("compression-threshold", 1024L).intValue(),
toml.getTable("advanced").getLong("compression-level", -1L).intValue(),
toml.getTable("advanced").getLong("login-ratelimit", 3000L).intValue(),
toml.getTable("query").getBoolean("enabled", false),
toml.getTable("query").getLong("port", 25577L).intValue(),
forwardingSecret);

Datei anzeigen

@ -19,15 +19,21 @@ public class Ratelimiter {
@VisibleForTesting
Ratelimiter(long timeoutMs, Ticker ticker) {
this.timeoutNanos = TimeUnit.MILLISECONDS.toNanos(timeoutMs);
this.expiringCache = CacheBuilder.newBuilder()
.ticker(ticker)
.concurrencyLevel(Runtime.getRuntime().availableProcessors())
.expireAfterWrite(timeoutMs, TimeUnit.MILLISECONDS)
.build();
if (timeoutMs == 0) {
this.timeoutNanos = timeoutMs;
this.expiringCache = null;
} else {
this.timeoutNanos = TimeUnit.MILLISECONDS.toNanos(timeoutMs);
this.expiringCache = CacheBuilder.newBuilder()
.ticker(ticker)
.concurrencyLevel(Runtime.getRuntime().availableProcessors())
.expireAfterWrite(timeoutMs, TimeUnit.MILLISECONDS)
.build();
}
}
public boolean attempt(InetAddress address) {
if (timeoutNanos == 0) return true;
long expectedNewValue = System.nanoTime() + timeoutNanos;
long last;
try {

Datei anzeigen

@ -43,6 +43,10 @@ compression-threshold = 1024
# How much compression should be done (from 0-9). The default is -1, which uses zlib's default level of 6.
compression-level = -1
# How fast (in miliseconds) are clients allowed to connect after the last connection? Default: 3000
# Disable by setting to 0
login-ratelimit = 3000
[query]
# Whether to enable responding to GameSpy 4 query responses or not
enabled = false

Datei anzeigen

@ -12,7 +12,14 @@ import static org.junit.jupiter.api.Assertions.*;
class RatelimiterTest {
@Test
void attempt() {
void attemptZero() {
Ratelimiter noRatelimiter = new Ratelimiter(0);
assertTrue(noRatelimiter.attempt(InetAddress.getLoopbackAddress()));
assertTrue(noRatelimiter.attempt(InetAddress.getLoopbackAddress()));
}
@Test
void attemptOne() {
long base = System.nanoTime();
AtomicLong extra = new AtomicLong();
Ticker testTicker = new Ticker() {
@ -27,4 +34,5 @@ class RatelimiterTest {
extra.addAndGet(TimeUnit.SECONDS.toNanos(2));
assertTrue(ratelimiter.attempt(InetAddress.getLoopbackAddress()));
}
}
}