Check for changing UUID many times on the same IP

This commit is contained in:
Anuken
2026-06-26 11:09:45 -04:00
parent 6d625167a5
commit 25a542759d
2 changed files with 30 additions and 0 deletions
+6
View File
@@ -165,6 +165,12 @@ public class NetServer implements ApplicationListener{
if(admins.isIPBanned(con.address) || admins.isSubnetBanned(con.address) || con.kicked || !con.isConnected()) return;
if(admins.checkUuidChanges(con.address, packet.uuid)){
Log.info("Banning IP @ due to more than @ ID changes in an hour.", con.address, Config.uuidChangeLimit.num());
con.kick(KickReason.banned);
return;
}
if(con.hasBegunConnecting){
con.kick(KickReason.idInUse);
return;
@@ -33,6 +33,7 @@ public class Administration{
private boolean modified, loaded;
/** All player info. Maps UUIDs to info. This persists throughout restarts. Do not modify directly. */
public ObjectMap<String, PlayerInfo> playerInfo = new ObjectMap<>();
private ObjectMap<String, IdEncounterInfo> encounteredIDsForIp = new ObjectMap<>();
public Administration(){
load();
@@ -288,6 +289,24 @@ public class Administration{
return true;
}
public boolean checkUuidChanges(String address, String uuid){
if(Config.uuidChangeLimit.num() <= 1) return false;
var set = encounteredIDsForIp.get(address, IdEncounterInfo::new);
//clear encountered list every hour
if(Time.timeSinceMillis(set.initialTime) > 1000 * 60 * 60){
set.hashes.clear();
set.initialTime = Time.millis();
}
set.hashes.add(uuid.hashCode());
if(set.hashes.size > Config.uuidChangeLimit.num()){
banPlayerIP(address);
return true;
}
return false;
}
/**
* Returns list of all players with admin status
*/
@@ -527,6 +546,7 @@ public class Administration{
messageRateLimit = new Config("messageRateLimit", "Message rate limit in seconds. 0 to disable.", 0),
messageSpamKick = new Config("messageSpamKick", "How many times a player must send a message before the cooldown to get kicked. 0 to disable.", 3),
packetSpamLimit = new Config("packetSpamLimit", "Limit for packet count sent within 3sec that will lead to a blacklist + kick.", 300),
uuidChangeLimit = new Config("uuidChangeLimit", "Limit for how many UUID changes an IP can send in an hour before it gets banned.", 10),
chatSpamLimit = new Config("chatSpamLimit", "Limit for chat packet count sent within 2sec that will lead to a blacklist + kick. Not the same as a rate limit.", 20),
socketInput = new Config("socketInput", "Allows a local application to control this server through a local TCP socket.", false, "socket", () -> Events.fire(Trigger.socketConfigChanged)),
socketInputPort = new Config("socketInputPort", "The port for socket input.", 6859, () -> Events.fire(Trigger.socketConfigChanged)),
@@ -743,4 +763,8 @@ public class Administration{
breakBlock, placeBlock, rotate, configure, withdrawItem, depositItem, control, buildSelect, command, removePlanned, commandUnits, commandBuilding, respawn, pickupBlock, dropPayload, pingLocation
}
static class IdEncounterInfo{
long initialTime;
IntSet hashes = new IntSet();
}
}