diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java
index cab438991d926d6112439f5cc266c380961d534a..8dabdc0f61f7ceb65afa366bf5b7742ccb39bda7 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java
@@ -553,6 +553,14 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
             if (_log.shouldLog(Log.DEBUG))
                 _log.debug(getPrefix(requestId) + "Destination: " + destination);
             
+            // Serve local proxy files (images, css linked from error pages)
+            // Ignore all the headers
+            if (destination.equals("proxy.i2p")) {
+                serveLocalFile(out, method, targetRequest);
+                s.close();
+                return;
+            }
+
             Destination dest = I2PTunnel.destFromName(destination);
             if (dest == null) {
                 //l.log("Could not resolve " + destination + ".");
@@ -778,4 +786,70 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
 
         return protocol.equalsIgnoreCase("http://");
     }
+
+    private final static byte[] ERR_404 =
+        ("HTTP/1.1 404 Not Found\r\n"+
+         "Content-Type: text/plain\r\n"+
+         "\r\n"+
+         "HTTP Proxy local file not found")
+        .getBytes();
+
+    /**
+     *  Very simple web server.
+     *
+     *  Serve local files in the docs/ directory, for CSS and images in
+     *  error pages, using the reserved address proxy.i2p
+     *  (similar to p.p in privoxy).
+     *  This solves the problems with including links to the router console,
+     *  as assuming the router console is at 127.0.0.1 leads to broken
+     *  links if it isn't.
+     *
+     *  Ignore all request headers (If-Modified-Since, etc.)
+     *
+     *  There is basic protection here -
+     *  FileUtil.readFile() prevents traversal above the base directory -
+     *  but inproxy/gateway ops would be wise to block proxy.i2p to prevent
+     *  exposing the docs/ directory or perhaps other issues through
+     *  uncaught vulnerabilities.
+     *
+     *  @param targetRequest "proxy.i2p/foo.png HTTP/1.1"
+     */
+    private static void serveLocalFile(OutputStream out, String method, String targetRequest) {
+        if (method.equals("GET") || method.equals("HEAD")) {
+            int space = targetRequest.indexOf(' ');
+            String filename = null;
+            try {
+                filename = targetRequest.substring(10, space);
+            } catch (IndexOutOfBoundsException ioobe) {}
+            if (filename == null || filename.length() <= 0) {
+                try {
+                    out.write(("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nCache-Control: max-age=86400\r\n\r\nI2P HTTP proxy OK").getBytes());
+                    out.flush();
+                } catch (IOException ioe) {}
+                return;
+            }
+            File file = new File(_errorDir, filename);
+            if (file.exists() && !file.isDirectory()) {
+                String type;
+                if (filename.endsWith(".css"))
+                    type = "text/css";
+                else if (filename.endsWith(".png"))
+                    type = "image/png";
+                else if (filename.endsWith(".jpg"))
+                    type = "image/jpeg";
+                else type = "text/html";
+                try {
+                    out.write("HTTP/1.1 200 OK\r\nContent-Type: ".getBytes());
+                    out.write(type.getBytes());
+                    out.write("\r\nCache-Control: max-age=86400\r\n\r\n".getBytes());
+                    FileUtil.readFile(filename, _errorDir.getAbsolutePath(), out);
+                    return;
+                } catch (IOException ioe) {}
+            }
+        }
+        try {
+            out.write(ERR_404);
+            out.flush();
+        } catch (IOException ioe) {}
+    }
 }