From ab96b9087333668d7048fd171fbc6f4d425c4a37 Mon Sep 17 00:00:00 2001 From: Cmd-GZ Date: Wed, 1 Jul 2026 02:13:02 +0800 Subject: [PATCH] Fix: Modify GlobalServer to implement a simple Dos defence way 1. Add a upper bound of the number of connection for per IP 2. Reject connection for request with symbol `&`, which is not encoded 3. Reject connection for too long request, which should be handle in the client --- src/GlobalServer/GlobalServer.java | 59 ++++++++++++++++++++++++++++++ src/GlobalServer/LobbyPlayer.java | 13 +++++++ src/GraphServer/Constants.java | 3 ++ 3 files changed, 75 insertions(+) diff --git a/src/GlobalServer/GlobalServer.java b/src/GlobalServer/GlobalServer.java index a888b84..7bd5284 100644 --- a/src/GlobalServer/GlobalServer.java +++ b/src/GlobalServer/GlobalServer.java @@ -26,8 +26,10 @@ import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.HashMap; import java.util.List; import java.util.ListIterator; +import java.util.Map; import java.util.Timer; import java.util.TimerTask; import java.util.Vector; @@ -44,6 +46,7 @@ public class GlobalServer implements Runnable private List rooms; private long lastRoomCheck; + private Map ipConnectionCount; private static final String STATUS_FILE = "/home/graphwar/graphwar/status.html"; private static final long STATUS_INTERVAL = 30 * 1000; @@ -52,6 +55,7 @@ public GlobalServer() { this.players = new Vector(); this.rooms = new Vector(); + this.ipConnectionCount = new HashMap(); lastRoomCheck = System.currentTimeMillis(); @@ -184,6 +188,8 @@ public void removePlayer(LobbyPlayer player) { players.remove(player); } + + decrementIpCount(player.getIpAddress()); if(player.getRoom() != null) { @@ -191,6 +197,38 @@ public void removePlayer(LobbyPlayer player) } } + public void rejectPlayer(LobbyPlayer player) + { + player.disconnect(); + + synchronized(players) + { + players.remove(player); + } + + decrementIpCount(player.getIpAddress()); + } + + private void decrementIpCount(String ip) + { + synchronized(ipConnectionCount) + { + Integer c = ipConnectionCount.get(ip); + if(c != null) + { + int newCount = c.intValue() - 1; + if(newCount <= 0) + { + ipConnectionCount.remove(ip); + } + else + { + ipConnectionCount.put(ip, newCount); + } + } + } + } + public void removeRoom(Room room) { String message = NetworkProtocol.CLOSE_ROOM+"&"+room.getRoomID(); @@ -364,6 +402,22 @@ private void waitConnection() throws IOException if(connected) { + String ip = tempSocket.getInetAddress().getHostAddress(); + + int count; + synchronized(ipConnectionCount) + { + Integer c = ipConnectionCount.get(ip); + count = (c == null) ? 0 : c.intValue(); + } + + if(count >= Constants.MAX_CONNECTIONS_PER_IP) + { + System.out.println("Rejected connection from " + ip + ": too many connections (" + count + ")"); + try { tempSocket.close(); } catch (IOException e) { } + return; + } + Connection connection = new Connection(tempSocket); LobbyPlayer player = new LobbyPlayer(connection, this); @@ -373,6 +427,11 @@ private void waitConnection() throws IOException this.players.add(player); } + synchronized(ipConnectionCount) + { + ipConnectionCount.put(ip, count + 1); + } + new Thread(player).start(); } } diff --git a/src/GlobalServer/LobbyPlayer.java b/src/GlobalServer/LobbyPlayer.java index 606f002..6324616 100644 --- a/src/GlobalServer/LobbyPlayer.java +++ b/src/GlobalServer/LobbyPlayer.java @@ -134,6 +134,19 @@ public void run() System.out.println("New name: "+name); + if(name == null) + { + this.globalServer.rejectPlayer(this); + return; + } + + if(name.length() > Constants.MAX_NAME_LENGTH || name.indexOf('&') != -1) + { + System.out.println("Rejected invalid name from " + getIpAddress() + ": length=" + name.length()); + this.globalServer.rejectPlayer(this); + return; + } + if(name.compareTo(Constants.DUMMY_NAME) == 0) { this.dummy = true; diff --git a/src/GraphServer/Constants.java b/src/GraphServer/Constants.java index 832ac2f..33905f9 100644 --- a/src/GraphServer/Constants.java +++ b/src/GraphServer/Constants.java @@ -45,6 +45,9 @@ public class Constants public static final int TURN_TIME = 60000; + public static final int MAX_NAME_LENGTH = 256; + public static final int MAX_CONNECTIONS_PER_IP = 32; + public static final int MAX_PLAYERS = 10; public static final int MAX_SOLDIERS_PER_PLAYER = 4; public static final int MAX_CLIENTS = 10;