geforkt von Mirrors/Velocity
Merge pull request #28 from MatrixTunnel/feature/ratelime-config
Add login ratelimit configuration
Dieser Commit ist enthalten in:
Commit
7130942032
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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()));
|
||||
}
|
||||
|
||||
}
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren