Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ Here are all the parameters that you can set in the `FabricProxy-Lite.toml` conf
| `hackOnlineMode` | `FABRIC_PROXY_HACK_ONLINE_MODE` | Allows connection through a proxy without disabling online-mode. | `true` | |
| `hackEarlySend` | `FABRIC_PROXY_HACK_EARLY_SEND` | Fabric-API can't send packet before QUERY_START event, so player info(UUID) will not ready at QUERY_START event. Setting `hackEarlySend` to `true` will use mixin for early send packet to velocity. <br><br> This is **required** for some mods, such as LuckPerms. | `false` | |
| `hackMessageChain` | `FABRIC_PROXY_HACK_MESSAGE_CHAIN` | This option fixes players being kicked for `Received chat packet with missing or invalid signature.` or `Chat message validation failure`, which only happens when the player switches to another server. <br><br> See [#30](/../../issues/30) and [#121](/../../discussions/121) for more info. | `false` | |
| `allowDirectConnections` | `FABRIC_PROXY_ALLOW_DIRECT_CONNECTIONS` | Allow direct connections from clients without Velocity. When enabled, the mod will accept non-Velocity connections. | `false` | |
| `disconnectMessage` | `FABRIC_PROXY_DISCONNECT_MESSAGE` | The custom disconnect/kick message for users that aren't connecting through Velocity. | `"This server requires you to connect with Velocity."` | |
| `secret` | `FABRIC_PROXY_SECRET` | The Velocity forwarding secret. This should be the same random string as in Velocity's `forwarding.secret` file. <br><br> Alternatively you could set the `FABRIC_PROXY_SECRET_FILE` environment variable to read the secret from a file instead of config. | | ✓ |
12 changes: 11 additions & 1 deletion src/main/java/one/oktw/ModConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class ModConfig {
private boolean hackOnlineMode = true;
private boolean hackEarlySend = false;
private boolean hackMessageChain = false;
private boolean allowDirectConnections = false;
private String disconnectMessage = "This server requires you to connect with Velocity.";
private String secret = "";

Expand Down Expand Up @@ -50,6 +51,11 @@ public static ModConfig load(Path configPath) {
config.hackMessageChain = Boolean.parseBoolean(envHackMessageChain);
}

String envAllowDirectConnections = System.getenv("FABRIC_PROXY_ALLOW_DIRECT_CONNECTIONS");
if (envAllowDirectConnections != null) {
config.allowDirectConnections = Boolean.parseBoolean(envAllowDirectConnections);
}

String envDisconnectMessage = System.getenv("FABRIC_PROXY_DISCONNECT_MESSAGE");
if (envDisconnectMessage != null) {
config.disconnectMessage = envDisconnectMessage;
Expand Down Expand Up @@ -88,7 +94,11 @@ public boolean getHackMessageChain() {
return hackMessageChain;
}

public boolean getAllowDirectConnections() {
return allowDirectConnections;
}

public String getSecret() {
return secret;
}
}
}
60 changes: 31 additions & 29 deletions src/main/java/one/oktw/PacketHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,41 +22,43 @@ class PacketHandler {

void handleVelocityPacket(MinecraftServer server, ServerLoginPacketListenerImpl handler, boolean understood, FriendlyByteBuf buf, ServerLoginNetworking.LoginSynchronizer synchronizer, PacketSender ignored) {
if (!understood) {
handler.disconnect(Component.nullToEmpty(config.getAbortedMessage()));
return;
}

synchronizer.waitFor(server.submit(() -> {
try {
if (!VelocityLib.checkIntegrity(buf)) {
if (!this.config.getAllowDirectConnections()) {
handler.disconnect(Component.nullToEmpty(config.getAbortedMessage()));
return;
}
} else {
synchronizer.waitFor(server.submit(() -> {
try {
if (!VelocityLib.checkIntegrity(buf)) {
handler.disconnect(Component.nullToEmpty("Unable to verify player details"));
return;
}
VelocityLib.checkVersion(buf);
} catch (Throwable e) {
LogManager.getLogger().error("Secret check failed.", e);
handler.disconnect(Component.nullToEmpty("Unable to verify player details"));
return;
}
VelocityLib.checkVersion(buf);
} catch (Throwable e) {
LogManager.getLogger().error("Secret check failed.", e);
handler.disconnect(Component.nullToEmpty("Unable to verify player details"));
return;
}

Connection connection = ((ServerLoginPacketListenerAccessor) handler).getConnection();
((ConnectionAccessor) connection).setAddress(new java.net.InetSocketAddress(VelocityLib.readAddress(buf), ((java.net.InetSocketAddress) (connection.getRemoteAddress())).getPort()));
Connection connection = ((ServerLoginPacketListenerAccessor) handler).getConnection();
((ConnectionAccessor) connection).setAddress(new java.net.InetSocketAddress(VelocityLib.readAddress(buf), ((java.net.InetSocketAddress) (connection.getRemoteAddress())).getPort()));

GameProfile profile;
try {
profile = VelocityLib.createProfile(buf);
} catch (Exception e) {
LogManager.getLogger().error("Profile create failed.", e);
handler.disconnect(Component.nullToEmpty("Unable to read player profile"));
return;
}
GameProfile profile;
try {
profile = VelocityLib.createProfile(buf);
} catch (Exception e) {
LogManager.getLogger().error("Profile create failed.", e);
handler.disconnect(Component.nullToEmpty("Unable to read player profile"));
return;
}

if (config.getHackEarlySend()) {
((ServerLoginPacketListenerAccessor) handler).setAuthenticatedProfile(profile);
handler.handleHello(new ServerboundHelloPacket(profile.name(), profile.id()));
}
if (config.getHackEarlySend()) {
((ServerLoginPacketListenerAccessor) handler).setAuthenticatedProfile(profile);
handler.handleHello(new ServerboundHelloPacket(profile.name(), profile.id()));
}

((ServerLoginPacketListenerAccessor) handler).setAuthenticatedProfile(profile);
}));
((ServerLoginPacketListenerAccessor) handler).setAuthenticatedProfile(profile);
}));
}
}
}