Opened 7 months ago

Last modified 7 months ago

#2275 open enhancement

I2PSnark/DHT: Increase blacklist timeout to 3 hours.

Reported by: obscuratus Owned by: zzz
Priority: minor Milestone: undecided
Component: apps/i2psnark Version: 0.9.34
Keywords: DHT, blacklist Cc:
Parent Tickets:

Description

Preamble: I don't want to over-dramatize this bug report as impuning the current implementation of DHT peer searching. DHT is cleverly designed to be robust and resilient to the issue described in this bug report, but DHT should work somewhat better if this change is implemented.

Increase the timeout period for removing blacklisted DHT peers from 17 minutes to 3 hours.

I2PSnark doesn't validate every peer in its DHT peer list, but as I2PSnark runs into peers that don't respond, they're added to the blacklist.

Also, I2PSnark is constantly sharing lists of known DHT peers with other clients.

DHT peers are held for a minimum of 3 hours (unless purged from an over-full DHT peer list). But dead peers are dropped from the blacklist after 17 minutes.

And a DHT peer's timeout period is refreshed if another peer shares that peer with you as being one of its known peers.

The aspiration is that dead peers who leave the network will be dropped from the DHT table after three hours. But, on my testing network, I can see dead peers hanging around on the DHT peer list for a long time, sometimes days. This is because I2PSnark is only validating a small portion of peers, but is constantly sharing un-validated peers with other clients.

(Note: By using the term "validation", I refer to the practice of of adding a peer to the blacklist if they don't respond to two consecutive attempts at contact.)

The DHT table does eventually clean itself up, but I would estimate that dead peers hang around with a half-life of approximately 8-16 hours instead of the desired 3 hours.

When some clients correctly identify a dead peer, and blacklist that peer, other clients will hold this dead peer on their DHT peer list because they are not looking directly at this peer to validate it.

After I2PSnark drops a dead-blacklisted peer from its DHT list after 17 minutes, other clients will add it right back.

There's too much churn of peers to presume that this change will "clean-up" all the zombie peers. But this will slightly help the efficiency of DHT queries by reducing the amount of time re-identifying zombie peers on your DHT peer list. You'll only need to re-identify dead peers every three hours instead of every 17 minutes.

I've implemented this change on my local version of I2PSnark, and I see my blacklist size has increased from typically 1-2 entries to 10-30 entries. These blacklisted entries probably don't represent every "dead" DHT peer in my table, but it does probably represent the DHT peers who are "close" to the items I am looking for, so it should improve the efficiency of my DHT searches.

From: obscuratus <obscuratus@mail.i2p>
Date: Thu, 7 Jun 2018 11:44:05 -0500
Subject: i2psnark/KRPC: Blacklist Enhancements

Increase the timeout for blacklist cleanup to 3 hours and establish
a maximum blacklist size.

Rationale:
The DHT table can acquire semi-persistant zombie peers from peers who
have left the network, but whose ID remains persistant as it is passed
around and refreshed long after the peer is gone.

This modification mitigates (but doesn't solve) the issue by setting
the blacklist timeout to 3 hours.  This is reasonable since the
timeout for peers in the table is also three hours.  Other peers
in the network will hold zombie peers in their table as long as there's
no need to specifically test that peer.

Signed-off-by: obscuratus <obscuratus@mail.i2p>
---
 apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java b/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java
index 16e20c793..ff3f7f27f 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java
@@ -154,11 +154,12 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
     private static final long DEFAULT_QUERY_TIMEOUT = 75*1000;
     private static final long DEST_LOOKUP_TIMEOUT = 10*1000;
     /** stagger with other cleaners */
     private static final long CLEAN_TIME = 63*1000;
     private static final long EXPLORE_TIME = 877*1000;
-    private static final long BLACKLIST_CLEAN_TIME = 17*60*1000;
+    private static final long BLACKLIST_CLEAN_TIME = 3*60*60*1000;
+    private static final int BLACKLIST_MAX_PEERS = 500;
     private static final long NODES_SAVE_TIME = 3*60*60*1000;
     public static final String DHT_FILE_SUFFIX = ".dht.dat";
 
     private static final int SEND_CRYPTO_TAGS = 8;
     private static final int LOW_CRYPTO_TAGS = 4;
@@ -1230,15 +1231,21 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
             if (_knownNodes.remove(nid) != null) {
                 if (_log.shouldLog(Log.INFO))
                     _log.info("Removed after consecutive timeouts: " + nInfo);
             }
             if (!_blacklist.contains(nid)) {
-                // used as when-added time
-                nid.setLastSeen();
-                _blacklist.add(nid);
-                if (_log.shouldLog(Log.INFO))
-                    _log.info("Blacklisted: " + nid);
+                if (_blacklist.size() > BLACKLIST_MAX_PEERS) {
+                    if (_log.shouldLog(Log.WARN))
+                        _log.warn("Blacklist Saturated: " + _blacklist.size() + " entries.");
+                        _log.warn("Possible rogue peer or misconfigured client spewing zombie DHT peers.");
+                } else {
+                    // used as when-added time
+                    nid.setLastSeen();
+                    _blacklist.add(nid);
+                    if (_log.shouldLog(Log.INFO))
+                        _log.info("Blacklisted: " + nid);
+                }
             }
         }
     }
 
     /**
-- 
2.16.4

Subtickets (add)

Change History (1)

comment:1 Changed 7 months ago by zzz

  • Status changed from new to open

May need to discuss this with BiglyBT. They have long timeouts for keeping DHT peers around and BiglyBT behavior basically dictates how it all works, as I suspect they make up a majority of the DHT peers.

DHT is by nature messy and lossy and inefficient. Not sure your "clean up" goals are even possible. But will investigate. Most of the parameters haven't been reconsidered since support was initially added.

Note: See TracTickets for help on using tickets.