From 9b0ace19c1c8d3009f0a468cde339fe3d305c33a Mon Sep 17 00:00:00 2001 From: zzz <zzz@i2pmail.org> Date: Thu, 15 Dec 2022 14:57:20 -0500 Subject: [PATCH] Router: Change transient IPv4 blocklist to LHMCache Reduce transient blocklist sizes if slow Improve logging of block source --- router/java/src/net/i2p/router/Blocklist.java | 76 +++++++++++++++---- .../src/net/i2p/router/sybil/Analysis.java | 3 +- .../net/i2p/router/sybil/PersistSybil.java | 13 +++- 3 files changed, 75 insertions(+), 17 deletions(-) diff --git a/router/java/src/net/i2p/router/Blocklist.java b/router/java/src/net/i2p/router/Blocklist.java index 072d54762a..f9f46065b3 100644 --- a/router/java/src/net/i2p/router/Blocklist.java +++ b/router/java/src/net/i2p/router/Blocklist.java @@ -39,6 +39,7 @@ import net.i2p.util.ConcurrentHashSet; import net.i2p.util.LHMCache; import net.i2p.util.Log; import net.i2p.util.SimpleTimer2; +import net.i2p.util.SystemVersion; import net.i2p.util.Translate; /** @@ -100,10 +101,10 @@ public class Blocklist { * Note that it's impossible to prevent clogging up * the tables by a determined attacker, esp. on IPv6 */ - private static final int MAX_IPV4_SINGLES = 8192; - private static final int MAX_IPV6_SINGLES = 4096; + private static final int MAX_IPV4_SINGLES = SystemVersion.isSlow() ? 512 : 8192; + private static final int MAX_IPV6_SINGLES = SystemVersion.isSlow() ? 256 : 4096; - private final Set<Integer> _singleIPBlocklist = new ConcurrentHashSet<Integer>(4); + private final Map<Integer, Object> _singleIPBlocklist = new LHMCache<Integer, Object>(MAX_IPV4_SINGLES); private final Map<BigInteger, Object> _singleIPv6Blocklist = new LHMCache<BigInteger, Object>(MAX_IPV6_SINGLES); private static final Object DUMMY = Integer.valueOf(0); @@ -382,6 +383,7 @@ public class Blocklist { try { br = new BufferedReader(new InputStreamReader( new FileInputStream(blFile), "UTF-8")); + String source = blFile.toString(); String buf = null; while ((buf = br.readLine()) != null) { Entry e = parse(buf, true); @@ -398,7 +400,7 @@ public class Blocklist { if (ip1.length == 4) { if (isFeedFile) { // temporary - add(ip1); + add(ip1, source); feedcount++; } else { byte[] ip2 = e.ip2; @@ -407,7 +409,7 @@ public class Blocklist { } } else { // IPv6 - add(ip1); + add(ip1, source); } } } catch (IOException ioe) { @@ -666,7 +668,22 @@ public class Blocklist { public void add(String ip) { byte[] pib = Addresses.getIP(ip); if (pib == null) return; - add(pib); + add(pib, null); + } + + /** + * Maintain a simple in-memory single-IP blocklist + * This is used for new additions, NOT for the main list + * of IP ranges read in from the file. + * + * @param ip IPv4 or IPv6 + * @param source for logging only, may be null + * @since 0.9.57 + */ + public void add(String ip, String source) { + byte[] pib = Addresses.getIP(ip); + if (pib == null) return; + add(pib, source); } /** @@ -677,6 +694,19 @@ public class Blocklist { * @param ip IPv4 or IPv6 */ public void add(byte ip[]) { + add(ip, null); + } + + /** + * Maintain a simple in-memory single-IP blocklist + * This is used for new additions, NOT for the main list + * of IP ranges read in from the file. + * + * @param ip IPv4 or IPv6 + * @param source for logging only, may be null + * @since 0.9.57 + */ + public void add(byte ip[], String source) { boolean rv; if (ip.length == 4) rv = add(toInt(ip)); @@ -684,8 +714,13 @@ public class Blocklist { rv = add(new BigInteger(1, ip)); else rv = false; - if (rv && _log.shouldInfo()) - _log.info("Adding IP to blocklist: " + Addresses.toString(ip)); + if (rv) { + // lower log level at startup when initializing from blocklist files + if (source == null && _log.shouldWarn()) + _log.warn("Added: " + Addresses.toString(ip), new Exception("source")); + else if (_log.shouldDebug()) + _log.debug("Added: " + Addresses.toString(ip) + " source: " + source); + } } /** @@ -703,25 +738,36 @@ public class Blocklist { remove(new BigInteger(1, ip)); } + /** + * @return true if it was NOT previously on the list + */ private boolean add(int ip) { - if (_singleIPBlocklist.size() >= MAX_IPV4_SINGLES) - return false; - return _singleIPBlocklist.add(Integer.valueOf(ip)); + Integer iip = Integer.valueOf(ip); + synchronized(_singleIPBlocklist) { + return _singleIPBlocklist.put(iip, DUMMY) == null; + } } /** * @since 0.9.28 */ private void remove(int ip) { - _singleIPBlocklist.remove(Integer.valueOf(ip)); + Integer iip = Integer.valueOf(ip); + synchronized(_singleIPBlocklist) { + _singleIPBlocklist.remove(iip); + } } private boolean isOnSingleList(int ip) { - return _singleIPBlocklist.contains(Integer.valueOf(ip)); + Integer iip = Integer.valueOf(ip); + synchronized(_singleIPBlocklist) { + return _singleIPBlocklist.get(iip) != null; + } } /** * @param ip IPv6 non-negative + * @return true if it was NOT previously on the list * @since IPv6 */ private boolean add(BigInteger ip) { @@ -1152,7 +1198,9 @@ public class Blocklist { * @since 0.9.48 */ public List<Integer> getTransientIPv4Blocks() { - return new ArrayList<Integer>(_singleIPBlocklist); + synchronized(_singleIPBlocklist) { + return new ArrayList<Integer>(_singleIPBlocklist.keySet()); + } } /** diff --git a/router/java/src/net/i2p/router/sybil/Analysis.java b/router/java/src/net/i2p/router/sybil/Analysis.java index 6483617c68..5adb818d14 100644 --- a/router/java/src/net/i2p/router/sybil/Analysis.java +++ b/router/java/src/net/i2p/router/sybil/Analysis.java @@ -154,10 +154,11 @@ public class Analysis extends JobImpl implements RouterApp { return; Blocklist bl = _context.blocklist(); Banlist ban = _context.banlist(); + String source = _persister.getBlocklistFile().toString(); for (Map.Entry<String, Long> e : map.entrySet()) { String s = e.getKey(); if (s.contains(".") || s.contains(":")) { - bl.add(s); + bl.add(s, source); } else { byte[] b = Base64.decode(s); if (b != null && b.length == Hash.HASH_LENGTH) { diff --git a/router/java/src/net/i2p/router/sybil/PersistSybil.java b/router/java/src/net/i2p/router/sybil/PersistSybil.java index c5f1a8f970..18f919863c 100644 --- a/router/java/src/net/i2p/router/sybil/PersistSybil.java +++ b/router/java/src/net/i2p/router/sybil/PersistSybil.java @@ -238,6 +238,16 @@ public class PersistSybil { return file.delete(); } + /** + * Get the blocklist path + * + * @since 0.9.57 + */ + File getBlocklistFile() { + File f = new File(_context.getConfigDir(), SDIR); + return new File(f, BLOCKLIST_SYBIL_FILE); + } + /** * Read the blocklist * @@ -245,8 +255,7 @@ public class PersistSybil { * @since 0.9.50 */ Map<String, Long> readBlocklist() { - File f = new File(_context.getConfigDir(), SDIR); - f = new File(f, BLOCKLIST_SYBIL_FILE); + File f = getBlocklistFile(); Map<String, Long> rv = readBlocklist(f); if (rv != null) notifyVersion(f.lastModified()); -- GitLab