diff --git a/GameServer/conf/world.xml b/GameServer/conf/world.xml index 7b087fa..126d308 100644 --- a/GameServer/conf/world.xml +++ b/GameServer/conf/world.xml @@ -27,8 +27,25 @@ None 1800000 - sudo route add -host ${ip} reject - sudo route del -host ${ip} reject + true + sudo route add -host ${ip} reject + sudo route del -host ${ip} reject + true + + + false + + true + + true + + 100 + + 5 + + 6000000 diff --git a/GameServer/src/org/moparscape/msc/config/Config.java b/GameServer/src/org/moparscape/msc/config/Config.java index 43f8139..adddca1 100644 --- a/GameServer/src/org/moparscape/msc/config/Config.java +++ b/GameServer/src/org/moparscape/msc/config/Config.java @@ -22,11 +22,11 @@ public class Config { SERVER_LOCATION, LS_IP; public static int SERVER_PORT, SERVER_VERSION, MAX_PLAYERS, LS_PORT, - SERVER_NUM; + SERVER_NUM, CONENCTION_THROTTLE_THRESHOLD; public static long START_TIME; - public static boolean members, f2pWildy; + public static boolean members, f2pWildy, APPLICATION_LEVEL_BLOCKING; public static double expRate, subExpRate; @@ -34,11 +34,11 @@ public class Config { public static int IP_BAN_REMOVAL_DELAY; public static int GARBAGE_COLLECT_INTERVAL; public static int SAVE_INTERVAL; - public static String DATE_FORMAT; - public static String BLOCK_COMMAND; - public static String UNBLOCK_COMMAND; - public static String ALERT_CONFIG; - public static String COMMAND_CONFIG; + public static String DATE_FORMAT, BLOCK_COMMAND, UNBLOCK_COMMAND, + ALERT_CONFIG, COMMAND_CONFIG; + public static int CONNECTION_THROTTLE_SIZE; + public static boolean OS_LEVEL_BLOCKING, APPLICATION_LEVEL_THROTTLE_ALERT, + OS_LEVEL_THROTTLE_ALERT, OS_LEVEL_UNBLOCK_FAILED_ALERT; static { loadEnv(); @@ -88,6 +88,20 @@ public class Config { .getProperty("ip-ban-removal-delay")); BLOCK_COMMAND = props.getProperty("block-command"); UNBLOCK_COMMAND = props.getProperty("unblock-command"); + CONNECTION_THROTTLE_SIZE = Integer.parseInt(props + .getProperty("connection-throttle-size")); + CONENCTION_THROTTLE_THRESHOLD = Integer.parseInt(props + .getProperty("connection-throttle")); + APPLICATION_LEVEL_BLOCKING = Boolean.parseBoolean(props + .getProperty("application-level-blocking")); + OS_LEVEL_BLOCKING = Boolean.parseBoolean(props + .getProperty("os-level-blocking")); + APPLICATION_LEVEL_THROTTLE_ALERT = Boolean.parseBoolean(props + .getProperty("application-level-blocking-throttle-alert")); + OS_LEVEL_THROTTLE_ALERT = Boolean.parseBoolean(props + .getProperty("os-level-blocking-throttle-alert")); + OS_LEVEL_UNBLOCK_FAILED_ALERT = Boolean.parseBoolean(props + .getProperty("os-level-blocking-unblock-failed-alert")); GARBAGE_COLLECT_INTERVAL = Integer.parseInt(props .getProperty("garbage-collect-interval")); diff --git a/GameServer/src/org/moparscape/msc/gs/Cache.java b/GameServer/src/org/moparscape/msc/gs/Cache.java index f18d06b..5ff5e1a 100644 --- a/GameServer/src/org/moparscape/msc/gs/Cache.java +++ b/GameServer/src/org/moparscape/msc/gs/Cache.java @@ -11,10 +11,17 @@ import org.apache.commons.collections.map.LRUMap; * */ public class Cache { + + private Map cache; + + public Cache() { + this(100); + } - // Shitty commons and their failure to support generics... @SuppressWarnings("unchecked") - private Map cache = new LRUMap(); + public Cache(int size) { + cache = new LRUMap(size); + } public V get(K key) { return cache.get(key); diff --git a/GameServer/src/org/moparscape/msc/gs/connection/RSCConnectionHandler.java b/GameServer/src/org/moparscape/msc/gs/connection/RSCConnectionHandler.java index 6b858c3..1c09647 100644 --- a/GameServer/src/org/moparscape/msc/gs/connection/RSCConnectionHandler.java +++ b/GameServer/src/org/moparscape/msc/gs/connection/RSCConnectionHandler.java @@ -15,18 +15,7 @@ import org.moparscape.msc.gs.util.Logger; * Handles the protocol events fired from MINA. */ public class RSCConnectionHandler implements IoHandler { - /** - * World instance - */ - /* - * - * private int attackers = 0; - * - * private Map clients; private Set - * connectedAddresses; private Map counts; private - * long lastAttack = 0; - */ /** * A reference to the game engine's packet queue */ @@ -41,22 +30,8 @@ public class RSCConnectionHandler implements IoHandler { */ public RSCConnectionHandler(GameEngine engine) { packets = (PacketQueue) engine.getPacketQueue(); - /* - * clients = Collections.synchronizedMap(new HashMap()); counts = Collections.synchronizedMap(new - * HashMap()); written = - * Collections.synchronizedMap(new HashMap()); - * connectedAddresses = new HashSet(); - */ } - /* - * public void connectionOk(IoSession io) { counts.remove(getAddress(io)); } - * - * public void delayClient(IoSession session, int delay) { long d = - * System.currentTimeMillis() - delay; clients.put(getAddress(session), d); - * } - */ /** * Invoked whenever an exception is thrown by MINA or this IoHandler. * @@ -67,69 +42,13 @@ public class RSCConnectionHandler implements IoHandler { */ public void exceptionCaught(IoSession session, Throwable cause) { Player p = (Player) session.getAttachment(); - // if(p.getUsername().equalsIgnoreCase("xent")) { - - // } + if (p != null) p.getActionSender().sendLogout(); session.close(); - /* - * Logging.debug("---MINA Error from: " + p.getUsername() + " -------"); - * cause.printStackTrace();Logging.debug( - * "------------------------------------------------------------"); - */ cause.printStackTrace(); } - /** - * Method responsible for deciding if a connection is OK to continue - * - * @param session - * The new session that will be verified - * @return True if the session meets the criteria, otherwise false (if - * false, adds to a IPSec filter & writes IP to log. - */ - /* - * public boolean isConnectionOk(IoSession session) { final InetAddress addr - * = getAddress(session); final String ip = addr.toString().replaceAll("/", - * ""); // ip = ip.replaceAll("/",""); long now = - * System.currentTimeMillis(); int c = 0; if (counts.containsKey(addr) && - * clients.containsKey(addr)) { try { c = counts.get(addr); } catch - * (Exception e) { Logging.debug("Error: " + e); } if (c >= 5) { if - * (!written.containsKey(addr)) { attackers++; // if(now - lastAttack > - * 60000) // { // for(Player p : world.getPlayers()) // { // p.save(); // - * p.getActionSender().sendLogout(); // } // - * Instance.getServer().getLoginConnector - * ().getActionSender().saveProfiles(); // } try { /* - * Logging.debug("ATTACKER IP: " + ip); BufferedWriter bf2 = new - * BufferedWriter(new FileWriter( "ddos.log", true)); - * bf2.write("sudo /sbin/route add " + addr.getHostAddress() + - * " gw 127.0.0.1"); bf2.newLine(); bf2.close(); / written.put(addr, 1); - * Instance.getDelayedEventHandler().add(new DelayedEvent(null, 3600000) { - * public void run() { written.remove(addr); counts.remove(addr); try { - * Runtime.getRuntime().exec("sudo /sbin/route delete " + ip); } catch - * (Exception err) { Logging.debug(err); } } }); try { - * Runtime.getRuntime().exec("sudo /sbin/route add " + ip + - * " gw 127.0.0.1"); } catch (Exception err) { Logging.debug(err); } - * - * // try { Runtime.getRuntime().exec(ip + ".bat"); } // catch (Exception - * err) { Logging.debug(err); } lastAttack = now; } catch (Exception e) { - * System.err.println(e); } } return false; } } if - * (clients.containsKey(addr)) { long lastConnTime = clients.get(addr); if - * (now - lastConnTime < 2000) { if (!counts.containsKey(addr)) - * counts.put(addr, 0); else c = counts.get(addr) + 1; counts.put(addr, c); - * return false; } else { clients.put(addr, now); if - * (counts.containsKey(addr)) counts.remove(addr); return true; } } else { - * clients.put(addr, now); return true; } } - */ - /** - * Invoked whenever a packet is ready to be added to the queue. - * - * @param session - * The IO session on which the packet was received - * @param message - * The packet - */ public void messageReceived(IoSession session, Object message) { Player player = (Player) session.getAttachment(); if (session.isClosing() || player.destroyed()) { @@ -137,12 +56,6 @@ public class RSCConnectionHandler implements IoHandler { } RSCPacket p = (RSCPacket) message; - /* - * if(p.getID() == 57 || p.getID() == 73 || p.getID() == 40 || p.getID() - * == 51 || p.getID() == 128 || p.getID() == 206 || p.getID() == 71 || - * p.getID() == 55) - */ - if (p.getID() == 55) player.addInterval(); @@ -176,14 +89,9 @@ public class RSCConnectionHandler implements IoHandler { } public void sessionCreated(IoSession session) { - /* - * if (!isConnectionOk(session)) { session.close(); return; } else { - * connectionOk(session); } - */ session.getFilterChain().addFirst("protocolFilter", new ProtocolCodecFilter(new RSCCodecFactory())); - // Logger.event("Connection from: " + - // ((InetSocketAddress)session.getRemoteAddress()).getAddress().getHostAddress()); + Logger.println("Connection from: " + ((InetSocketAddress) session.getRemoteAddress()).getAddress() .getHostAddress()); diff --git a/GameServer/src/org/moparscape/msc/gs/connection/filter/ConnectionFilter.java b/GameServer/src/org/moparscape/msc/gs/connection/filter/ConnectionFilter.java index 8c34be8..b35c829 100644 --- a/GameServer/src/org/moparscape/msc/gs/connection/filter/ConnectionFilter.java +++ b/GameServer/src/org/moparscape/msc/gs/connection/filter/ConnectionFilter.java @@ -6,21 +6,25 @@ import java.net.SocketAddress; import org.apache.mina.common.IoFilter; import org.apache.mina.common.IoSession; import org.apache.mina.filter.BlacklistFilter; +import org.moparscape.msc.config.Config; import org.moparscape.msc.gs.util.Cache; public class ConnectionFilter extends BlacklistFilter { - private Cache connections = new Cache(); - private static final int BLOCK_THRESHOLD = 5; + private Cache connections = new Cache( + Config.CONNECTION_THROTTLE_SIZE); public void sessionCreated(IoFilter.NextFilter nextFilter, IoSession session) { final SocketAddress sa = session.getRemoteAddress(); if (sa != null && sa instanceof InetSocketAddress) { final InetSocketAddress a = (InetSocketAddress) sa; + if(IPBanManager.isBlocked(a)) { + block(a.getAddress()); + return; + } final Integer val = connections.get(a); - System.out.println(val); final Integer retVal = connections .put(a, val == null ? 1 : val + 1); - if (retVal != null && retVal > BLOCK_THRESHOLD) { + if (retVal != null && retVal > Config.CONENCTION_THROTTLE_THRESHOLD) { block(a.getAddress()); } } @@ -33,10 +37,10 @@ public class ConnectionFilter extends BlacklistFilter { if (sa != null && sa instanceof InetSocketAddress) { final InetSocketAddress a = (InetSocketAddress) sa; final Integer val = connections.get(a); - System.out.println(val); final Integer retVal = connections .put(a, val == null ? 1 : val + 1); - if (retVal != null && retVal - 1 <= BLOCK_THRESHOLD) { + if (retVal != null + && retVal - 1 <= Config.CONENCTION_THROTTLE_THRESHOLD) { unblock(a.getAddress()); } } diff --git a/GameServer/src/org/moparscape/msc/gs/connection/filter/IPBanManager.scala b/GameServer/src/org/moparscape/msc/gs/connection/filter/IPBanManager.scala new file mode 100644 index 0000000..ce92c71 --- /dev/null +++ b/GameServer/src/org/moparscape/msc/gs/connection/filter/IPBanManager.scala @@ -0,0 +1,179 @@ +package org.moparscape.msc.gs.connection.filter; + +import java.util.List +import java.util.concurrent.CopyOnWriteArrayList +import org.moparscape.msc.gs.Server +import org.moparscape.msc.gs.core.DelayedEventHandler +import org.moparscape.msc.gs.event.DelayedEvent +import org.moparscape.msc.gs.util.Logger +import org.moparscape.msc.config.Config +import org.moparscape.msc.gs.alert.AlertHandler +import java.net.InetSocketAddress +import java.net.SocketAddress +import scala.collection.JavaConversions._ + +object IPBanManager extends Blocker { + override def isBlocked(ip: String) = { + var v = false + if (Config.APPLICATION_LEVEL_BLOCKING) + v = ApplicationLevelBlocking.isBlocked(ip) + if (Config.OS_LEVEL_BLOCKING) + v = v || OSLevelBlocking.isBlocked(ip) + v + } + + def isBlocked(ip: SocketAddress): Boolean = { + isBlocked(lookupIP(ip)) + } + + override def throttle(ip: String) { + if (Config.APPLICATION_LEVEL_BLOCKING) + ApplicationLevelBlocking.throttle(ip) + if (Config.OS_LEVEL_BLOCKING) + OSLevelBlocking.throttle(ip) + } + + def throttle(ip: java.util.List[String]) { + ip foreach { throttle(_) } + } + + def throttle(ip: SocketAddress) { + throttle(lookupIP(ip)) + } + + override def block(ip: String) { + if (ip != null && ip.length > 0) { + if (Config.APPLICATION_LEVEL_BLOCKING) + ApplicationLevelBlocking.block(ip) + if (Config.OS_LEVEL_BLOCKING) + OSLevelBlocking.block(ip) + } + + } + + def block(ip: java.util.List[String]) { + ip foreach { block(_) } + } + + def block(ip: SocketAddress) { + block(lookupIP(ip)) + } + + override def unblock(ip: String) { + ApplicationLevelBlocking.unblock(ip) + OSLevelBlocking.unblock(ip) + } + + def unblock(ip: SocketAddress) { + unblock(lookupIP(ip)) + } + + private def lookupIP(sa: SocketAddress): String = { + if (sa != null && sa.isInstanceOf[InetSocketAddress]) { + val a = sa.asInstanceOf[InetSocketAddress] + return a.getAddress.getHostAddress + } + return null + } +} + +trait Blocker { + def isBlocked(ip: String): Boolean + def block(ip: String) + def unblock(ip: String) + def throttle(ip: String) +} + +private object ApplicationLevelBlocking extends Blocker { + private val blocked = new CopyOnWriteArrayList[String]; + + private val throttled = new CopyOnWriteArrayList[String] + + private val events = Server.getServer().getEngine().getEventHandler() + + override def isBlocked(ip: String) = { + if (blocked.contains(ip)) { + true + } + false + } + + override def block(ip: String) { + blocked.addIfAbsent(ip) + } + + override def unblock(ip: String) { + blocked.remove(ip) + } + + override def throttle(ip: String) { + if (!throttled.contains(ip)) { + events.add(new DelayedEvent(null, Config.IP_BAN_REMOVAL_DELAY) { + + override def run() { + unblock(ip) + throttled.remove(ip) + Logger.println("Application - Unblocked " + ip) + } + }) + block(ip) + throttled.add(ip) + if (Config.APPLICATION_LEVEL_THROTTLE_ALERT) + AlertHandler.sendAlert("Application - Throttled " + ip, throttled.size / 10) + Logger.println("Application - Throttled " + ip) + } + } +} + +private object OSLevelBlocking extends Blocker { + + private val throttled = new CopyOnWriteArrayList[String] + private val blocked = new CopyOnWriteArrayList[String] + + private val events = Server.getServer().getEngine().getEventHandler() + + override def isBlocked(ip: String) = { + if (blocked.contains(ip)) { + true + } + false + } + + override def throttle(ip: String) { + if (!throttled.contains(ip)) { + events.add(new DelayedEvent(null, Config.IP_BAN_REMOVAL_DELAY) { + + override def run() { + unblock(ip) + throttled.remove(ip) + } + }) + block(ip) + throttled.add(ip) + if (Config.OS_LEVEL_THROTTLE_ALERT) + AlertHandler.sendAlert("OS - Throttled " + ip, throttled.size / 10) + Logger.println("OS - Throttled " + ip) + } + } + + override def block(ip: String) { + Runtime.getRuntime.exec(Config.BLOCK_COMMAND.replaceAll("${ip}", ip)) + blocked addIfAbsent ip + } + + override def unblock(ip: String) { + try { + Runtime.getRuntime.exec(Config.UNBLOCK_COMMAND.replaceAll("${ip}", ip)) + blocked remove ip + throttled.remove(ip) + Logger.println("OS - Unblocked " + ip) + } catch { + case e: Exception => { + Logger.println("OS - Failed to unblock " + ip) + Logger.error(e) + if (Config.OS_LEVEL_UNBLOCK_FAILED_ALERT) + AlertHandler.sendAlert("OS - Failed to unblock " + ip, 2) + } + } + } +} diff --git a/GameServer/src/org/moparscape/msc/gs/connection/filter/OSLevelBlocking.scala b/GameServer/src/org/moparscape/msc/gs/connection/filter/OSLevelBlocking.scala deleted file mode 100644 index d3be48f..0000000 --- a/GameServer/src/org/moparscape/msc/gs/connection/filter/OSLevelBlocking.scala +++ /dev/null @@ -1,42 +0,0 @@ -package org.moparscape.msc.gs.connection.filter; - -import java.util.List -import java.util.concurrent.CopyOnWriteArrayList -import org.moparscape.msc.gs.Server -import org.moparscape.msc.gs.core.DelayedEventHandler -import org.moparscape.msc.gs.event.DelayedEvent -import org.moparscape.msc.gs.util.Logger -import org.moparscape.msc.config.Config -import org.moparscape.msc.gs.alert.AlertHandler - -object OSLevelBlocking { - - private val blocked = new CopyOnWriteArrayList[String]; - - private val events = Server.getServer().getEngine().getEventHandler() - - def block(ip: String) { - if (!blocked.contains(ip)) { - events.add(new DelayedEvent(null, Config.IP_BAN_REMOVAL_DELAY) { - - def run() { - try { - Runtime.getRuntime.exec(Config.UNBLOCK_COMMAND.replaceAll("${ip}", ip)); - blocked.remove(ip) - Logger.println("Unblocked " + ip) - } catch { - case e: Exception => { - Logger.error(e) - Logger.println("Failed to unblock " + ip) - AlertHandler.sendAlert("Failed to unblock " + ip, 2); - } - } - } - }) - Runtime.getRuntime.exec(Config.BLOCK_COMMAND.replaceAll("${ip}", ip)); - blocked.add(ip) - AlertHandler.sendAlert("Blocked " + ip, blocked.size / 10); - Logger.println("Blocked " + ip) - } - } -} diff --git a/GameServer/src/org/moparscape/msc/gs/core/GameEngine.java b/GameServer/src/org/moparscape/msc/gs/core/GameEngine.java index 9348146..1e26000 100644 --- a/GameServer/src/org/moparscape/msc/gs/core/GameEngine.java +++ b/GameServer/src/org/moparscape/msc/gs/core/GameEngine.java @@ -228,8 +228,7 @@ public final class GameEngine extends Thread { if (player.getUsername() == null && p.getID() != 32 && p.getID() != 77 && p.getID() != 0) { final String ip = player.getCurrentIP(); - // flagSession(session); - OSLevelBlocking.block(ip); + OSLevelBlocking.throttle(ip); continue; } PacketHandler handler = packetHandlers.get(p.getID()); diff --git a/LoginServer/conf/LSPacketHandlers.xml b/LoginServer/conf/LSPacketHandlers.xml index 9c9e6be..4af6c7e 100644 --- a/LoginServer/conf/LSPacketHandlers.xml +++ b/LoginServer/conf/LSPacketHandlers.xml @@ -1,92 +1,106 @@ - - - 1 - 2 - - org.moparscape.msc.ls.packethandler.loginserver.RegisterWorld - - - - 3 - - org.moparscape.msc.ls.packethandler.loginserver.KillHandler - - - - 4 - 5 - - org.moparscape.msc.ls.packethandler.loginserver.BanHandler - - - - 6 - - org.moparscape.msc.ls.packethandler.loginserver.PrivacySettingHandler - - - - 7 - - org.moparscape.msc.ls.packethandler.loginserver.GameSettingHandler - - - - 8 - - org.moparscape.msc.ls.packethandler.loginserver.PlayerInfoRequestHandler - - - - 9 - - org.moparscape.msc.ls.packethandler.loginserver.SaveProfilesRequestHandler - - - - 10 - 11 - 12 - 13 - 14 - - org.moparscape.msc.ls.packethandler.loginserver.FriendHandler - - - - 15 - - org.moparscape.msc.ls.packethandler.loginserver.ReportHandler - - - - 20 - - org.moparscape.msc.ls.packethandler.loginserver.PlayerSaveHandler - - - - 30 - - org.moparscape.msc.ls.packethandler.loginserver.PlayerLogoutHandler - - - - 31 - - org.moparscape.msc.ls.packethandler.loginserver.PlayerLoginHandler - - - - 32 - - org.moparscape.msc.ls.packethandler.loginserver.LogHandler - - - - 33 - - org.moparscape.msc.ls.packethandler.loginserver.Tradelog - + + + 1 + 2 + + org.moparscape.msc.ls.packethandler.loginserver.RegisterWorld + + + + + 3 + + org.moparscape.msc.ls.packethandler.loginserver.KillHandler + + + + + 4 + 5 + + org.moparscape.msc.ls.packethandler.loginserver.BanHandler + + + + + 6 + + org.moparscape.msc.ls.packethandler.loginserver.PrivacySettingHandler + + + + + 7 + + org.moparscape.msc.ls.packethandler.loginserver.GameSettingHandler + + + + + 8 + + org.moparscape.msc.ls.packethandler.loginserver.PlayerInfoRequestHandler + + + + + 9 + + org.moparscape.msc.ls.packethandler.loginserver.SaveProfilesRequestHandler + + + + + 10 + 11 + 12 + 13 + 14 + + org.moparscape.msc.ls.packethandler.loginserver.FriendHandler + + + + + 15 + + org.moparscape.msc.ls.packethandler.loginserver.ReportHandler + + + + + 20 + + org.moparscape.msc.ls.packethandler.loginserver.PlayerSaveHandler + + + + + 30 + + org.moparscape.msc.ls.packethandler.loginserver.PlayerLogoutHandler + + + + + 31 + + org.moparscape.msc.ls.packethandler.loginserver.PlayerLoginHandler + + + + + 32 + + org.moparscape.msc.ls.packethandler.loginserver.LogHandler + + + + + 33 + + org.moparscape.msc.ls.packethandler.loginserver.Tradelog + +