diff --git a/router/java/src/net/i2p/data/i2np/DatabaseLookupMessage.java b/router/java/src/net/i2p/data/i2np/DatabaseLookupMessage.java
index 413e61a1339c22e77c010c1c656eb299d9c0dd5c..ef133abb0d3e54abb2d44772c11cab4a2b4dea2b 100644
--- a/router/java/src/net/i2p/data/i2np/DatabaseLookupMessage.java
+++ b/router/java/src/net/i2p/data/i2np/DatabaseLookupMessage.java
@@ -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);
diff --git a/router/java/src/net/i2p/router/RouterContext.java b/router/java/src/net/i2p/router/RouterContext.java
index 9c0b8a30deedfecb47f765508e7d0c5b76f6774c..cdd05a3d2013c6408b9209abcb6873c6d7ec493b 100644
--- a/router/java/src/net/i2p/router/RouterContext.java
+++ b/router/java/src/net/i2p/router/RouterContext.java
@@ -94,7 +94,8 @@ public class RouterContext extends I2PAppContext {
         _statPublisher = new StatisticsManager(this);
         _shitlist = new Shitlist(this);
         _messageValidator = new MessageValidator(this);
-        _throttle = new RouterThrottleImpl(this);
+        //_throttle = new RouterThrottleImpl(this);
+        _throttle = new RouterDoSThrottle(this);
         _isFailingCalc = new IsFailingCalculator(this);
         _integrationCalc = new IntegrationCalculator(this);
         _speedCalc = new SpeedCalculator(this);
diff --git a/router/java/src/net/i2p/router/RouterDoSThrottle.java b/router/java/src/net/i2p/router/RouterDoSThrottle.java
new file mode 100644
index 0000000000000000000000000000000000000000..f4919987b218af11f0ce1e262f0f3dfe60327205
--- /dev/null
+++ b/router/java/src/net/i2p/router/RouterDoSThrottle.java
@@ -0,0 +1,57 @@
+package net.i2p.router;
+
+import net.i2p.data.Hash;
+import net.i2p.data.i2np.TunnelCreateMessage;
+import net.i2p.stat.Rate;
+import net.i2p.stat.RateStat;
+import net.i2p.util.Log;
+
+/**
+ * Minor extention of the router throttle to handle some DoS events and 
+ * throttle accordingly.
+ *
+ */
+class RouterDoSThrottle extends RouterThrottleImpl {
+    public RouterDoSThrottle(RouterContext context) {
+        super(context);
+        context.statManager().createRateStat("router.throttleNetDbDoS", "How many netDb lookup messages have we received so far during a period with a DoS detected", "Throttle", new long[] { 60*1000, 10*60*1000, 60*60*1000, 24*60*60*1000 });
+    }
+    
+    private volatile long _currentLookupPeriod;
+    private volatile int _currentLookupCount;
+    // if we receive over 20 netDb lookups in 10 seconds, someone is acting up
+    private static final long LOOKUP_THROTTLE_PERIOD = 10*1000;
+    private static final long LOOKUP_THROTTLE_MAX = 20;
+    
+    public boolean acceptNetDbLookupRequest(Hash key) { 
+        // if we were going to refuse it anyway, drop it
+        boolean shouldAccept = super.acceptNetDbLookupRequest(key);
+        if (!shouldAccept) return false;
+        
+        // now lets check for DoS
+        long now = getContext().clock().now();
+        if (_currentLookupPeriod + LOOKUP_THROTTLE_PERIOD > now) {
+            // same period, check for DoS
+            _currentLookupCount++;
+            if (_currentLookupCount >= LOOKUP_THROTTLE_MAX) {
+                getContext().statManager().addRateData("router.throttleNetDbDoS", _currentLookupCount, 0);
+                int rand = getContext().random().nextInt(_currentLookupCount);
+                if (rand > LOOKUP_THROTTLE_MAX) {
+                    return false;
+                } else {
+                    return true;
+                }
+            } else {
+                // no DoS, at least, not yet
+                return true;
+            }
+        } else {
+            // on to the next period, reset counter, no DoS
+            // (no, I'm not worried about concurrency here)
+            _currentLookupPeriod = now;
+            _currentLookupCount = 1;
+            return true;
+        }
+    }
+
+}
diff --git a/router/java/src/net/i2p/router/RouterThrottleImpl.java b/router/java/src/net/i2p/router/RouterThrottleImpl.java
index f5a8813a9d077f0003aeb5b3e49a77c62263578e..9bcbeda27bb570aef8e61e7fde1e2df97eaca037 100644
--- a/router/java/src/net/i2p/router/RouterThrottleImpl.java
+++ b/router/java/src/net/i2p/router/RouterThrottleImpl.java
@@ -129,4 +129,6 @@ class RouterThrottleImpl implements RouterThrottle {
                        + " tunnels with lag of " + lag + " and " + throttleEvents + " throttle events)");
         return true;
     }
+    
+    protected RouterContext getContext() { return _context; }
 }
diff --git a/router/java/src/net/i2p/router/StatisticsManager.java b/router/java/src/net/i2p/router/StatisticsManager.java
index eff93f7a004f0188f86cd4ae2cb5a60408d757aa..f7bd91169ca584deeb008d566a9cedcb195d2e63 100644
--- a/router/java/src/net/i2p/router/StatisticsManager.java
+++ b/router/java/src/net/i2p/router/StatisticsManager.java
@@ -125,7 +125,10 @@ public class StatisticsManager implements Service {
             includeRate("netDb.storeSent", stats, new long[] { 5*60*1000, 60*60*1000 });
             includeRate("netDb.successPeers", stats, new long[] { 60*60*1000 });
             includeRate("netDb.failedPeers", stats, new long[] { 60*60*1000 });
-            includeRate("netDb.searchCount", stats, new long[] { 3*60*60*1000});
+            includeRate("router.throttleNetDbDoSSend", stats, new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
+            includeRate("router.throttleNetDbDoS", stats, new long[] { 10*60*1000, 60*60*1000 });
+            //includeRate("netDb.searchCount", stats, new long[] { 3*60*60*1000});
+            //includeRate("netDb.searchMessageCount", stats, new long[] { 5*60*1000, 10*60*1000, 60*60*1000 });
             //includeRate("inNetMessage.timeToDiscard", stats, new long[] { 5*60*1000, 10*60*1000, 60*60*1000 });
             //includeRate("outNetMessage.timeToDiscard", stats, new long[] { 5*60*1000, 10*60*1000, 60*60*1000 });
             includeRate("router.throttleNetworkCause", stats, new long[] { 10*60*1000, 60*60*1000 });