mirror of
https://github.com/jonesdevelopment/sonar.git
synced 2026-11-05 09:20:15 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b4394624f | ||
|
|
d8f7e288e8 | ||
|
|
3f3411ca9d | ||
|
|
14ae85384a | ||
|
|
8204477eb6 | ||
|
|
44754e5027 | ||
|
|
847936ed08 |
No files matched your search
+1
-1
@@ -46,7 +46,7 @@ allprojects {
|
||||
implementation("com.j256.ormlite:ormlite-jdbc:6.1") // ORM
|
||||
implementation("xyz.jonesdev:cappuccino:0.1.6-SNAPSHOT") // expiring cache
|
||||
|
||||
compileOnly("io.netty:netty-all:4.1.100.Final") // netty
|
||||
compileOnly("io.netty:netty-all:4.1.101.Final") // netty
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
group=xyz.jonesdev.sonar
|
||||
version=2.0.8
|
||||
version=2.0.9
|
||||
description=Effective Anti-bot plugin for Velocity, BungeeCord, and Bukkit (1.7-latest)
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -45,6 +45,8 @@ public final class AttackTracker implements JVMProfiler {
|
||||
private int peakJoinsPerSecond;
|
||||
private double peakProcessCPUUsage;
|
||||
private long peakProcessMemoryUsage;
|
||||
// Calculate during-attack-statistics using their deltas
|
||||
private int successfulVerifications, failedVerifications;
|
||||
}
|
||||
|
||||
public void checkIfUnderAttack() {
|
||||
@@ -62,6 +64,8 @@ public final class AttackTracker implements JVMProfiler {
|
||||
// An attack has been detected
|
||||
if (currentAttack == null) {
|
||||
currentAttack = new AttackStatistics();
|
||||
currentAttack.successfulVerifications = Sonar.get().getVerifiedPlayerController().estimatedSize();
|
||||
currentAttack.failedVerifications = Statistics.FAILED_VERIFICATIONS.get();
|
||||
Sonar.get().getEventManager().publish(new AttackDetectedEvent());
|
||||
} else {
|
||||
// Reset attack timer if we're still under attack
|
||||
@@ -101,8 +105,11 @@ public final class AttackTracker implements JVMProfiler {
|
||||
final String startTimestamp = String.valueOf(currentAttack.duration.getStart() / 1000L);
|
||||
final String endTimestamp = String.valueOf(System.currentTimeMillis() / 1000L);
|
||||
final long blacklisted = Sonar.get().getFallback().getBlacklisted().estimatedSize();
|
||||
final long verified = Sonar.get().getVerifiedPlayerController().estimatedSize();
|
||||
final long failed = Statistics.FAILED_VERIFICATIONS.get();
|
||||
// Calculate during-attack-statistics using their deltas
|
||||
final long totalVerified = Sonar.get().getVerifiedPlayerController().estimatedSize();
|
||||
final long verified = Math.max(totalVerified - currentAttack.successfulVerifications, 0);
|
||||
final long totalFailed = Statistics.FAILED_VERIFICATIONS.get();
|
||||
final long failed = Math.max(totalFailed - currentAttack.failedVerifications, 0);
|
||||
|
||||
// Post webhook to Discord
|
||||
Optional.ofNullable(Sonar.get().getConfig().getDiscordWebhook()).ifPresent(webhook -> webhook.post(() -> {
|
||||
|
||||
@@ -28,8 +28,6 @@ import xyz.jonesdev.sonar.api.command.subcommand.argument.Argument;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
@@ -51,18 +49,7 @@ public abstract class Subcommand {
|
||||
.collect(Collectors.joining(", "));
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/5284147/validating-ipv4-addresses-with-regexp
|
||||
private static final Pattern IP_PATTERN = Pattern.compile("^((25[0-5]|(2[0-4]|1\\d|[1-9]|)\\d)\\.?\\b){4}$");
|
||||
|
||||
protected static @Nullable InetAddress getInetAddressIfValid(final InvocationSource source, final String rawIP) {
|
||||
// We perform a regex check beforehand,
|
||||
// so we don't have to create a new InetAddress,
|
||||
// therefore, potentially saving some performance.
|
||||
if (!IP_PATTERN.matcher(Objects.requireNonNull(rawIP)).matches()) {
|
||||
source.sendMessage(SONAR.getConfig().getCommands().getIncorrectIpAddress());
|
||||
return null;
|
||||
}
|
||||
|
||||
final InetAddress inetAddress;
|
||||
try {
|
||||
inetAddress = InetAddress.getByName(rawIP);
|
||||
@@ -72,7 +59,7 @@ public abstract class Subcommand {
|
||||
return null;
|
||||
}
|
||||
} catch (UnknownHostException exception) {
|
||||
source.sendMessage(SONAR.getConfig().getCommands().getUnknownIpAddress());
|
||||
source.sendMessage(SONAR.getConfig().getCommands().getIncorrectIpAddress());
|
||||
return null;
|
||||
}
|
||||
return inetAddress;
|
||||
|
||||
@@ -112,4 +112,9 @@ public final class SimpleYamlConfig {
|
||||
yaml.addDefault(path, def);
|
||||
return yaml.getStringList(path);
|
||||
}
|
||||
|
||||
public List<Integer> getIntList(final String path, final List<Integer> def) {
|
||||
yaml.addDefault(path, def);
|
||||
return yaml.getIntegerList(path);
|
||||
}
|
||||
}
|
||||
@@ -29,10 +29,7 @@ import xyz.jonesdev.sonar.api.webhook.DiscordWebhook;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static xyz.jonesdev.sonar.api.Sonar.LINE_SEPARATOR;
|
||||
@@ -134,11 +131,12 @@ public final class SonarConfiguration {
|
||||
private int maxBrandLength;
|
||||
private int maxMovementTicks;
|
||||
private int maxIgnoredTicks;
|
||||
private int maxVerifyingPlayers;
|
||||
private int maxLoginPackets;
|
||||
private int maxPing;
|
||||
private int readTimeout;
|
||||
private int reconnectDelay;
|
||||
private final Collection<Integer> whitelistedProtocols = new HashSet<>(0);
|
||||
private final Collection<Integer> blacklistedProtocols = new HashSet<>(0);
|
||||
|
||||
private Component tooManyPlayers;
|
||||
private Component tooFastReconnect;
|
||||
@@ -150,6 +148,7 @@ public final class SonarConfiguration {
|
||||
private Component alreadyVerifying;
|
||||
private Component alreadyQueued;
|
||||
private Component blacklisted;
|
||||
private Component protocolBlacklisted;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@@ -158,7 +157,6 @@ public final class SonarConfiguration {
|
||||
private String incorrectCommandUsage;
|
||||
private String incorrectIpAddress;
|
||||
private String illegalIpAddress;
|
||||
private String unknownIpAddress;
|
||||
private String subCommandNoPerm;
|
||||
private String playersOnly;
|
||||
private String consoleOnly;
|
||||
@@ -481,16 +479,23 @@ public final class SonarConfiguration {
|
||||
"Amount of time that has to pass before a player times out");
|
||||
verification.readTimeout = clamp(generalConfig.getInt("verification.read-timeout", 3500), 500, 30000);
|
||||
|
||||
generalConfig.getYaml().setComment("verification.max-players",
|
||||
"Maximum number of players verifying at the same time");
|
||||
verification.maxVerifyingPlayers = clamp(generalConfig.getInt("verification.max-players", 1024), 1,
|
||||
Short.MAX_VALUE);
|
||||
|
||||
generalConfig.getYaml().setComment("verification.rejoin-delay",
|
||||
"Minimum number of rejoin delay during verification");
|
||||
verification.reconnectDelay = clamp(generalConfig.getInt("verification.rejoin-delay", 8000), 0, 100000);
|
||||
|
||||
// Webhooks
|
||||
generalConfig.getYaml().setComment("verification.whitelisted-protocols",
|
||||
"List of protocol IDs which are not checked by Sonar (verification bypass)"
|
||||
+ LINE_SEPARATOR + "You can find the full list of all protocol IDs here:"
|
||||
+ LINE_SEPARATOR + "https://wiki.vg/Protocol_version_numbers"
|
||||
+ LINE_SEPARATOR + "For example, Minecraft 1.20 has the ID 763.");
|
||||
verification.whitelistedProtocols.clear();
|
||||
verification.whitelistedProtocols.addAll(generalConfig.getIntList("verification.whitelisted-protocols", new ArrayList<>(0)));
|
||||
|
||||
generalConfig.getYaml().setComment("verification.blacklisted-protocols",
|
||||
"List of protocol IDs which are unable to join the server at all");
|
||||
verification.blacklistedProtocols.clear();
|
||||
verification.blacklistedProtocols.addAll(generalConfig.getIntList("verification.blacklisted-protocols", new ArrayList<>(0)));
|
||||
|
||||
generalConfig.getYaml().setComment("webhook",
|
||||
"Bot attack notifications can also be sent to your Discord server using webhooks");
|
||||
generalConfig.getYaml().setComment("webhook.url",
|
||||
@@ -605,7 +610,7 @@ public final class SonarConfiguration {
|
||||
"%prefix%<red>Usage: /sonar %usage%"));
|
||||
|
||||
messagesConfig.getYaml().setComment("commands.invalid-ip-address",
|
||||
"Message that is shown when someone provides an invalid IP address (Invalid characters)");
|
||||
"Message that is shown when someone provides an invalid IP address (Invalid format)");
|
||||
commands.incorrectIpAddress = formatString(messagesConfig.getString("commands.invalid-ip-address",
|
||||
"%prefix%The IP address you provided seems to be invalid."));
|
||||
|
||||
@@ -614,11 +619,6 @@ public final class SonarConfiguration {
|
||||
commands.illegalIpAddress = formatString(messagesConfig.getString("commands.illegal-ip-address",
|
||||
"%prefix%The IP address you provided seems to be either a local or loopback IP."));
|
||||
|
||||
messagesConfig.getYaml().setComment("commands.unknown-ip-address",
|
||||
"Message that is shown when someone provides an unknown IP address (Unknown Host)");
|
||||
commands.unknownIpAddress = formatString(messagesConfig.getString("commands.unknown-ip-address",
|
||||
"%prefix%The IP address you provided seems to be unknown."));
|
||||
|
||||
messagesConfig.getYaml().setComment("commands.player-only",
|
||||
"Message that is shown when the console runs a command that is player-only");
|
||||
commands.playersOnly = formatString(messagesConfig.getString("commands.player-only",
|
||||
@@ -952,6 +952,16 @@ public final class SonarConfiguration {
|
||||
"%footer%"
|
||||
))));
|
||||
|
||||
messagesConfig.getYaml().setComment("verification.blacklisted-protocol",
|
||||
"Disconnect message that is shown when someone joins with a blacklisted version");
|
||||
verification.protocolBlacklisted = deserialize(fromList(messagesConfig.getStringList("verification.blacklisted-protocol",
|
||||
Arrays.asList(
|
||||
"%header%",
|
||||
"<red>You are using a version that is not allowed on our server.",
|
||||
"<gold>Need help logging in? <gray>%support-url%",
|
||||
"%footer%"
|
||||
))));
|
||||
|
||||
messagesConfig.getYaml().setComment("verification.already-online",
|
||||
"Disconnect message that is shown when someone tries verifying with an account that is online");
|
||||
verification.alreadyConnected = deserialize(fromList(messagesConfig.getStringList("verification.already-online",
|
||||
|
||||
@@ -40,11 +40,10 @@ public final class Fallback {
|
||||
public static final Fallback INSTANCE = new Fallback();
|
||||
private static final @NotNull Sonar SONAR = Objects.requireNonNull(Sonar.get());
|
||||
|
||||
private final Map<String, InetAddress> connected = new ConcurrentHashMap<>();
|
||||
private final Map<String, InetAddress> connected = new ConcurrentHashMap<>(64, 0.75f);
|
||||
// Only block the player for a few minutes to avoid issues
|
||||
private final ExpiringCache<String> blacklisted = Cappuccino.buildExpiring(
|
||||
10L, TimeUnit.MINUTES, 5000L
|
||||
);
|
||||
private final ExpiringCache<InetAddress> blacklisted = Cappuccino.buildExpiring(
|
||||
10L, TimeUnit.MINUTES, 5000L);
|
||||
private final @NotNull FallbackQueue queue = FallbackQueue.INSTANCE;
|
||||
private final @NotNull FallbackRatelimiter ratelimiter = FallbackRatelimiter.INSTANCE;
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ public interface FallbackUser<X, Y> {
|
||||
// Call the BotBlacklistedEvent for external API usage
|
||||
Sonar.get().getEventManager().publish(new UserBlacklistedEvent(this));
|
||||
|
||||
getFallback().getBlacklisted().put(getInetAddress().toString());
|
||||
getFallback().getBlacklisted().put(getInetAddress());
|
||||
getFallback().getLogger().info(Sonar.get().getConfig().getVerification().getBlacklistLog()
|
||||
.replace("%ip%", Sonar.get().getConfig().formatAddress(getInetAddress()))
|
||||
.replace("%protocol%", String.valueOf(getProtocolVersion().getProtocol())));
|
||||
|
||||
+28
-22
@@ -123,7 +123,8 @@ public final class FallbackInitialHandler extends InitialHandler {
|
||||
}
|
||||
receivedLoginPacket = true;
|
||||
// Cache protocol version so other handlers don't throw NPEs
|
||||
protocolVersion = ProtocolVersion.fromId(getHandshake().getProtocolVersion());
|
||||
final int protocolId = getHandshake().getProtocolVersion();
|
||||
protocolVersion = ProtocolVersion.fromId(protocolId);
|
||||
final Channel channel = channelWrapper.getHandle();
|
||||
|
||||
// Run in the channel's event loop
|
||||
@@ -135,26 +136,19 @@ public final class FallbackInitialHandler extends InitialHandler {
|
||||
// Increase total traffic statistic
|
||||
Statistics.TOTAL_TRAFFIC.increment();
|
||||
|
||||
final InetAddress inetAddress = getAddress().getAddress();
|
||||
// Check the blacklist here since we cannot let the player "ghost join"
|
||||
if (FALLBACK.getBlacklisted().has(inetAddress)) {
|
||||
closeWith(getKickPacket(Sonar.get().getConfig().getVerification().getBlacklisted()));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the verification is enabled
|
||||
if (!Sonar.get().getFallback().shouldVerifyNewPlayers()) {
|
||||
super.handle(loginRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
final InetAddress inetAddress = getAddress().getAddress();
|
||||
val uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + loginRequest.getData()).getBytes(StandardCharsets.UTF_8));
|
||||
// Check if the player is already verified
|
||||
if (Sonar.get().getVerifiedPlayerController().has(inetAddress, uuid)) {
|
||||
super.handle(loginRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the blacklist here since we cannot let the player "ghost join"
|
||||
if (FALLBACK.getBlacklisted().has(inetAddress.toString())) {
|
||||
closeWith(getKickPacket(Sonar.get().getConfig().getVerification().getBlacklisted()));
|
||||
return;
|
||||
}
|
||||
|
||||
// Completely skip Geyser connections
|
||||
if (isGeyserConnection(channel)) {
|
||||
FALLBACK.getLogger().info("Skipping Geyser player: {}{}",
|
||||
@@ -163,6 +157,25 @@ public final class FallbackInitialHandler extends InitialHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the protocol ID of the player is not allowed to enter the server
|
||||
if (Sonar.get().getConfig().getVerification().getBlacklistedProtocols().contains(protocolId)) {
|
||||
closeWith(getKickPacket(Sonar.get().getConfig().getVerification().getProtocolBlacklisted()));
|
||||
return;
|
||||
}
|
||||
|
||||
val uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + loginRequest.getData()).getBytes(StandardCharsets.UTF_8));
|
||||
// Check if the player is already verified
|
||||
if (Sonar.get().getVerifiedPlayerController().has(inetAddress, uuid)) {
|
||||
super.handle(loginRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the protocol ID of the player is allowed to bypass verification
|
||||
if (Sonar.get().getConfig().getVerification().getWhitelistedProtocols().contains(protocolId)) {
|
||||
super.handle(loginRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create wrapped Fallback user
|
||||
user = new FallbackUserWrapper(
|
||||
FALLBACK, channelWrapper, this,
|
||||
@@ -202,13 +215,6 @@ public final class FallbackInitialHandler extends InitialHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
// We cannot allow too many players on our Fallback server
|
||||
// There's technically no reason for limiting this, but we'll better stay safe.
|
||||
if (FALLBACK.getConnected().size() > Sonar.get().getConfig().getVerification().getMaxVerifyingPlayers()) {
|
||||
closeWith(getKickPacket(Sonar.get().getConfig().getVerification().getTooManyPlayers()));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the IP address is currently being rate-limited
|
||||
if (!FALLBACK.getRatelimiter().attempt(inetAddress)) {
|
||||
closeWith(getKickPacket(Sonar.get().getConfig().getVerification().getTooFastReconnect()));
|
||||
|
||||
-6
@@ -327,12 +327,6 @@ public final class FallbackVerificationHandler implements FallbackPacketListener
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: implement ChunkData packet for 1.20.2
|
||||
if (user.getProtocolVersion().compareTo(MINECRAFT_1_20_2) >= 0) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
// First, send an Abilities packet to the client to make
|
||||
// sure the player falls even in spectator mode.
|
||||
// Then, teleport the player to the spawn position.
|
||||
|
||||
+6
-3
@@ -29,8 +29,7 @@ import xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion;
|
||||
import xyz.jonesdev.sonar.common.fallback.protocol.FallbackPacket;
|
||||
|
||||
import static xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion.*;
|
||||
import static xyz.jonesdev.sonar.common.utility.protocol.ProtocolUtil.writeArray;
|
||||
import static xyz.jonesdev.sonar.common.utility.protocol.ProtocolUtil.writeCompoundTag;
|
||||
import static xyz.jonesdev.sonar.common.utility.protocol.ProtocolUtil.*;
|
||||
import static xyz.jonesdev.sonar.common.utility.protocol.VarIntUtil.writeVarInt;
|
||||
|
||||
@Getter
|
||||
@@ -92,7 +91,11 @@ public final class EmptyChunkData implements FallbackPacket {
|
||||
}
|
||||
|
||||
if (protocolVersion.compareTo(MINECRAFT_1_14) >= 0) {
|
||||
writeCompoundTag(byteBuf, protocolVersion.compareTo(MINECRAFT_1_18) < 0 ? LEGACY_TAG : MODERN_TAG);
|
||||
if (protocolVersion.compareTo(MINECRAFT_1_20_2) >= 0) {
|
||||
writeNamelessCompoundTag(byteBuf, MODERN_TAG);
|
||||
} else {
|
||||
writeCompoundTag(byteBuf, protocolVersion.compareTo(MINECRAFT_1_18) < 0 ? LEGACY_TAG : MODERN_TAG);
|
||||
}
|
||||
|
||||
if (protocolVersion.compareTo(MINECRAFT_1_15) >= 0 && protocolVersion.compareTo(MINECRAFT_1_18) < 0) {
|
||||
if (protocolVersion.compareTo(MINECRAFT_1_16_2) >= 0) {
|
||||
|
||||
+4
-4
@@ -54,7 +54,7 @@ public final class BlacklistCommand extends Subcommand {
|
||||
if (inetAddress == null) return;
|
||||
|
||||
// Make sure the IP is not blacklisted already
|
||||
if (SONAR.getFallback().getBlacklisted().has(inetAddress.toString())) {
|
||||
if (SONAR.getFallback().getBlacklisted().has(inetAddress)) {
|
||||
invocation.getSender().sendMessage(SONAR.getConfig().getCommands().getBlacklistDuplicate());
|
||||
return;
|
||||
}
|
||||
@@ -66,7 +66,7 @@ public final class BlacklistCommand extends Subcommand {
|
||||
}
|
||||
|
||||
// Blacklist the given IP address
|
||||
SONAR.getFallback().getBlacklisted().put(inetAddress.toString());
|
||||
SONAR.getFallback().getBlacklisted().put(inetAddress);
|
||||
invocation.getSender().sendMessage(SONAR.getConfig().getCommands().getBlacklistAdd()
|
||||
.replace("%ip%", rawInetAddress));
|
||||
break;
|
||||
@@ -85,13 +85,13 @@ public final class BlacklistCommand extends Subcommand {
|
||||
if (inetAddress == null) return;
|
||||
|
||||
// Make sure the IP is blacklisted
|
||||
if (!SONAR.getFallback().getBlacklisted().has(inetAddress.toString())) {
|
||||
if (!SONAR.getFallback().getBlacklisted().has(inetAddress)) {
|
||||
invocation.getSender().sendMessage(SONAR.getConfig().getCommands().getBlacklistNotFound());
|
||||
return;
|
||||
}
|
||||
|
||||
// Invalidate the cache entry of the blacklisted IP address
|
||||
SONAR.getFallback().getBlacklisted().invalidate(inetAddress.toString());
|
||||
SONAR.getFallback().getBlacklisted().invalidate(inetAddress);
|
||||
invocation.getSender().sendMessage(SONAR.getConfig().getCommands().getBlacklistRemove()
|
||||
.replace("%ip%", rawInetAddress));
|
||||
break;
|
||||
|
||||
+12
-1
@@ -25,6 +25,7 @@ import io.netty.handler.codec.DecoderException;
|
||||
import io.netty.handler.codec.EncoderException;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import net.kyori.adventure.nbt.BinaryTagIO;
|
||||
import net.kyori.adventure.nbt.BinaryTagTypes;
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -113,7 +114,17 @@ public class ProtocolUtil {
|
||||
public static void writeCompoundTag(final ByteBuf byteBuf, final CompoundBinaryTag compoundTag) {
|
||||
try {
|
||||
BinaryTagIO.writer().write(compoundTag, (DataOutput) new ByteBufOutputStream(byteBuf));
|
||||
} catch (IOException e) {
|
||||
} catch (IOException exception) {
|
||||
throw new EncoderException("Unable to encode NBT CompoundTag");
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeNamelessCompoundTag(final @NotNull ByteBuf byteBuf, final CompoundBinaryTag compoundTag) {
|
||||
try {
|
||||
final DataOutput output = new ByteBufOutputStream(byteBuf);
|
||||
output.writeByte(BinaryTagTypes.COMPOUND.id());
|
||||
BinaryTagTypes.COMPOUND.write(compoundTag, output);
|
||||
} catch (IOException exception) {
|
||||
throw new EncoderException("Unable to encode NBT CompoundTag");
|
||||
}
|
||||
}
|
||||
|
||||
+24
-18
@@ -155,7 +155,8 @@ public final class FallbackListener {
|
||||
val activeSessionHandler = (MinecraftSessionHandler) SESSION_HANDLER_FIELD.get(mcConnection);
|
||||
|
||||
// Check the blacklist here since we cannot let the player "ghost join"
|
||||
if (fallback.getBlacklisted().has(inetAddress.toString())) {
|
||||
if (fallback.getBlacklisted().has(inetAddress)) {
|
||||
// Mark the connection as dead to avoid unnecessary console logs
|
||||
markConnectionAsDead(activeSessionHandler);
|
||||
initialConnection.getConnection().closeWith(Disconnect.create(
|
||||
Sonar.get().getConfig().getVerification().getBlacklisted(),
|
||||
@@ -167,17 +168,32 @@ public final class FallbackListener {
|
||||
// Don't continue the verification process if the verification is disabled
|
||||
if (!Sonar.get().getFallback().shouldVerifyNewPlayers()) return;
|
||||
|
||||
// Completely skip Geyser connections
|
||||
if (isGeyserConnection(channel)) {
|
||||
fallback.getLogger().info("Skipping Geyser player: {}{}",
|
||||
event.getUsername(), Sonar.get().getConfig().formatAddress(inetAddress));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the protocol ID of the player is not allowed to enter the server
|
||||
final int protocolId = inboundConnection.getProtocolVersion().getProtocol();
|
||||
if (Sonar.get().getConfig().getVerification().getBlacklistedProtocols().contains(protocolId)) {
|
||||
// Mark the connection as dead to avoid unnecessary console logs
|
||||
markConnectionAsDead(activeSessionHandler);
|
||||
initialConnection.getConnection().closeWith(Disconnect.create(
|
||||
Sonar.get().getConfig().getVerification().getProtocolBlacklisted(),
|
||||
inboundConnection.getProtocolVersion()
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the player is already verified.
|
||||
// No one wants to be verified over and over again.
|
||||
final GameProfile gameProfile = GameProfile.forOfflinePlayer(event.getUsername());
|
||||
if (Sonar.get().getVerifiedPlayerController().has(inetAddress, gameProfile.getId())) return;
|
||||
|
||||
// Completely skip Geyser connections
|
||||
if (isGeyserConnection(channel)) {
|
||||
fallback.getLogger().info("Skipping Geyser player: {}{}",
|
||||
gameProfile.getName(), Sonar.get().getConfig().formatAddress(inetAddress));
|
||||
return;
|
||||
}
|
||||
// Check if the protocol ID of the player is allowed to bypass verification
|
||||
if (Sonar.get().getConfig().getVerification().getWhitelistedProtocols().contains(protocolId)) return;
|
||||
|
||||
// We now mark the connection as dead by using our fake connection
|
||||
markConnectionAsDead(activeSessionHandler);
|
||||
@@ -204,16 +220,6 @@ public final class FallbackListener {
|
||||
return;
|
||||
}
|
||||
|
||||
// We cannot allow too many players on our Fallback server
|
||||
// There's technically no reason for limiting this, but we'll better stay safe.
|
||||
if (fallback.getConnected().size() > Sonar.get().getConfig().getVerification().getMaxVerifyingPlayers()) {
|
||||
initialConnection.getConnection().closeWith(Disconnect.create(
|
||||
Sonar.get().getConfig().getVerification().getTooManyPlayers(),
|
||||
inboundConnection.getProtocolVersion()
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the IP address is currently being rate-limited
|
||||
if (!fallback.getRatelimiter().attempt(inetAddress)) {
|
||||
initialConnection.getConnection().closeWith(Disconnect.create(
|
||||
@@ -278,7 +284,7 @@ public final class FallbackListener {
|
||||
final FallbackUserWrapper user = new FallbackUserWrapper(
|
||||
fallback, connectedPlayer, mcConnection, mcConnection.getChannel(),
|
||||
mcConnection.getChannel().pipeline(), inetAddress,
|
||||
ProtocolVersion.fromId(connectedPlayer.getProtocolVersion().getProtocol())
|
||||
ProtocolVersion.fromId(protocolId)
|
||||
);
|
||||
|
||||
// Disconnect if the protocol version could not be resolved
|
||||
|
||||
Reference in new issue
Block a user