forked from I2P_Developers/i2p.i2p
* track searches more carefully
* detect situations where we may be inadvertantly flooding the netDb and log them as CRIT with a stacktrace, as well as publish the count of those events in the netDb * detect potential netDb DoS situations by checking to see if we have received more than 20 netDb lookups in 10 seconds, and if so, probabalistically drop subsequent netDb messages (P=1-(10/numReceived)). This is also published in the netDb.
This commit is contained in:
@ -36,11 +36,41 @@ public class DatabaseLookupMessage extends I2NPMessageImpl {
|
||||
private TunnelId _replyTunnel;
|
||||
private Set _dontIncludePeers;
|
||||
|
||||
private static volatile long _currentLookupPeriod;
|
||||
private static volatile int _currentLookupCount;
|
||||
// if we try to send over 20 netDb lookups in 10 seconds, we're acting up
|
||||
private static final long LOOKUP_THROTTLE_PERIOD = 10*1000;
|
||||
private static final long LOOKUP_THROTTLE_MAX = 20;
|
||||
|
||||
public DatabaseLookupMessage(I2PAppContext context) {
|
||||
super(context);
|
||||
setSearchKey(null);
|
||||
setFrom(null);
|
||||
setDontIncludePeers(null);
|
||||
|
||||
context.statManager().createRateStat("router.throttleNetDbDoSSend", "How many netDb lookup messages we are sending during a period with a DoS detected", "Throttle", new long[] { 60*1000, 10*60*1000, 60*60*1000, 24*60*60*1000 });
|
||||
}
|
||||
|
||||
private static boolean detectDoS(I2PAppContext context) {
|
||||
// now lets check for DoS
|
||||
long now = context.clock().now();
|
||||
if (_currentLookupPeriod + LOOKUP_THROTTLE_PERIOD > now) {
|
||||
// same period, check for DoS
|
||||
_currentLookupCount++;
|
||||
if (_currentLookupCount >= LOOKUP_THROTTLE_MAX) {
|
||||
context.statManager().addRateData("router.throttleNetDbDoSSend", _currentLookupCount, 0);
|
||||
return true;
|
||||
} else {
|
||||
// no DoS, at least, not yet
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// on to the next period, reset counter, no DoS
|
||||
// (no, I'm not worried about concurrency here)
|
||||
_currentLookupPeriod = now;
|
||||
_currentLookupCount = 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,6 +140,15 @@ public class DatabaseLookupMessage extends I2NPMessageImpl {
|
||||
if (_key == null) throw new I2NPMessageException("Key being searched for not specified");
|
||||
if (_fromHash == null) throw new I2NPMessageException("From address not specified");
|
||||
|
||||
// we do this in the writeMessage so we know that we have all the data
|
||||
boolean isDoS = detectDoS(_context);
|
||||
if (isDoS) {
|
||||
_log.log(Log.CRIT, "Are we flooding the network with NetDb lookup messages for "
|
||||
+ _key.toBase64() + " (reply through " + _fromHash + " / " + _replyTunnel + ")",
|
||||
new Exception("Flood cause"));
|
||||
}
|
||||
|
||||
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream(32);
|
||||
try {
|
||||
_key.writeBytes(os);
|
||||
|
Reference in New Issue
Block a user