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

Datei anzeigen

@ -34,6 +34,7 @@ public class VelocityConfiguration {
private final List<String> attemptConnectionOrder; private final List<String> attemptConnectionOrder;
private final int compressionThreshold; private final int compressionThreshold;
private final int compressionLevel; private final int compressionLevel;
private final int loginRatelimit;
private final boolean queryEnabled; private final boolean queryEnabled;
private final int queryPort; private final int queryPort;
@ -46,8 +47,8 @@ public class VelocityConfiguration {
private VelocityConfiguration(String bind, String motd, int showMaxPlayers, boolean onlineMode, private VelocityConfiguration(String bind, String motd, int showMaxPlayers, boolean onlineMode,
PlayerInfoForwarding playerInfoForwardingMode, Map<String, String> servers, PlayerInfoForwarding playerInfoForwardingMode, Map<String, String> servers,
List<String> attemptConnectionOrder, int compressionThreshold, List<String> attemptConnectionOrder, int compressionThreshold,
int compressionLevel, boolean queryEnabled, int queryPort, int compressionLevel, int loginRatelimit, boolean queryEnabled,
byte[] forwardingSecret) { int queryPort, byte[] forwardingSecret) {
this.bind = bind; this.bind = bind;
this.motd = motd; this.motd = motd;
this.showMaxPlayers = showMaxPlayers; this.showMaxPlayers = showMaxPlayers;
@ -57,6 +58,7 @@ public class VelocityConfiguration {
this.attemptConnectionOrder = attemptConnectionOrder; this.attemptConnectionOrder = attemptConnectionOrder;
this.compressionThreshold = compressionThreshold; this.compressionThreshold = compressionThreshold;
this.compressionLevel = compressionLevel; this.compressionLevel = compressionLevel;
this.loginRatelimit = loginRatelimit;
this.queryEnabled = queryEnabled; this.queryEnabled = queryEnabled;
this.queryPort = queryPort; this.queryPort = queryPort;
this.forwardingSecret = forwardingSecret; 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."); 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(); loadFavicon();
return valid; return valid;
@ -211,6 +218,10 @@ public class VelocityConfiguration {
return compressionLevel; return compressionLevel;
} }
public int getLoginRatelimit() {
return loginRatelimit;
}
public Favicon getFavicon() { public Favicon getFavicon() {
return favicon; return favicon;
} }
@ -231,6 +242,7 @@ public class VelocityConfiguration {
", attemptConnectionOrder=" + attemptConnectionOrder + ", attemptConnectionOrder=" + attemptConnectionOrder +
", compressionThreshold=" + compressionThreshold + ", compressionThreshold=" + compressionThreshold +
", compressionLevel=" + compressionLevel + ", compressionLevel=" + compressionLevel +
", loginRatelimit=" + loginRatelimit +
", queryEnabled=" + queryEnabled + ", queryEnabled=" + queryEnabled +
", queryPort=" + queryPort + ", queryPort=" + queryPort +
", motdAsComponent=" + motdAsComponent + ", motdAsComponent=" + motdAsComponent +
@ -267,6 +279,7 @@ public class VelocityConfiguration {
toml.getTable("servers").getList("try"), toml.getTable("servers").getList("try"),
toml.getTable("advanced").getLong("compression-threshold", 1024L).intValue(), toml.getTable("advanced").getLong("compression-threshold", 1024L).intValue(),
toml.getTable("advanced").getLong("compression-level", -1L).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").getBoolean("enabled", false),
toml.getTable("query").getLong("port", 25577L).intValue(), toml.getTable("query").getLong("port", 25577L).intValue(),
forwardingSecret); forwardingSecret);

Datei anzeigen

@ -19,15 +19,21 @@ public class Ratelimiter {
@VisibleForTesting @VisibleForTesting
Ratelimiter(long timeoutMs, Ticker ticker) { Ratelimiter(long timeoutMs, Ticker ticker) {
this.timeoutNanos = TimeUnit.MILLISECONDS.toNanos(timeoutMs); if (timeoutMs == 0) {
this.expiringCache = CacheBuilder.newBuilder() this.timeoutNanos = timeoutMs;
.ticker(ticker) this.expiringCache = null;
.concurrencyLevel(Runtime.getRuntime().availableProcessors()) } else {
.expireAfterWrite(timeoutMs, TimeUnit.MILLISECONDS) this.timeoutNanos = TimeUnit.MILLISECONDS.toNanos(timeoutMs);
.build(); this.expiringCache = CacheBuilder.newBuilder()
.ticker(ticker)
.concurrencyLevel(Runtime.getRuntime().availableProcessors())
.expireAfterWrite(timeoutMs, TimeUnit.MILLISECONDS)
.build();
}
} }
public boolean attempt(InetAddress address) { public boolean attempt(InetAddress address) {
if (timeoutNanos == 0) return true;
long expectedNewValue = System.nanoTime() + timeoutNanos; long expectedNewValue = System.nanoTime() + timeoutNanos;
long last; long last;
try { 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. # How much compression should be done (from 0-9). The default is -1, which uses zlib's default level of 6.
compression-level = -1 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] [query]
# Whether to enable responding to GameSpy 4 query responses or not # Whether to enable responding to GameSpy 4 query responses or not
enabled = false enabled = false

Datei anzeigen

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