From e613fb14d727fb4d71d36f052a3b5b49b357dec0 Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Fri, 22 Jul 2011 16:56:08 -0500 Subject: [PATCH] Add support for enforcing banned-ips.txt on internal web server --- configuration.default | 2 + src/main/java/org/dynmap/DynmapPlugin.java | 3 +- src/main/java/org/dynmap/web/HttpServer.java | 76 ++++++++++++++++++- .../org/dynmap/web/HttpServerConnection.java | 7 +- 4 files changed, 84 insertions(+), 4 deletions(-) diff --git a/configuration.default b/configuration.default index 2ba21c11..4f93ac4e 100644 --- a/configuration.default +++ b/configuration.default @@ -138,6 +138,8 @@ quitmessage: "%playername% quit" spammessage: "You may only chat once every %interval% seconds." webprefix: "§2[WEB] " websuffix: "§f" +# Enable checking for banned IPs via banned-ips.txt (internal web server only) +check-banned-ips: true defaultzoom: 0 defaultworld: world diff --git a/src/main/java/org/dynmap/DynmapPlugin.java b/src/main/java/org/dynmap/DynmapPlugin.java index d589e66b..6bd163d7 100644 --- a/src/main/java/org/dynmap/DynmapPlugin.java +++ b/src/main/java/org/dynmap/DynmapPlugin.java @@ -274,11 +274,12 @@ public class DynmapPlugin extends JavaPlugin { } int port = configuration.getInteger("webserver-port", 8123); boolean allow_symlinks = configuration.getBoolean("allow-symlinks", false); + boolean checkbannedips = configuration.getBoolean("check-banned-ips", true); if(allow_symlinks) Log.verboseinfo("Web server is permitting symbolic links"); else Log.verboseinfo("Web server is not permitting symbolic links"); - webServer = new HttpServer(bindAddress, port); + webServer = new HttpServer(bindAddress, port, checkbannedips); webServer.handlers.put("/", new FilesystemHandler(getFile(configuration.getString("webpath", "web")), allow_symlinks)); webServer.handlers.put("/tiles/", new FilesystemHandler(tilesDirectory, allow_symlinks)); webServer.handlers.put("/up/configuration", new ClientConfigurationHandler(this)); diff --git a/src/main/java/org/dynmap/web/HttpServer.java b/src/main/java/org/dynmap/web/HttpServer.java index 748092eb..3119c176 100644 --- a/src/main/java/org/dynmap/web/HttpServer.java +++ b/src/main/java/org/dynmap/web/HttpServer.java @@ -1,10 +1,16 @@ package org.dynmap.web; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; import java.io.IOException; import java.net.InetAddress; +import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; +import java.net.SocketAddress; import java.util.Collections; +import java.util.HashSet; import java.util.SortedMap; import java.util.TreeMap; import java.util.logging.Logger; @@ -13,19 +19,20 @@ import org.dynmap.Log; public class HttpServer extends Thread { protected static final Logger log = Logger.getLogger("Minecraft"); - protected static final String LOG_PREFIX = "[dynmap] "; private ServerSocket sock = null; private Thread listeningThread; private InetAddress bindAddress; private int port; + private boolean check_banned_ips; public SortedMap handlers = new TreeMap(Collections.reverseOrder()); - public HttpServer(InetAddress bindAddress, int port) { + public HttpServer(InetAddress bindAddress, int port, boolean check_banned_ips) { this.bindAddress = bindAddress; this.port = port; + this.check_banned_ips = check_banned_ips; } public InetAddress getAddress() { @@ -49,6 +56,11 @@ public class HttpServer extends Thread { while (listeningThread == Thread.currentThread()) { try { Socket socket = s.accept(); + if(checkForBannedIp(socket.getRemoteSocketAddress())) { + try { socket.close(); } catch (IOException iox) {} + socket = null; + } + HttpServerConnection requestThread = new HttpServerConnection(socket, this); requestThread.start(); } catch (IOException e) { @@ -75,4 +87,64 @@ public class HttpServer extends Thread { Log.warning("Exception while closing socket for webserver shutdown", e); } } + + private HashSet banned_ips = new HashSet(); + private HashSet banned_ips_notified = new HashSet(); + private long last_loaded = 0; + private long lastmod = 0; + private static final long BANNED_RELOAD_INTERVAL = 15000; /* Every 15 seconds */ + + private void loadBannedIPs() { + banned_ips.clear(); + banned_ips_notified.clear(); + File f = new File("banned-ips.txt"); + if(f.exists() == false) + return; + if(f.lastModified() == lastmod) { + return; + } + lastmod = f.lastModified(); + BufferedReader rdr = null; + try { + rdr = new BufferedReader(new FileReader(f)); + String line; + while((line = rdr.readLine()) != null) { + line = line.trim().toLowerCase(); /* Trim it and case normalize it */ + if((line.length() == 0) || (line.charAt(0) == '#')) { /* Blank or comment? */ + continue; + } + banned_ips.add(line); + } + } catch (IOException iox) { + Log.severe("Error reading banned-ips.txt!"); + } finally { + if(rdr != null) { + try { rdr.close(); } catch (IOException iox) {} + rdr = null; + } + } + } + /* Return true if address is banned */ + public boolean checkForBannedIp(SocketAddress socketAddress) { + if(!check_banned_ips) + return false; + + long t = System.currentTimeMillis(); + if((t < last_loaded) || ((t-last_loaded) > BANNED_RELOAD_INTERVAL)) { + loadBannedIPs(); + last_loaded = t; + } + /* Follow same technique as MC uses - toString the SocketAddress and clip out string between "/" and ":" */ + String ip = socketAddress.toString(); + ip = ip.substring(ip.indexOf("/") + 1); + ip = ip.substring(0, ip.indexOf(":")); + if(banned_ips.contains(ip)) { + if(banned_ips_notified.contains(ip) == false) { + Log.info("Rejected connection by banned IP address - " + socketAddress.toString()); + banned_ips_notified.add(ip); + } + return true; + } + return false; + } } diff --git a/src/main/java/org/dynmap/web/HttpServerConnection.java b/src/main/java/org/dynmap/web/HttpServerConnection.java index 0a00a8ff..411149ab 100644 --- a/src/main/java/org/dynmap/web/HttpServerConnection.java +++ b/src/main/java/org/dynmap/web/HttpServerConnection.java @@ -115,7 +115,7 @@ public class HttpServerConnection extends Thread { public final void writeResponseHeader(HttpResponse response) throws IOException { writeResponseHeader(printOut, response); } - + public void run() { try { if (socket == null) @@ -128,6 +128,11 @@ public class HttpServerConnection extends Thread { printOut = new PrintStream(out, false); while (true) { + /* Check for start of each request - kicks out persistent connections */ + if(server.checkForBannedIp(rmtaddr)) { + return; + } + HttpRequest request = new HttpRequest(); request.rmtaddr = rmtaddr; if (!readRequestHeader(in, request)) {