diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java
index 8962b3635c91540dd9ee4f53782464fe3235a52e..d6f0bb79034a8271e0b88c98d8d6051cf6c1ac34 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java
@@ -920,7 +920,7 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
             return "Invalid routerInfo signature";
         }
         if (routerInfo.getNetworkId() != _networkID){
-            _context.banlist().banlistRouter(key, "Not in our network");
+            _context.banlist().banlistRouterForever(key, "Not in our network: " + routerInfo.getNetworkId());
             if (_log.shouldLog(Log.WARN))
                 _log.warn("Bad network: " + routerInfo);
             return "Not in our network";
diff --git a/router/java/src/net/i2p/router/transport/ntcp/InboundEstablishState.java b/router/java/src/net/i2p/router/transport/ntcp/InboundEstablishState.java
index 38066761e043bec05ea07ca12e5a636b39e6131a..c718de552c5847307aa51d228fb6bf161c543200 100644
--- a/router/java/src/net/i2p/router/transport/ntcp/InboundEstablishState.java
+++ b/router/java/src/net/i2p/router/transport/ntcp/InboundEstablishState.java
@@ -572,6 +572,38 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa
         return true;
     }
 
+    /**
+     *  Validate network ID, NTCP 2 only.
+     *  Call after receiving Alice's RouterInfo,
+     *  but before storing it in the netdb.
+     *
+     *  Side effects: When returning false, sets _msg3p2FailReason,
+     *  banlists permanently and blocklists
+     *
+     *  @return success
+     *  @since 0.9.38
+     */
+    private boolean verifyInboundNetworkID(RouterInfo alice) {
+        int aliceID = alice.getNetworkId();
+        boolean rv = aliceID == _context.router().getNetworkID();
+        if (!rv) {
+            Hash aliceHash = alice.getHash();
+            if (_log.shouldLog(Log.WARN))
+                _log.warn("Dropping inbound connection from wrong network: " + aliceID + ' ' + aliceHash);
+            // So next time we will not accept the con from this IP,
+            // rather than doing the whole handshake
+            InetAddress addr = _con.getChannel().socket().getInetAddress();
+            if (addr != null) {
+                byte[] ip = addr.getAddress();
+                _context.blocklist().add(ip);
+            }
+            _context.banlist().banlistRouterForever(aliceHash, "Not in our network: " + aliceID);
+            _transport.markUnreachable(aliceHash);
+            _msg3p2FailReason = NTCPConnection.REASON_BANNED;
+        }
+        return rv;
+    }
+
     /**
      *  We are Bob. Send message #4 to Alice.
      *
@@ -988,6 +1020,9 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa
         boolean ok = verifyInbound(h);
         if (!ok)
             throw new DataFormatException("NTCP2 verifyInbound() fail");
+        ok = verifyInboundNetworkID(ri);
+        if (!ok)
+            throw new DataFormatException("NTCP2 network ID mismatch");
         try {
             RouterInfo old = _context.netDb().store(h, ri);
             if (flood && !ri.equals(old)) {
diff --git a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java
index e05a935a69f4e28b0aea2a89c8c34a6e4dc8a6a4..321b250cb466b878984229f54e15b48b49f3ffa4 100644
--- a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java
+++ b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java
@@ -81,6 +81,7 @@ public class NTCPTransport extends TransportImpl {
     private int _ssuPort;
     /** synch on this */
     private final Set<InetSocketAddress> _endpoints;
+    private final int _networkID;
 
     /**
      * list of NTCPConnection of connections not yet established that we
@@ -229,6 +230,7 @@ public class NTCPTransport extends TransportImpl {
         _reader = new Reader(ctx);
         _writer = new net.i2p.router.transport.ntcp.Writer(ctx);
 
+        _networkID = ctx.router().getNetworkID();
         _fastBid = new SharedBid(25); // best
         _slowBid = new SharedBid(70); // better than ssu unestablished, but not better than ssu established
         _slowCostBid = new SharedBid(85);
@@ -504,6 +506,11 @@ public class NTCPTransport extends TransportImpl {
             }
             return _fastBid;
         }
+        if (toAddress.getNetworkId() != _networkID) {
+            _context.banlist().banlistRouterForever(peer, "Not in our network: " + toAddress.getNetworkId());
+            markUnreachable(peer);
+            return null;    
+        }
         if (dataSize > NTCPConnection.NTCP1_MAX_MSG_SIZE) {
             // Not established, too big for NTCP 1, let SSU deal with it
             // TODO look at his addresses to see if NTCP2 supported?
diff --git a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
index 9d5c91207925cdb0468a813de1481be74aae87cd..645d2f8096dc8988c652b8e3ce0823831f4a3b76 100644
--- a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
+++ b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
@@ -252,7 +252,7 @@ class EstablishmentManager {
         RouterIdentity toIdentity = toRouterInfo.getIdentity();
         Hash toHash = toIdentity.calculateHash();
         if (toRouterInfo.getNetworkId() != _networkID) {
-            _context.banlist().banlistRouter(toHash);
+            _context.banlist().banlistRouterForever(toHash, "Not in our network: " + toRouterInfo.getNetworkId());
             _transport.markUnreachable(toHash);
             _transport.failed(msg, "Remote peer is on the wrong network, cannot establish");
             return;
diff --git a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
index 4071879422a1ad1cba999009945a930c08d1fb7b..5b0a680661d37ed862b31ce7bf7279bd54c284fe 100644
--- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
+++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
@@ -1416,7 +1416,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
                     _context.simpleTimer2().addEvent(new RemoveDropList(remote), DROPLIST_PERIOD);
                 }
                 markUnreachable(peerHash);
-                _context.banlist().banlistRouter(peerHash, "Part of the wrong network, version = " + ((RouterInfo) entry).getVersion());
+                _context.banlist().banlistRouterForever(peerHash, "Not in our network: " + ((RouterInfo) entry).getNetworkId());
                 //_context.banlist().banlistRouter(peerHash, "Part of the wrong network", STYLE);
                 if (peer != null)
                     sendDestroy(peer);
@@ -1754,6 +1754,12 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
             else
                 return _cachedBid[FAST_BID];
         } else {
+            if (toAddress.getNetworkId() != _networkID) {
+                _context.banlist().banlistRouterForever(to, "Not in our network: " + toAddress.getNetworkId());
+                markUnreachable(to);
+                return null;    
+            }
+
             // If we don't have a port, all is lost
             if ( _reachabilityStatus == Status.HOSED) {
                 markUnreachable(to);
@@ -1880,15 +1886,16 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
     @Override
     public void send(OutNetMessage msg) { 
         if (msg == null) return;
-        if (msg.getTarget() == null) return;
-        if (msg.getTarget().getIdentity() == null) return;
+        RouterInfo tori = msg.getTarget();
+        if (tori == null) return;
+        if (tori.getIdentity() == null) return;
         if (_establisher == null) {
             failed(msg, "UDP not up yet");
             return;    
         }
 
         msg.timestamp("sending on UDP transport");
-        Hash to = msg.getTarget().getIdentity().calculateHash();
+        Hash to = tori.getIdentity().calculateHash();
         PeerState peer = getPeerState(to);
         if (_log.shouldLog(Log.DEBUG))
             _log.debug("Sending to " + (to != null ? to.toString() : ""));