From 9e2bb1ad0ad106f1783884fbe85d617d70fde314 Mon Sep 17 00:00:00 2001 From: zzz <zzz@i2pmail.org> Date: Wed, 8 Feb 2023 08:25:09 -0500 Subject: [PATCH] Transports: Check RI in handshake for matching IP --- .../transport/ntcp/InboundEstablishState.java | 31 +++++++++++++++++-- .../transport/udp/InboundEstablishState2.java | 22 +++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) 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 9f608f5901..6f41a5daea 100644 --- a/router/java/src/net/i2p/router/transport/ntcp/InboundEstablishState.java +++ b/router/java/src/net/i2p/router/transport/ntcp/InboundEstablishState.java @@ -629,15 +629,32 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa throw new DataFormatException("no NTCP in RI: " + ri); } String s = null; + String mismatchMessage = null; + byte[] realIP = _con.getRemoteIP(); for (RouterAddress addr : addrs) { String v = addr.getOption("v"); if (v == null || (!v.equals(NTCPTransport.NTCP2_VERSION) && !v.startsWith(NTCPTransport.NTCP2_VERSION_ALT))) { continue; } - s = addr.getOption("s"); - if (s != null) - break; + if (s == null) + s = addr.getOption("s"); + if (realIP != null) { + byte[] infoIP = addr.getIP(); + if (infoIP != null && infoIP.length == realIP.length) { + if (infoIP.length == 16) { + if ((((int) infoIP[0]) & 0xfe) == 0x02) + continue; // ygg + if (DataHelper.eq(realIP, 0, infoIP, 0, 8)) + continue; + } else { + if (DataHelper.eq(realIP, infoIP)) + continue; + } + // We will ban and throw below after checking s + mismatchMessage = "IP mismatch actual IP " + Addresses.toString(realIP) + " in RI: "; + } + } } if (s == null) { _msg3p2FailReason = NTCPConnection.REASON_S_MISMATCH; @@ -661,6 +678,14 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa boolean ok = verifyInbound(h); if (!ok) throw new DataFormatException("NTCP2 verifyInbound() fail"); + + // s is verified, we may now ban the hash + if (mismatchMessage != null) { + _context.banlist().banlistRouter(h, "IP mismatch", null, null, _context.clock().now() + 2*60*60*1000); + _msg3p2FailReason = NTCPConnection.REASON_BANNED; + throw new DataFormatException(mismatchMessage + ri); + } + try { RouterInfo old = _context.netDb().store(h, ri); if (flood && !ri.equals(old)) { diff --git a/router/java/src/net/i2p/router/transport/udp/InboundEstablishState2.java b/router/java/src/net/i2p/router/transport/udp/InboundEstablishState2.java index c4f8df7e6d..2630be8597 100644 --- a/router/java/src/net/i2p/router/transport/udp/InboundEstablishState2.java +++ b/router/java/src/net/i2p/router/transport/udp/InboundEstablishState2.java @@ -248,6 +248,7 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa boolean isIPv6 = _aliceIP.length == 16; List<RouterAddress> addrs = _transport.getTargetAddresses(ri); RouterAddress ra = null; + String mismatchMessage = null; for (RouterAddress addr : addrs) { // skip SSU 1 address w/o "s" if (addrs.size() > 1 && addr.getTransportStyle().equals("SSU") && addr.getOption("s") == null) @@ -266,6 +267,20 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa continue; } ra = addr; + byte[] infoIP = ra.getIP(); + if (infoIP != null && infoIP.length == _aliceIP.length) { + if (isIPv6) { + if ((((int) infoIP[0]) & 0xfe) == 0x02) + continue; // ygg + if (DataHelper.eq(_aliceIP, 0, infoIP, 0, 8)) + continue; + } else { + if (DataHelper.eq(_aliceIP, infoIP)) + continue; + } + // We will ban and throw below after checking signature + mismatchMessage = "IP mismatch actual IP " + Addresses.toString(_aliceIP) + " in RI: "; + } break; } @@ -312,6 +327,13 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa throw new RIException("SSU2 network ID mismatch", REASON_NETID); } + if (mismatchMessage != null) { + _context.banlist().banlistRouter(h, "IP mismatch", null, null, _context.clock().now() + 2*60*60*1000); + if (ri.verifySignature()) + _context.blocklist().add(_aliceIP); + throw new RIException(mismatchMessage + ri, REASON_BANNED); + } + if (!"2".equals(ra.getOption("v"))) throw new RIException("bad SSU2 v", REASON_VERSION); -- GitLab