diff --git a/router/java/src/net/i2p/router/transport/udp/IPThrottler.java b/router/java/src/net/i2p/router/transport/udp/IPThrottler.java index a318c9101..9daf4c92e 100644 --- a/router/java/src/net/i2p/router/transport/udp/IPThrottler.java +++ b/router/java/src/net/i2p/router/transport/udp/IPThrottler.java @@ -25,12 +25,12 @@ class IPThrottler { */ public boolean shouldThrottle(byte[] ip) { // for IPv4 we simply use the IP; - // for IPv6 we use a secure hash as an attacker could select the lower bytes + // for IPv6 we use a hash of the first 8 bytes Integer key; if (ip.length == 4) key = toInt(ip); else - key = Integer.valueOf(SipHash.hashCode(ip)); + key = hashCode(ip); return _counter.increment(key) > _max; } @@ -41,6 +41,15 @@ class IPThrottler { return Integer.valueOf(rv); } + /** @since 0.9.55 */ + private static Integer hashCode(byte ip[]) { + int rv = 0; + for (int i = 0; i < 8; i++) { + rv ^= ip[i] << (i * 4); + } + return Integer.valueOf(rv); + } + private class Cleaner implements SimpleTimer.TimedEvent { public void timeReached() { _counter.clear(); diff --git a/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java b/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java index e1bb090b6..8a130adcd 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java @@ -984,22 +984,9 @@ class PeerTestManager { return; } } - if (_throttle.shouldThrottle(fromIP)) { - if (_log.shouldLog(Log.WARN)) - _log.warn("PeerTest throttle from " + Addresses.toString(fromIP, fromPort)); - return; - } // common checks - - // use the same counter for both from and to IPs - if (_throttle.shouldThrottle(testIP)) { - if (_log.shouldLog(Log.WARN)) - _log.warn("PeerTest throttle to " + Addresses.toString(testIP, testPort)); - return; - } - if (msg >= 1 && msg <= 4) { if (fromPeer == null) { if (_log.shouldWarn()) @@ -1070,6 +1057,14 @@ class PeerTestManager { _transport.send(packet); return; } + if (_throttle.shouldThrottle(fromIP)) { + if (_log.shouldLog(Log.WARN)) + _log.warn("PeerTest throttle from " + Addresses.toString(fromIP, fromPort)); + UDPPacket packet = _packetBuilder2.buildPeerTestToAlice(SSU2Util.TEST_REJECT_BOB_LIMIT, + Hash.FAKE_HASH, data, fromPeer); + _transport.send(packet); + return; + } Hash alice = fromPeer.getRemotePeer(); RouterInfo aliceRI = _context.netDb().lookupRouterInfoLocally(alice); if (aliceRI == null) { @@ -1157,6 +1152,9 @@ class PeerTestManager { !_transport.isValid(testIP) || _transport.isTooClose(testIP)) { rcode = SSU2Util.TEST_REJECT_CHARLIE_ADDRESS; + } else if (_throttle.shouldThrottle(fromIP) || + _throttle.shouldThrottle(testIP)) { + rcode = SSU2Util.TEST_REJECT_CHARLIE_LIMIT; } else { // bob should have sent it to us. Don't bother to lookup // remotely if he didn't, or it was out-of-order or lost.