Opened 4 weeks ago

Last modified 14 hours ago

#2759 open enhancement

Automatic blacklisting of routers in same country for routers in hostile countries

Reported by: Reportage Owned by: zzz
Priority: minor Milestone: undecided
Component: router/transport Version: 0.9.46
Keywords: netdb, blocklisting, hostile countries Cc:
Parent Tickets: Sensitive: no

Description

To complement automatic hidden mode for routers in potentially hostile countries, additionally automatically blocklisting routers in the same country and principalities might be considered. This would make it harder for hostile routers in hostile countries to enumerate routers running in hidden mode, where the act of running a router might itself invite negative consequences including arrest, detention, confiscation of hardware etc.

As an example, given recent developments in Hong Kong, it's not inconceivable that activists running I2P might attract the attention of the Chinese govt, so grouping China, Hong Kong, Macau and related Chinese-governed territories and blocklisting all routers in these countries on other routers running in the same group may afford some protection to users in these countries.

Additionally, this feature might be used to implement something similar to Tor's excludeExitNodes directive, where specific country codes can be specified to automatically blocklist/prevent local tunnel builds with routers in a given country.

Subtickets

Change History (8)

comment:1 Changed 4 weeks ago by zzz

Component: router/netdbrouter/transport
Status: newopen

It's worth thinking about.

If the threat model is enumeration, then we want to prevent direct connection to other routers in the same country. That would ideally be done with IP blocks (blocklist). Router hash blocking (banlist) is not sufficient.

Also, delayed blocking (where we have a RI and try to connect to them, possibly before doing a geoip lookup) is too late.

Incoming connections for the most part won't happen if we're in hidden mode.

Using them for SSU peer testing or introductions would also need to be prevented.

Building tunnels through other routers in the same country should be OK, if they aren't the closest hop, but if the router gets banlisted and blocklisted it won't be anyway.

So, ideally, at startup, we'd go through the entire geoip database, get all the IP ranges for a given country, and blocklist all of those IP ranges.

The trouble is that we support three geoip database formats with three different APIs. None of those APIs support a "give me all IP ranges for country xx" call. So it's not easy and would take further research. We'd need three implementations of the new API call. I'm not sure anything less than this is worth doing.

The final suggestion, to block additional related countries, is a further complication that would be tackled after the above, if deemed necessary.

There's also an implicit suggestion in the OP (explicitly stated in IRC) that HK be added to our strict countries list. I reviewed the lastest Freedom in the World report and some recent news articles. Based on that research, I don't think it is yet indicated, but it's a fast-changing situation and we'll keep monitoring it. Obviously if HK starts getting routed through GFW then we'll reevaluate.

Comments from others welcome.

comment:2 Changed 4 weeks ago by zzz

A different threat model would be getting "trapped" behind the GFW, where out-of-country connections are blocked, so your entire netdb view would get collapsed to in-country routers only. If a portion of those routers were colluding, they could deanonymize your traffic. Preventing in-country routers from being in your tunnels would stop this attack, but also cause I2P to stop working altogether. Although it probably wasn't working very well to begin with.

comment:3 Changed 4 weeks ago by zzz

As a quick test I wrote a program to brute force query all /24s from 1.0.0.0 to 223.255.255.0 in the geoip2 database and it took 67 seconds to run, which is unacceptable. That's 14.6 million queries. The database reports it has 892K entries (nodes). So presumably we could speed it up 16x if we figured out how to efficiently walk the nodes. The geoip2 format is documented here: https://github.com/maxmind/MaxMind-DB/blob/master/MaxMind-DB-spec.md

I did also look at the data, it does vary on at least a /24 basis, so any shorter prefix would not work.

comment:4 in reply to:  2 Changed 12 days ago by idk

Replying to zzz:

A different threat model would be getting "trapped" behind the GFW, where out-of-country connections are blocked, so your entire netdb view would get collapsed to in-country routers only. If a portion of those routers were colluding, they could deanonymize your traffic. Preventing in-country routers from being in your tunnels would stop this attack, but also cause I2P to stop working altogether. Although it probably wasn't working very well to begin with.

Is there a realistic scenario where routers affected by such trapping would also not be at serious risk of attack from colluding in-country routers? The desirable behavior might be different for different groups within I2P in such a country, and people who regard themselves as conducting high-risk communications may wish to "fail closed" and not make those in-country connections. OTOH, somebody who is participating in just like, conventional file-sharing might not care much.

