From 041c87a2c90b8bdfc174a1c3c0e7a30160a68b3e Mon Sep 17 00:00:00 2001 From: zzz Date: Thu, 31 May 2012 12:19:27 +0000 Subject: [PATCH] * i2psnark: - Add per-hour conn limit - Blacklist peer after two bad handshakes - Reduce connect timeout --- .../org/klomp/snark/ConnectionAcceptor.java | 32 ++++++++++++++++--- .../src/org/klomp/snark/I2PSnarkUtil.java | 5 +++ .../src/org/klomp/snark/PeerAcceptor.java | 12 ++++++- history.txt | 6 ++++ .../src/net/i2p/router/RouterVersion.java | 2 +- 5 files changed, 51 insertions(+), 6 deletions(-) diff --git a/apps/i2psnark/java/src/org/klomp/snark/ConnectionAcceptor.java b/apps/i2psnark/java/src/org/klomp/snark/ConnectionAcceptor.java index b4ba0f299..0211f6bbd 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/ConnectionAcceptor.java +++ b/apps/i2psnark/java/src/org/klomp/snark/ConnectionAcceptor.java @@ -29,8 +29,12 @@ import net.i2p.I2PAppContext; import net.i2p.I2PException; import net.i2p.client.streaming.I2PServerSocket; import net.i2p.client.streaming.I2PSocket; +import net.i2p.data.Hash; import net.i2p.util.I2PAppThread; import net.i2p.util.Log; +import net.i2p.util.ObjectCounter; +import net.i2p.util.SimpleScheduler; +import net.i2p.util.SimpleTimer; /** * Accepts connections on a TCP port and routes them to sub-acceptors. @@ -41,11 +45,15 @@ public class ConnectionAcceptor implements Runnable private I2PServerSocket serverSocket; private PeerAcceptor peeracceptor; private Thread thread; - private I2PSnarkUtil _util; + private final I2PSnarkUtil _util; + private final ObjectCounter _badCounter = new ObjectCounter(); private boolean stop; private boolean socketChanged; + private static final int MAX_BAD = 2; + private static final long BAD_CLEAN_INTERVAL = 30*60*1000; + public ConnectionAcceptor(I2PSnarkUtil util) { _util = util; } public synchronized void startAccepting(PeerCoordinatorSet set, I2PServerSocket socket) { @@ -59,6 +67,7 @@ public class ConnectionAcceptor implements Runnable thread = new I2PAppThread(this, "I2PSnark acceptor"); thread.setDaemon(true); thread.start(); + SimpleScheduler.getInstance().addPeriodicEvent(new Cleaner(), BAD_CLEAN_INTERVAL); } } } @@ -70,11 +79,10 @@ public class ConnectionAcceptor implements Runnable this.peeracceptor = peeracceptor; _util = util; - socketChanged = false; - stop = false; thread = new I2PAppThread(this, "I2PSnark acceptor"); thread.setDaemon(true); thread.start(); + SimpleScheduler.getInstance().addPeriodicEvent(new Cleaner(), BAD_CLEAN_INTERVAL); } public void halt() @@ -142,6 +150,12 @@ public class ConnectionAcceptor implements Runnable try { socket.close(); } catch (IOException ioe) {} continue; } + if (_badCounter.count(socket.getPeerDestination().calculateHash()) >= MAX_BAD) { + if (_log.shouldLog(Log.WARN)) + _log.warn("Rejecting connection from " + socket.getPeerDestination().calculateHash() + " after " + MAX_BAD + " failures"); + try { socket.close(); } catch (IOException ioe) {} + continue; + } Thread t = new I2PAppThread(new Handler(socket), "I2PSnark incoming connection"); t.start(); } @@ -171,10 +185,12 @@ public class ConnectionAcceptor implements Runnable } private class Handler implements Runnable { - private I2PSocket _socket; + private final I2PSocket _socket; + public Handler(I2PSocket socket) { _socket = socket; } + public void run() { try { InputStream in = _socket.getInputStream(); @@ -184,6 +200,9 @@ public class ConnectionAcceptor implements Runnable if (_log.shouldLog(Log.DEBUG)) _log.debug("Handling socket from " + _socket.getPeerDestination().calculateHash().toBase64()); peeracceptor.connection(_socket, in, out); + } catch (PeerAcceptor.ProtocolException ihe) { + _badCounter.increment(_socket.getPeerDestination().calculateHash()); + try { _socket.close(); } catch (IOException ignored) { } } catch (IOException ioe) { if (_log.shouldLog(Log.DEBUG)) _log.debug("Error handling connection from " + _socket.getPeerDestination().calculateHash().toBase64(), ioe); @@ -191,4 +210,9 @@ public class ConnectionAcceptor implements Runnable } } } + + /** @since 0.9.1 */ + private class Cleaner implements SimpleTimer.TimedEvent { + public void timeReached() { _badCounter.clear(); } + } } diff --git a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java index f4e98147a..77c10d402 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java +++ b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java @@ -20,6 +20,7 @@ import net.i2p.client.streaming.I2PSocket; import net.i2p.client.streaming.I2PSocketEepGet; import net.i2p.client.streaming.I2PSocketManager; import net.i2p.client.streaming.I2PSocketManagerFactory; +import net.i2p.client.streaming.I2PSocketOptions; import net.i2p.data.Base32; import net.i2p.data.DataFormatException; import net.i2p.data.Destination; @@ -210,6 +211,8 @@ public class I2PSnarkUtil { // we don't need fast handshake for peer connections. //if (opts.getProperty("i2p.streaming.connectDelay") == null) // opts.setProperty("i2p.streaming.connectDelay", "500"); + if (opts.getProperty(I2PSocketOptions.PROP_CONNECT_TIMEOUT) == null) + opts.setProperty(I2PSocketOptions.PROP_CONNECT_TIMEOUT, "75000"); if (opts.getProperty("i2p.streaming.inactivityTimeout") == null) opts.setProperty("i2p.streaming.inactivityTimeout", "240000"); if (opts.getProperty("i2p.streaming.inactivityAction") == null) @@ -226,6 +229,8 @@ public class I2PSnarkUtil { opts.setProperty("i2p.streaming.maxConnsPerMinute", "2"); if (opts.getProperty("i2p.streaming.maxTotalConnsPerMinute") == null) opts.setProperty("i2p.streaming.maxTotalConnsPerMinute", "8"); + if (opts.getProperty("i2p.streaming.maxConnsPerHour") == null) + opts.setProperty("i2p.streaming.maxConnsPerHour", "20"); _manager = I2PSocketManagerFactory.createManager(_i2cpHost, _i2cpPort, opts); } // FIXME this only instantiates krpc once, left stuck with old manager diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerAcceptor.java b/apps/i2psnark/java/src/org/klomp/snark/PeerAcceptor.java index 1bd49c25a..53b14b175 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerAcceptor.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerAcceptor.java @@ -143,9 +143,19 @@ public class PeerAcceptor byte buf[] = new byte[LOOKAHEAD_SIZE]; int read = DataHelper.read(in, buf); if (read != buf.length) - throw new IOException("Unable to read the hash (read " + read + ")"); + throw new ProtocolException("Unable to read the hash (read " + read + ")"); byte rv[] = new byte[20]; System.arraycopy(buf, buf.length-rv.length, rv, 0, rv.length); return rv; } + + /** + * A unique exception so we can tell the ConnectionAcceptor about non-BT connections + * @since 0.9.1 + */ + public static class ProtocolException extends IOException { + public ProtocolException(String s) { + super(s); + } + } } diff --git a/history.txt b/history.txt index e19fdd241..94d50249f 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,9 @@ +2012-05-31 zzz + * i2psnark: + - Add per-hour conn limit + - Blacklist peer after two bad handshakes + - Reduce connect timeout + 2012-05-30 zzz * Graphs: Reduce log EOF error to warn * i2psnark: diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index fecba78d6..a6204817e 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 7; + public final static long BUILD = 8; /** for example "-test" */ public final static String EXTRA = "";