Skip to content

Commit eab54cc

Browse files
valapheeonebeastchris
authored andcommitted
Move haproxy handling and throttling to Cloudburst network (GeyserMC#6390)
(cherry picked from commit 6b979fa)
1 parent d8abfe9 commit eab54cc

11 files changed

Lines changed: 31 additions & 851 deletions

core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@
3838
import org.geysermc.geyser.GeyserImpl;
3939
import org.geysermc.geyser.session.GeyserSession;
4040

41-
import java.net.InetSocketAddress;
42-
4341
public class GeyserServerInitializer extends BedrockServerInitializer {
4442
private final GeyserImpl geyser;
4543
private final boolean rakCookiesEnabled;
@@ -63,13 +61,6 @@ protected void preInitChannel(Channel channel) throws Exception {
6361
@Override
6462
public void initSession(@NonNull BedrockServerSession bedrockServerSession) {
6563
try {
66-
if (this.geyser.getGeyserServer().getProxiedAddresses() != null) {
67-
InetSocketAddress address = this.geyser.getGeyserServer().getProxiedAddresses().get((InetSocketAddress) bedrockServerSession.getSocketAddress());
68-
if (address != null) {
69-
((GeyserBedrockPeer) bedrockServerSession.getPeer()).setProxiedAddress(address);
70-
}
71-
}
72-
7364
bedrockServerSession.setLogging(this.geyser.config().debugMode());
7465
GeyserSession session = new GeyserSession(this.geyser, bedrockServerSession, this.eventLoopGroup.next());
7566

core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,6 @@ public PacketSignal handle(LoginPacket loginPacket) {
203203
}
204204
receivedLoginPacket = true;
205205

206-
if (geyser.getSessionManager().reachedMaxConnectionsPerAddress(session)) {
207-
session.disconnect("Too many connections are originating from this location!");
208-
return PacketSignal.HANDLED;
209-
}
210-
211206
LoginEncryptionUtils.encryptPlayerConnection(session, loginPacket);
212207

213208
if (session.isClosed()) {

core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java

Lines changed: 18 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,8 @@
3737
import io.netty.util.concurrent.DefaultThreadFactory;
3838
import io.netty.util.concurrent.Future;
3939
import lombok.Getter;
40-
import net.jodah.expiringmap.ExpirationPolicy;
41-
import net.jodah.expiringmap.ExpiringMap;
4240
import org.cloudburstmc.netty.channel.raknet.RakChannelFactory;
41+
import org.cloudburstmc.netty.channel.raknet.config.DefaultRakServerThrottle;
4342
import org.cloudburstmc.netty.channel.raknet.config.RakChannelOption;
4443
import org.cloudburstmc.netty.channel.raknet.config.RakServerCookieMode;
4544
import org.cloudburstmc.netty.handler.codec.raknet.server.RakServerOfflineHandler;
@@ -54,9 +53,7 @@
5453
import org.geysermc.geyser.network.GameProtocol;
5554
import org.geysermc.geyser.network.GeyserServerInitializer;
5655
import org.geysermc.geyser.network.netty.handler.RakConnectionRequestHandler;
57-
import org.geysermc.geyser.network.netty.handler.RakGeyserRateLimiter;
5856
import org.geysermc.geyser.network.netty.handler.RakPingHandler;
59-
import org.geysermc.geyser.network.netty.proxy.ProxyServerHandler;
6057
import org.geysermc.geyser.ping.GeyserPingInfo;
6158
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
6259
import org.geysermc.geyser.skin.SkinProvider;
@@ -107,8 +104,6 @@ public final class GeyserServer {
107104
private final ServerBootstrap bootstrap;
108105
private EventLoopGroup playerGroup;
109106

110-
@Getter
111-
private final ExpiringMap<InetSocketAddress, InetSocketAddress> proxiedAddresses;
112107
private int listenCount;
113108

114109
private ChannelFuture[] bootstrapFutures;
@@ -136,14 +131,6 @@ public GeyserServer(GeyserImpl geyser, int threadCount) {
136131
this.listenCount = 1;
137132
}
138133

139-
if (this.geyser.config().advanced().bedrock().useHaproxyProtocol() || this.geyser.config().advanced().bedrock().useWaterdogpeForwarding()) {
140-
this.proxiedAddresses = ExpiringMap.builder()
141-
.expiration(30 + 1, TimeUnit.MINUTES)
142-
.expirationPolicy(ExpirationPolicy.ACCESSED).build();
143-
} else {
144-
this.proxiedAddresses = null;
145-
}
146-
147134
this.broadcastPort = geyser.config().advanced().bedrock().broadcastPort();
148135
}
149136

@@ -170,21 +157,6 @@ private void modifyHandlers(ChannelFuture future) {
170157
channel.pipeline()
171158
.addFirst(RakConnectionRequestHandler.NAME, new RakConnectionRequestHandler(this))
172159
.addAfter(RakServerOfflineHandler.NAME, RakPingHandler.NAME, new RakPingHandler(this));
173-
174-
// Add proxy handler
175-
boolean isProxyProtocol = this.geyser.config().advanced().bedrock().useHaproxyProtocol();
176-
if (isProxyProtocol) {
177-
channel.pipeline().addFirst("proxy-protocol-decoder", new ProxyServerHandler());
178-
}
179-
180-
boolean isWhitelistedProxyProtocol = isProxyProtocol && !this.geyser.config().advanced().bedrock().haproxyProtocolWhitelistedIps().isEmpty();
181-
if (Boolean.parseBoolean(System.getProperty("Geyser.RakRateLimitingDisabled", "false")) || isWhitelistedProxyProtocol) {
182-
// We would already block any non-whitelisted IP addresses in onConnectionRequest so we can remove the rate limiter
183-
channel.pipeline().remove(RakServerRateLimiter.NAME);
184-
} else {
185-
// Use our own rate limiter to allow multiple players from the same IP
186-
channel.pipeline().replace(RakServerRateLimiter.NAME, RakGeyserRateLimiter.NAME, new RakGeyserRateLimiter(channel));
187-
}
188160
});
189161
}
190162

@@ -237,6 +209,15 @@ private ServerBootstrap createBootstrap() {
237209
boolean rakSendCookie = Boolean.parseBoolean(System.getProperty("Geyser.RakSendCookie", "true"));
238210
this.geyser.getLogger().debug("Setting RakNet send cookie to " + rakSendCookie);
239211

212+
int maxConnectionsPerAddress = positivePropOrDefault("Geyser.MaxConnectionsPerAddress", 10);
213+
this.geyser.getLogger().debug("Setting max connections per address to " + maxConnectionsPerAddress);
214+
215+
boolean rakRateLimitingDisabled = Boolean.parseBoolean(System.getProperty(
216+
"Geyser.RakRateLimitingDisabled",
217+
Boolean.toString(this.geyser.config().advanced().bedrock().useWaterdogpeForwarding())
218+
));
219+
this.geyser.getLogger().debug("Disabling RakNet rate limiting " + rakRateLimitingDisabled);
220+
240221
GeyserServerInitializer serverInitializer = new GeyserServerInitializer(this.geyser, rakSendCookie);
241222
playerGroup = serverInitializer.getEventLoopGroup();
242223

@@ -245,13 +226,15 @@ private ServerBootstrap createBootstrap() {
245226
.group(group, childGroup)
246227
.option(RakChannelOption.RAK_HANDLE_PING, true)
247228
.option(RakChannelOption.RAK_MAX_MTU, this.geyser.config().advanced().bedrock().mtu())
248-
.option(RakChannelOption.RAK_PACKET_LIMIT, rakPacketLimit)
229+
.option(RakChannelOption.RAK_PACKET_LIMIT, rakRateLimitingDisabled ? 0 : rakPacketLimit)
249230
.option(RakChannelOption.RAK_GLOBAL_PACKET_LIMIT, rakGlobalPacketLimit)
250231
.option(RakChannelOption.RAK_SERVER_COOKIE_MODE, rakSendCookie ? RakServerCookieMode.ACTIVE : RakServerCookieMode.INVALID)
232+
.option(RakChannelOption.RAK_PROXY_PROTOCOL, this.geyser.config().advanced().bedrock().useHaproxyProtocol())
233+
.option(RakChannelOption.RAK_THROTTLE, rakRateLimitingDisabled ? null : new DefaultRakServerThrottle(maxConnectionsPerAddress, 4_000, 3))
251234
.childHandler(serverInitializer);
252235
}
253236

254-
public boolean onConnectionRequest(InetSocketAddress inetSocketAddress) {
237+
public boolean onConnectionRequest(InetSocketAddress inetSocketAddress, InetSocketAddress clientAddress) {
255238
List<String> allowedProxyIPs = geyser.config().advanced().bedrock().haproxyProtocolWhitelistedIps();
256239
if (geyser.config().advanced().bedrock().useHaproxyProtocol() && !allowedProxyIPs.isEmpty()) {
257240
boolean isWhitelistedIP = false;
@@ -268,20 +251,11 @@ public boolean onConnectionRequest(InetSocketAddress inetSocketAddress) {
268251
}
269252
}
270253

271-
String ip;
272-
if (geyser.config().logPlayerIpAddresses()) {
273-
if (this.proxiedAddresses != null) {
274-
ip = this.proxiedAddresses.getOrDefault(inetSocketAddress, inetSocketAddress).toString();
275-
} else {
276-
ip = inetSocketAddress.toString();
277-
}
278-
} else {
279-
ip = "<IP address withheld>";
280-
}
254+
String ip = geyser.config().logPlayerIpAddresses() ? clientAddress.toString() : "<IP address withheld>";
281255

282256
ConnectionRequestEvent requestEvent = new ConnectionRequestEvent(
283-
inetSocketAddress,
284-
this.proxiedAddresses != null ? this.proxiedAddresses.get(inetSocketAddress) : null
257+
clientAddress,
258+
geyser.config().advanced().bedrock().useHaproxyProtocol() ? inetSocketAddress : null
285259
);
286260
geyser.eventBus().fire(requestEvent);
287261
if (requestEvent.isCancelled()) {
@@ -297,16 +271,7 @@ public boolean onConnectionRequest(InetSocketAddress inetSocketAddress) {
297271

298272
public BedrockPong onQuery(Channel channel, InetSocketAddress inetSocketAddress) {
299273
if (geyser.config().debugMode() && PRINT_DEBUG_PINGS) {
300-
String ip;
301-
if (geyser.config().logPlayerIpAddresses()) {
302-
if (this.proxiedAddresses != null) {
303-
ip = this.proxiedAddresses.getOrDefault(inetSocketAddress, inetSocketAddress).toString();
304-
} else {
305-
ip = inetSocketAddress.toString();
306-
}
307-
} else {
308-
ip = "<IP address withheld>";
309-
}
274+
String ip = geyser.config().logPlayerIpAddresses() ? inetSocketAddress.toString() : "<IP address withheld>";
310275
geyser.getLogger().debug(GeyserLocale.getLocaleStringLog("geyser.network.pinged", ip));
311276
}
312277

core/src/main/java/org/geysermc/geyser/network/netty/handler/RakConnectionRequestHandler.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import io.netty.channel.socket.DatagramPacket;
3434
import lombok.RequiredArgsConstructor;
3535
import org.checkerframework.checker.nullness.qual.NonNull;
36+
import org.cloudburstmc.netty.channel.raknet.RakServerChannel;
3637
import org.cloudburstmc.netty.channel.raknet.config.RakChannelOption;
3738
import org.geysermc.geyser.network.netty.GeyserServer;
3839

@@ -84,8 +85,10 @@ public void channelRead(@NonNull ChannelHandlerContext ctx, @NonNull Object msg)
8485
ByteBuf magicBuf = ctx.channel().config().getOption(RakChannelOption.RAK_UNCONNECTED_MAGIC);
8586
long guid = ctx.channel().config().getOption(RakChannelOption.RAK_GUID);
8687

87-
if (!this.server.onConnectionRequest(packet.sender())) {
88-
this.sendConnectionBanned(ctx, packet.sender(), magicBuf, guid);
88+
InetSocketAddress address = packet.sender();
89+
InetSocketAddress clientAddress = ((RakServerChannel) ctx.channel()).getClientAddress(address);
90+
if (!this.server.onConnectionRequest(address, clientAddress)) {
91+
this.sendConnectionBanned(ctx, address, magicBuf, guid);
8992
} else {
9093
ctx.fireChannelRead(msg);
9194
}

core/src/main/java/org/geysermc/geyser/network/netty/handler/RakGeyserRateLimiter.java

Lines changed: 0 additions & 49 deletions
This file was deleted.

core/src/main/java/org/geysermc/geyser/network/netty/handler/RakPingHandler.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,12 @@
3131
import lombok.RequiredArgsConstructor;
3232
import org.cloudburstmc.netty.channel.raknet.RakPing;
3333
import org.cloudburstmc.netty.channel.raknet.RakPong;
34+
import org.cloudburstmc.netty.channel.raknet.RakServerChannel;
3435
import org.cloudburstmc.netty.channel.raknet.config.RakChannelOption;
3536
import org.geysermc.geyser.network.netty.GeyserServer;
3637

38+
import java.net.InetSocketAddress;
39+
3740
@ChannelHandler.Sharable
3841
@RequiredArgsConstructor
3942
public class RakPingHandler extends SimpleChannelInboundHandler<RakPing> {
@@ -45,7 +48,9 @@ public class RakPingHandler extends SimpleChannelInboundHandler<RakPing> {
4548
protected void channelRead0(ChannelHandlerContext ctx, RakPing msg) {
4649
long guid = ctx.channel().config().getOption(RakChannelOption.RAK_GUID);
4750

48-
RakPong pong = msg.reply(guid, this.server.onQuery(ctx.channel(), msg.getSender()).toByteBuf());
51+
InetSocketAddress address = msg.getSender();
52+
InetSocketAddress clientAddress = ((RakServerChannel) ctx.channel()).getClientAddress(address);
53+
RakPong pong = msg.reply(guid, this.server.onQuery(ctx.channel(), clientAddress).toByteBuf());
4954
ctx.writeAndFlush(pong);
5055
}
5156
}

0 commit comments

Comments
 (0)