Edit: I suppose that switching from allowing in-country connections to not in a trapped scenario would be a dead giveaway that the user considers their previous activity to be high-risk, though.

Last edited 12 days ago by idk (previous) (diff)

comment:5 Changed 12 days ago by Reportage

In order to increase transparency when automatic blocking of country codes is active, and to enable users to override the configuration manually, a configuration option along the lines of router.excludeCountryCodes={cn,hk} could be available, with some indication in the console that it's active for routers that fall into the automatic same-country router blocking category.

This feature could be combined with per-cc blocklists that are either shipped with updates when the geoip db changes, or manually calculated from the active geoip db at router startup before netdb initialization.

Regarding threat models, enumeration appears to be the primary risk. In countries in the strict list with a modest amount of routers, enumerating every non-firewalled router would be trivial for a state-level actor. In this context, it might further be considered to place all routers in forced firewall mode to further prevent enumeration.

As for routers in a country where all non-country routers are inaccessible, it may be preferable to prevent the router operating at all, as the operating environment must be considered hostile in this context.

comment:6 Changed 12 days ago by zzz

@idk in practice these countries have few if any floodfills or peers for tunnels, due to the hidden-by-default implementation of java i2p, so there's all sorts of anonymity issues if you're "trapped".

comment:7 Changed 10 days ago by zzz

A while back I did write some code that would block everybody in your country on first run of the geoip lookup. If the first threat model above is correct (one connection and you're done) this wouldn't be sufficient, because we do delayed lookups as explained in comment 1.

Posting here anyway for comment. Unfinished, untested. It also pushes the inner class to an inner-inner class, can't remember why I did that and probably pointless.

#
# old_revision [1dfacc4adbaff4f5fdab92c302abd6ef642f3668]
#
# patch "router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java"
#  from [1b0a6a57129fb96d11ca9033599b186dc1e6da41]
#    to [80950f88bbdc5a2aec7bca061a589f283d5f9c9c]
#
============================================================
--- router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java	1b0a6a57129fb96d11ca9033599b186dc1e6da41
+++ router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java	80950f88bbdc5a2aec7bca061a589f283d5f9c9c
@@ -423,27 +423,42 @@ public class CommSystemFacadeImpl extend
     }
 
     private class Lookup implements SimpleTimer.TimedEvent {
+        private volatile boolean countryChecked;
+
         public void timeReached() {
             (new LookupThread()).start();
         }
-    }
 
-    /**
-     *  This takes too long to run on the SimpleTimer2 queue
-     *  @since 0.9.10
-     */
-    private class LookupThread extends I2PThread {
+        /**
+         *  This takes too long to run on the SimpleTimer2 queue
+         *  @since 0.9.10
+         */
+        private class LookupThread extends I2PThread {
 
-        public LookupThread() {
-            super("GeoIP Lookup");
-            setDaemon(true);
-        }
+            public LookupThread() {
+                super("GeoIP Lookup");
+                setDaemon(true);
+            }
 
-        public void run() {
-            long start = System.currentTimeMillis();
-            _geoIP.blockingLookup();
-            if (_log.shouldLog(Log.INFO))
-                _log.info("GeoIP lookup took " + (System.currentTimeMillis() - start));
+            public void run() {
+                long start = System.currentTimeMillis();
+                String oldCountry = getOurCountry();
+                _geoIP.blockingLookup();
+                String newCountry = getOurCountry();
+                if (newCountry != null && (!countryChecked || !newCountry.equals(oldCountry))) {
+                    countryChecked = true;
+                    if (isInStrictCountry()) {
+                        for (Hash h : _context.netDb().getAllRouters()) {
+                            String hisCountry = getCountry(h);
+                            if (newCountry.equals(hisCountry)) {
+                                _context.banlist().banlistRouterForever(h, "In our country");
+                            }
+                        }
+                    }
+                }
+                if (_log.shouldLog(Log.INFO))
+                    _log.info("GeoIP lookup took " + (System.currentTimeMillis() - start));
+            }
         }
     }
 

comment:8 Changed 14 hours ago by Reportage

Instead of pulling the ip blocks from the geoip dbs, another solution may be to use a service that provides frequently updated country ip blocks for both ipv4 and ipv6: https://www.ipdeny.com/ipblocks/

Note: See TracTickets for help on using tickets.