From 17c4038c6048a1567eba76b89a8a9e19d7e81d38 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 11 Jul 2023 13:16:35 -0400 Subject: [PATCH 01/23] select router with ipv4 for endpoint --- libi2pd/NetDb.cpp | 19 ++++++++++++------- libi2pd/NetDb.hpp | 4 ++-- libi2pd/Tunnel.cpp | 4 ++-- libi2pd/TunnelPool.cpp | 19 ++++++++----------- libi2pd/TunnelPool.h | 4 ++-- libi2pd_client/MatchedDestination.cpp | 3 ++- 6 files changed, 28 insertions(+), 25 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 5134dbe0..7bccb2a0 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -59,7 +59,7 @@ namespace data { Reseed (); } - else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo (), false)) + else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, false)) Reseed (); // we don't have a router we can connect to. Trying to reseed auto it = m_RouterInfos.find (i2p::context.GetIdentHash ()); @@ -1199,15 +1199,17 @@ namespace data }); } - std::shared_ptr NetDb::GetRandomRouter (std::shared_ptr compatibleWith, bool reverse) const + std::shared_ptr NetDb::GetRandomRouter (std::shared_ptr compatibleWith, + bool reverse, bool endpoint) const { return GetRandomRouter ( - [compatibleWith, reverse](std::shared_ptr router)->bool + [compatibleWith, reverse, endpoint](std::shared_ptr router)->bool { return !router->IsHidden () && router != compatibleWith && (reverse ? compatibleWith->IsReachableFrom (*router) : router->IsReachableFrom (*compatibleWith)) && - router->IsECIES () && !router->IsHighCongestion (false); + router->IsECIES () && !router->IsHighCongestion (false) && + (!endpoint || (router->IsV4 () && (!reverse || router->IsPublished (true)))); // endpoint must be ipv4 and published if inbound(reverse) }); } @@ -1231,17 +1233,20 @@ namespace data }); } - std::shared_ptr NetDb::GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith, bool reverse) const + std::shared_ptr NetDb::GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith, + bool reverse, bool endpoint) const { return GetRandomRouter ( - [compatibleWith, reverse](std::shared_ptr router)->bool + [compatibleWith, reverse, endpoint](std::shared_ptr router)->bool { return !router->IsHidden () && router != compatibleWith && (reverse ? compatibleWith->IsReachableFrom (*router) : router->IsReachableFrom (*compatibleWith)) && (router->GetCaps () & RouterInfo::eHighBandwidth) && router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION && - router->IsECIES () && !router->IsHighCongestion (true); + router->IsECIES () && !router->IsHighCongestion (true) && + (!endpoint || (router->IsV4 () && (!reverse || router->IsPublished (true)))); // endpoint must be ipv4 and published if inbound(reverse) + }); } diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index adfdcde7..b7d9a5b3 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -84,8 +84,8 @@ namespace data void HandleNTCP2RouterInfoMsg (std::shared_ptr m); std::shared_ptr GetRandomRouter () const; - std::shared_ptr GetRandomRouter (std::shared_ptr compatibleWith, bool reverse) const; - std::shared_ptr GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith, bool reverse) const; + std::shared_ptr GetRandomRouter (std::shared_ptr compatibleWith, bool reverse, bool endpoint) const; + std::shared_ptr GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith, bool reverse, bool endpoint) const; std::shared_ptr GetRandomSSU2PeerTestRouter (bool v4, const std::set& excluded) const; std::shared_ptr GetRandomSSU2Introducer (bool v4, const std::set& excluded) const; std::shared_ptr GetClosestFloodfill (const IdentHash& destination, const std::set& excluded) const; diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index db6f74f9..6234ceb4 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -709,7 +709,7 @@ namespace tunnel auto inboundTunnel = GetNextInboundTunnel (); auto router = i2p::transport::transports.RoutesRestricted() ? i2p::transport::transports.GetRestrictedPeer() : - i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false); // reachable by us + i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, true); // reachable by us if (!inboundTunnel || !router) return; LogPrint (eLogDebug, "Tunnel: Creating one hop outbound tunnel"); CreateTunnel ( @@ -781,7 +781,7 @@ namespace tunnel auto router = i2p::transport::transports.RoutesRestricted() ? i2p::transport::transports.GetRestrictedPeer() : // should be reachable by us because we send build request directly - i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false); + i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, true); if (!router) { LogPrint (eLogWarning, "Tunnel: Can't find any router, skip creating tunnel"); return; diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index a2168f64..5b305de1 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -470,13 +470,14 @@ namespace tunnel return i2p::tunnel::tunnels.GetExploratoryPool () == shared_from_this (); } - std::shared_ptr TunnelPool::SelectNextHop (std::shared_ptr prevHop, bool reverse) const + std::shared_ptr TunnelPool::SelectNextHop (std::shared_ptr prevHop, + bool reverse, bool endpoint) const { - auto hop = IsExploratory () ? i2p::data::netdb.GetRandomRouter (prevHop, reverse): - i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse); + auto hop = IsExploratory () ? i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint): + i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse, endpoint); if (!hop || hop->GetProfile ()->IsBad ()) - hop = i2p::data::netdb.GetRandomRouter (prevHop, reverse); + hop = i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint); return hop; } @@ -508,7 +509,7 @@ namespace tunnel for(int i = start; i < numHops; i++ ) { - auto hop = nextHop (prevHop, inbound); + auto hop = nextHop (prevHop, inbound, i == numHops - 1); if (!hop && !i) // if no suitable peer found for first hop, try already connected { LogPrint (eLogInfo, "Tunnels: Can't select first hop for a tunnel. Trying already connected"); @@ -520,11 +521,6 @@ namespace tunnel LogPrint (eLogError, "Tunnels: Can't select next hop for ", prevHop->GetIdentHashBase64 ()); return false; } - if ((i == numHops - 1) && (!hop->IsV4 () || (inbound && !hop->IsPublished (true)))) // IBGW is not published ipv4 - { - auto hop1 = nextHop (prevHop, inbound); - if (hop1) hop = hop1; - } prevHop = hop; path.Add (hop); } @@ -566,7 +562,8 @@ namespace tunnel if (m_CustomPeerSelector) return m_CustomPeerSelector->SelectPeers(path, numHops, isInbound); } - return StandardSelectPeers(path, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this, std::placeholders::_1, std::placeholders::_2)); + return StandardSelectPeers(path, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); } bool TunnelPool::SelectExplicitPeers (Path& path, bool isInbound) diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index e9dd142e..c1fd19cd 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -56,7 +56,7 @@ namespace tunnel class TunnelPool: public std::enable_shared_from_this // per local destination { - typedef std::function(std::shared_ptr, bool)> SelectHopFunc; + typedef std::function(std::shared_ptr, bool, bool)> SelectHopFunc; public: TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, @@ -112,7 +112,7 @@ namespace tunnel std::shared_ptr GetLowestLatencyOutboundTunnel(std::shared_ptr exclude = nullptr) const; // for overriding tunnel peer selection - std::shared_ptr SelectNextHop (std::shared_ptr prevHop, bool reverse) const; + std::shared_ptr SelectNextHop (std::shared_ptr prevHop, bool reverse, bool endpoint) const; bool StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop); private: diff --git a/libi2pd_client/MatchedDestination.cpp b/libi2pd_client/MatchedDestination.cpp index 1e2e8275..40752f5b 100644 --- a/libi2pd_client/MatchedDestination.cpp +++ b/libi2pd_client/MatchedDestination.cpp @@ -73,7 +73,8 @@ namespace client { auto pool = GetTunnelPool(); if(!pool || !pool->StandardSelectPeers(path, hops, inbound, - std::bind(&i2p::tunnel::TunnelPool::SelectNextHop, pool, std::placeholders::_1, std::placeholders::_2))) + std::bind(&i2p::tunnel::TunnelPool::SelectNextHop, pool, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3))) return false; // more here for outbound tunnels if(!inbound && m_RemoteLeaseSet) From ea7cf1cf6905257cd668848283ad86dfb5c6eb00 Mon Sep 17 00:00:00 2001 From: Vort Date: Sat, 15 Jul 2023 18:44:37 +0300 Subject: [PATCH 02/23] fix termination block processing and size check --- libi2pd/NTCP2.cpp | 2 +- libi2pd/SSU2Session.cpp | 23 ++++++++++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 5e1cbaf6..364ebe8e 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -884,7 +884,7 @@ namespace transport auto size = bufbe16toh (frame + offset); offset += 2; LogPrint (eLogDebug, "NTCP2: Block type ", (int)blk, " of size ", size); - if (size > len) + if (offset + size > len) { LogPrint (eLogError, "NTCP2: Unexpected block length ", size); break; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 49004437..23afd4c3 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1486,7 +1486,7 @@ namespace transport auto size = bufbe16toh (buf + offset); offset += 2; LogPrint (eLogDebug, "SSU2: Block type ", (int)blk, " of size ", size); - if (size > len) + if (offset + size > len) { LogPrint (eLogError, "SSU2: Unexpected block length ", size); break; @@ -1532,16 +1532,21 @@ namespace transport break; case eSSU2BlkTermination: { - uint8_t rsn = buf[11]; // reason - LogPrint (eLogDebug, "SSU2: Termination reason=", (int)rsn); - if (IsEstablished () && rsn != eSSU2TerminationReasonTerminationReceived) - RequestTermination (eSSU2TerminationReasonTerminationReceived); - else if (m_State != eSSU2SessionStateTerminated) + if (size >= 9) { - if (m_State == eSSU2SessionStateClosing && rsn == eSSU2TerminationReasonTerminationReceived) - m_State = eSSU2SessionStateClosingConfirmed; - Done (); + uint8_t rsn = buf[offset + 8]; // reason + LogPrint (eLogDebug, "SSU2: Termination reason=", (int)rsn); + if (IsEstablished () && rsn != eSSU2TerminationReasonTerminationReceived) + RequestTermination (eSSU2TerminationReasonTerminationReceived); + else if (m_State != eSSU2SessionStateTerminated) + { + if (m_State == eSSU2SessionStateClosing && rsn == eSSU2TerminationReasonTerminationReceived) + m_State = eSSU2SessionStateClosingConfirmed; + Done (); + } } + else + LogPrint(eLogWarning, "SSU2: Unexpected termination block size ", size); break; } case eSSU2BlkRelayRequest: From 8e63f8f333d21724bb5143f99f8ee0c471ddd473 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 15 Jul 2023 17:11:56 -0400 Subject: [PATCH 03/23] consider all addresses non published for U and H routers --- libi2pd/RouterInfo.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 5ba8a5b1..646711c1 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -995,6 +995,7 @@ namespace data bool RouterInfo::IsPublished (bool v4) const { + if (m_Caps & (eUnreachable | eHidden)) return false; // if router sets U or H we assume that all addreses are not published auto addr = GetAddresses (); if (v4) return ((*addr)[eNTCP2V4Idx] && ((*addr)[eNTCP2V4Idx])->published) || From 940a97db11d2e092273090319b4cf2f148bb0971 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 16 Jul 2023 14:02:30 +0300 Subject: [PATCH 04/23] [gha] fix msvc build Signed-off-by: r4sas --- .github/workflows/build-windows-msvc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-windows-msvc.yml b/.github/workflows/build-windows-msvc.yml index 356bb466..172e0596 100644 --- a/.github/workflows/build-windows-msvc.yml +++ b/.github/workflows/build-windows-msvc.yml @@ -29,7 +29,7 @@ jobs: - name: Install Boost uses: crazy-max/ghaction-chocolatey@v2 with: - args: install boost-msvc-14.3 + args: install boost-msvc-14.3 --version=1.81.0 - name: Install OpenSSL uses: crazy-max/ghaction-chocolatey@v2 From e7157cf15efddbe50a057c72afee5eb0a3276199 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 17 Jul 2023 17:57:30 -0400 Subject: [PATCH 05/23] don't create paired inbound tunnel if length is different --- libi2pd/TunnelPool.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 5b305de1..fd31cb09 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -296,10 +296,12 @@ namespace tunnel for (const auto& it : m_InboundTunnels) if (it->IsEstablished ()) num++; } - if (!num && !m_OutboundTunnels.empty () && m_NumOutboundHops > 0) + if (!num && !m_OutboundTunnels.empty () && m_NumOutboundHops > 0 && + m_NumInboundHops == m_NumOutboundHops) { for (auto it: m_OutboundTunnels) { + // try to create inbound tunnel through the same path as succesive outbound CreatePairedInboundTunnel (it); num++; if (num >= m_NumInboundTunnels) break; From c620fc1232e4a7823b2ac1558ffeb454c3a9f8b4 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 17 Jul 2023 18:44:51 -0400 Subject: [PATCH 06/23] clear unreachable flag upon succesive connect --- libi2pd/NetDb.cpp | 9 +++------ libi2pd/Profiling.cpp | 6 +++--- libi2pd/Profiling.h | 2 +- libi2pd/Transports.cpp | 1 + 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 7bccb2a0..112d3cb3 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -424,12 +424,9 @@ namespace data if (r) { r->SetUnreachable (unreachable); - if (unreachable) - { - auto profile = r->GetProfile (); - if (profile) - profile->Unreachable (); - } + auto profile = r->GetProfile (); + if (profile) + profile->Unreachable (unreachable); } } diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 47fc15e7..879aea29 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -165,12 +165,12 @@ namespace data } } - void RouterProfile::Unreachable () + void RouterProfile::Unreachable (bool unreachable) { - m_LastUnreachableTime = i2p::util::GetSecondsSinceEpoch (); + m_LastUnreachableTime = unreachable ? i2p::util::GetSecondsSinceEpoch () : 0; UpdateTime (); } - + void RouterProfile::Connected () { m_HasConnected = true; diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index 6b814893..c351b41d 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -55,7 +55,7 @@ namespace data void TunnelBuildResponse (uint8_t ret); void TunnelNonReplied (); - void Unreachable (); + void Unreachable (bool unreachable); void Connected (); boost::posix_time::ptime GetLastUpdateTime () const { return m_LastUpdateTime; }; diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 38d6e270..01e484f4 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -716,6 +716,7 @@ namespace transport if (transport == i2p::data::RouterInfo::eNTCP2V4 || transport == i2p::data::RouterInfo::eNTCP2V6 || transport == i2p::data::RouterInfo::eNTCP2V6Mesh) it->second.router->GetProfile ()->Connected (); // outgoing NTCP2 connection if always real + i2p::data::netdb.SetUnreachable (ident, false); // clear unreachable } it->second.numAttempts = 0; it->second.router = nullptr; // we don't need RouterInfo after successive connect From 902899ae2422d82147a5e73dac13d7a7f2297a30 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 17 Jul 2023 19:49:42 -0400 Subject: [PATCH 07/23] don't pick completely unreachable peers --- libi2pd/NetDb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 112d3cb3..061ccc23 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1203,7 +1203,7 @@ namespace data [compatibleWith, reverse, endpoint](std::shared_ptr router)->bool { return !router->IsHidden () && router != compatibleWith && - (reverse ? compatibleWith->IsReachableFrom (*router) : + (reverse ? (compatibleWith->IsReachableFrom (*router) && router->GetCompatibleTransports (true)): router->IsReachableFrom (*compatibleWith)) && router->IsECIES () && !router->IsHighCongestion (false) && (!endpoint || (router->IsV4 () && (!reverse || router->IsPublished (true)))); // endpoint must be ipv4 and published if inbound(reverse) @@ -1237,7 +1237,7 @@ namespace data [compatibleWith, reverse, endpoint](std::shared_ptr router)->bool { return !router->IsHidden () && router != compatibleWith && - (reverse ? compatibleWith->IsReachableFrom (*router) : + (reverse ? (compatibleWith->IsReachableFrom (*router) && router->GetCompatibleTransports (true)) : router->IsReachableFrom (*compatibleWith)) && (router->GetCaps () & RouterInfo::eHighBandwidth) && router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION && From 0754255c1f597beba3f9dae5c21f7c99e927918b Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 17 Jul 2023 21:08:26 -0400 Subject: [PATCH 08/23] drop incoming session from too old or from future routers --- libi2pd/NTCP2.cpp | 11 +++++++++-- libi2pd/SSU2Session.cpp | 11 +++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 364ebe8e..fa852f92 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -695,12 +695,19 @@ namespace transport SendTerminationAndTerminate (eNTCP2RouterInfoSignatureVerificationFail); return; } - if (i2p::util::GetMillisecondsSinceEpoch () > ri.GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes + auto ts = i2p::util::GetMillisecondsSinceEpoch (); + if (ts > ri.GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes { - LogPrint (eLogError, "NTCP2: RouterInfo is too old in SessionConfirmed"); + LogPrint (eLogError, "NTCP2: RouterInfo is too old in SessionConfirmed for ", (ts - ri.GetTimestamp ())/1000LL, " seconds"); SendTerminationAndTerminate (eNTCP2Message3Error); return; } + if (ts + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri.GetTimestamp ()) // 2 minutes + { + LogPrint (eLogError, "NTCP2: RouterInfo is from future for ", (ri.GetTimestamp () - ts)/1000LL, " seconds"); + SendTerminationAndTerminate (eNTCP2Message3Error); + return; + } auto addr = m_RemoteEndpoint.address ().is_v4 () ? ri.GetNTCP2V4Address () : (i2p::util::net::IsYggdrasilAddress (m_RemoteEndpoint.address ()) ? ri.GetYggdrasilAddress () : ri.GetNTCP2V6Address ()); if (!addr || memcmp (m_Establisher->m_RemoteStaticKey, addr->s, 32)) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 23afd4c3..51c167ea 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1053,6 +1053,17 @@ namespace transport LogPrint (eLogError, "SSU2: SessionConfirmed malformed RouterInfo block"); return false; } + auto ts = i2p::util::GetMillisecondsSinceEpoch(); + if (ts > ri->GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes + { + LogPrint (eLogError, "SSU2: RouterInfo in SessionConfirmed is too old for ", (ts - ri->GetTimestamp ())/1000LL, " seconds"); + return false; + } + if (ts + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri->GetTimestamp ()) // 2 minutes + { + LogPrint (eLogError, "SSU2: RouterInfo in SessionConfirmed is from future for ", (ri->GetTimestamp () - ts)/1000LL, " seconds"); + return false; + } m_Address = m_RemoteEndpoint.address ().is_v6 () ? ri->GetSSU2V6Address () : ri->GetSSU2V4Address (); if (!m_Address || memcmp (S, m_Address->s, 32)) { From f13cc0b862646c0d13514d429d1472df1b948883 Mon Sep 17 00:00:00 2001 From: Vort Date: Wed, 19 Jul 2023 16:38:04 +0300 Subject: [PATCH 09/23] allow 0 hops with explicitPeers --- libi2pd/TunnelPool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index fd31cb09..23cc53e3 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -570,9 +570,9 @@ namespace tunnel bool TunnelPool::SelectExplicitPeers (Path& path, bool isInbound) { + if (!m_ExplicitPeers->size ()) return false; int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops; if (numHops > (int)m_ExplicitPeers->size ()) numHops = m_ExplicitPeers->size (); - if (!numHops) return false; for (int i = 0; i < numHops; i++) { auto& ident = (*m_ExplicitPeers)[i]; From 6e9a3422e9e723197c3ad56fbc9357f2656fe1f3 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 21 Jul 2023 07:59:09 -0400 Subject: [PATCH 10/23] correct min size for keepalive --- libi2pd/SSU2Session.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 51c167ea..dcc5ad52 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -243,7 +243,7 @@ namespace transport if (IsEstablished ()) { uint8_t payload[20]; - size_t payloadSize = CreatePaddingBlock (payload, 20, 5); + size_t payloadSize = CreatePaddingBlock (payload, 20, 8); SendData (payload, payloadSize); } } From c7efd465fa5bd06d4fccfde0e771a1920c624049 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 21 Jul 2023 18:25:28 -0400 Subject: [PATCH 11/23] padding for path response --- libi2pd/SSU2Session.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index dcc5ad52..4a1395b3 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2857,7 +2857,7 @@ namespace transport void SSU2Session::SendPathResponse (const uint8_t * data, size_t len) { - if (len < 8 || len > m_MaxPayloadSize - 3) + if (len > m_MaxPayloadSize - 3) { LogPrint (eLogWarning, "SSU2: Incorrect data size for path response ", len); return; @@ -2866,7 +2866,10 @@ namespace transport payload[0] = eSSU2BlkPathResponse; htobe16buf (payload + 1, len); memcpy (payload + 3, data, len); - SendData (payload, len + 3); + size_t payloadSize = len + 3; + if (payloadSize < m_MaxPayloadSize) + payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, payloadSize < 8 ? 8 : 0); + SendData (payload, payloadSize); } void SSU2Session::SendPathChallenge () @@ -2884,7 +2887,7 @@ namespace transport } len += 3; if (len < m_MaxPayloadSize) - len += CreatePaddingBlock (payload + len, m_MaxPayloadSize - len); + len += CreatePaddingBlock (payload + len, m_MaxPayloadSize - len, len < 8 ? 8 : 0); SendData (payload, len); } From b8e19bf5f1e3fbcf0f45ccfb85b1923142d96e46 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 22 Jul 2023 08:50:49 -0400 Subject: [PATCH 12/23] reduced peer test interval and added peer test interval variance --- libi2pd/SSU2.cpp | 12 ++++++++---- libi2pd/SSU2.h | 3 ++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index a9e04790..6594f6d9 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1078,7 +1078,8 @@ namespace transport { if (m_IsPublished) { - m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL)); + m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds( + SSU2_KEEP_ALIVE_INTERVAL + rand () % SSU2_KEEP_ALIVE_INTERVAL_VARIANCE)); m_IntroducersUpdateTimer.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, this, std::placeholders::_1, true)); } @@ -1091,7 +1092,8 @@ namespace transport m_IntroducersUpdateTimer.cancel (); i2p::context.ClearSSU2Introducers (true); m_Introducers.clear (); - m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL/2)); + m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds( + (SSU2_KEEP_ALIVE_INTERVAL + rand () % SSU2_KEEP_ALIVE_INTERVAL_VARIANCE)/2)); m_IntroducersUpdateTimer.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, this, std::placeholders::_1, true)); } @@ -1101,7 +1103,8 @@ namespace transport { if (m_IsPublished) { - m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL)); + m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds( + SSU2_KEEP_ALIVE_INTERVAL + rand () % SSU2_KEEP_ALIVE_INTERVAL_VARIANCE)); m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, this, std::placeholders::_1, false)); } @@ -1114,7 +1117,8 @@ namespace transport m_IntroducersUpdateTimerV6.cancel (); i2p::context.ClearSSU2Introducers (false); m_IntroducersV6.clear (); - m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL/2)); + m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds( + (SSU2_KEEP_ALIVE_INTERVAL + rand () % SSU2_KEEP_ALIVE_INTERVAL_VARIANCE)/2)); m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, this, std::placeholders::_1, false)); } diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 2e652786..a1fafc63 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -29,7 +29,8 @@ namespace transport const size_t SSU2_MAX_NUM_INTRODUCERS = 3; const int SSU2_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour const int SSU2_TO_INTRODUCER_SESSION_EXPIRATION = 4800; // 80 minutes - const int SSU2_KEEP_ALIVE_INTERVAL = 30; // in seconds + const int SSU2_KEEP_ALIVE_INTERVAL = 15; // in seconds + const int SSU2_KEEP_ALIVE_INTERVAL_VARIANCE = 4; // in seconds const int SSU2_PROXY_CONNECT_RETRY_TIMEOUT = 30; // in seconds class SSU2Server: private i2p::util::RunnableServiceWithWork From 413e25f20e16a0a0e1b01ed9cdf1d76e20ba3a5b Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 22 Jul 2023 10:13:05 -0400 Subject: [PATCH 13/23] don't pick too old session for introducer --- libi2pd/SSU2.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 6594f6d9..f3f0542d 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1035,10 +1035,13 @@ namespace transport for (const auto& it : sessions) { + uint32_t exp = it->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION; + if (ts + SSU2_TO_INTRODUCER_SESSION_DURATION/2 > exp) + continue; // don't pick too old session for introducer i2p::data::RouterInfo::Introducer introducer; introducer.iTag = it->GetRelayTag (); introducer.iH = it->GetRemoteIdentity ()->GetIdentHash (); - introducer.iExp = it->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION; + introducer.iExp = exp; excluded.insert (it->GetRemoteIdentity ()->GetIdentHash ()); if (i2p::context.AddSSU2Introducer (introducer, v4)) { From d6834d6a9a205756f77a1ec02488db947a1c4d4d Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 22 Jul 2023 15:03:03 -0400 Subject: [PATCH 14/23] keep non-published, but not-expired introducers in the introducers list --- libi2pd/SSU2.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index f3f0542d..959bef54 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -983,7 +983,7 @@ namespace transport void SSU2Server::UpdateIntroducers (bool v4) { uint32_t ts = i2p::util::GetSecondsSinceEpoch (); - std::list newList; + std::list newList, impliedList; auto& introducers = v4 ? m_Introducers : m_IntroducersV6; std::set excluded; for (const auto& it : introducers) @@ -997,12 +997,17 @@ namespace transport } if (session && session->IsEstablished ()) { - if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) - session->SendKeepAlive (); if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) newList.push_back (it); else + { + if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) + { + impliedList.push_back (it); // keep in introducers list, but not publish + session->SendKeepAlive (); + } session = nullptr; + } } if (!session) i2p::context.RemoveSSU2Introducer (it, v4); @@ -1024,10 +1029,7 @@ namespace transport { session->SetCreationTime (session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION); if (std::find (newList.begin (), newList.end (), it) == newList.end ()) - { - newList.push_back (it); sessions.push_back (session); - } } } } @@ -1075,6 +1077,7 @@ namespace transport } } } + introducers.splice (introducers.end (), impliedList); // insert non-published, but non-expired introducers back } void SSU2Server::ScheduleIntroducersUpdateTimer () From 4aa631c33f7db3e75979a3e21da3597ebd83bc6b Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 22 Jul 2023 16:51:19 -0400 Subject: [PATCH 15/23] clear implied list if no more introducers found --- libi2pd/SSU2.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 959bef54..c371928c 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1019,6 +1019,7 @@ namespace transport { // bump creation time for previous introducers if no new sessions found LogPrint (eLogDebug, "SSU2: No new introducers found. Trying to reuse existing"); + impliedList.clear (); for (auto& it : introducers) { auto it1 = m_SessionsByRouterHash.find (it); From 2064504ccedc84d16007db4b22f8385c949dec28 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 23 Jul 2023 07:17:10 -0400 Subject: [PATCH 16/23] fixed send keepalive for existing session --- libi2pd/SSU2.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index c371928c..0832b78c 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -997,17 +997,16 @@ namespace transport } if (session && session->IsEstablished ()) { - if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) + if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) newList.push_back (it); else { if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) - { impliedList.push_back (it); // keep in introducers list, but not publish - session->SendKeepAlive (); - } - session = nullptr; - } + else + session = nullptr; + } + if (session) session->SendKeepAlive (); } if (!session) i2p::context.RemoveSSU2Introducer (it, v4); From ae5239de435e1dcdff342961af9b506f60a494d4 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 23 Jul 2023 07:42:36 -0400 Subject: [PATCH 17/23] remove introducer from RouterInfo after 60 minutes --- libi2pd/SSU2.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 0832b78c..ac42ca7a 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -997,16 +997,19 @@ namespace transport } if (session && session->IsEstablished ()) { - if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) - newList.push_back (it); - else + if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) { - if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) + session->SendKeepAlive (); + if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) + newList.push_back (it); + else + { impliedList.push_back (it); // keep in introducers list, but not publish - else - session = nullptr; + session = nullptr; + } } - if (session) session->SendKeepAlive (); + else + session = nullptr; } if (!session) i2p::context.RemoveSSU2Introducer (it, v4); From 68f4961f1aff340f5e0269af7653cf029918d97a Mon Sep 17 00:00:00 2001 From: Vort Date: Sun, 30 Jul 2023 15:29:10 +0300 Subject: [PATCH 18/23] separate test status from network status --- Win32/Win32App.cpp | 9 ++++--- daemon/HTTPServer.cpp | 9 ++++--- libi2pd/RouterContext.cpp | 31 ++++++++++++++++++------ libi2pd/RouterContext.h | 14 +++++++---- libi2pd/SSU2.cpp | 4 +-- libi2pd/SSU2Session.cpp | 51 ++++++++++++++++++++++++++++++--------- libi2pd/SSU2Session.h | 2 ++ libi2pd/Transports.cpp | 12 ++++----- 8 files changed, 92 insertions(+), 40 deletions(-) diff --git a/Win32/Win32App.cpp b/Win32/Win32App.cpp index fc61a8ac..9f750c4c 100644 --- a/Win32/Win32App.cpp +++ b/Win32/Win32App.cpp @@ -145,18 +145,19 @@ namespace win32 s << bytes << " Bytes\n"; } - static void ShowNetworkStatus (std::stringstream& s, RouterStatus status) + static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, bool testing) { switch (status) { case eRouterStatusOK: s << "OK"; break; - case eRouterStatusTesting: s << "Test"; break; case eRouterStatusFirewalled: s << "FW"; break; case eRouterStatusUnknown: s << "Unk"; break; case eRouterStatusProxy: s << "Proxy"; break; case eRouterStatusMesh: s << "Mesh"; break; default: s << "Unk"; }; + if (testing) + s << " (Test)"; if (i2p::context.GetError () != eRouterErrorNone) { switch (i2p::context.GetError ()) @@ -179,11 +180,11 @@ namespace win32 { s << "\n"; s << "Status: "; - ShowNetworkStatus (s, i2p::context.GetStatus ()); + ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetTesting ()); if (i2p::context.SupportsV6 ()) { s << " / "; - ShowNetworkStatus (s, i2p::context.GetStatusV6 ()); + ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetTestingV6 ()); } s << "; "; s << "Success Rate: " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate() << "%\n"; diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 50666940..2d6800b4 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -222,18 +222,19 @@ namespace http { s << "" << tr("ERROR") << ": " << string << "
\r\n"; } - static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, RouterError error) + static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, bool testing, RouterError error) { switch (status) { case eRouterStatusOK: s << tr("OK"); break; - case eRouterStatusTesting: s << tr("Testing"); break; case eRouterStatusFirewalled: s << tr("Firewalled"); break; case eRouterStatusUnknown: s << tr("Unknown"); break; case eRouterStatusProxy: s << tr("Proxy"); break; case eRouterStatusMesh: s << tr("Mesh"); break; default: s << tr("Unknown"); } + if (testing) + s << " (" << tr("Testing") << ")"; if (error != eRouterErrorNone) { switch (error) @@ -264,12 +265,12 @@ namespace http { ShowUptime(s, i2p::context.GetUptime ()); s << "
\r\n"; s << "" << tr("Network status") << ": "; - ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetError ()); + ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetTesting(), i2p::context.GetError ()); s << "
\r\n"; if (i2p::context.SupportsV6 ()) { s << "" << tr("Network status v6") << ": "; - ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetErrorV6 ()); + ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetTestingV6(), i2p::context.GetErrorV6 ()); s << "
\r\n"; } #if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY)) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 3e7d7a2c..fa3ba7bd 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -31,7 +31,8 @@ namespace i2p RouterContext::RouterContext (): m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false), m_ShareRatio (100), m_Status (eRouterStatusUnknown), m_StatusV6 (eRouterStatusUnknown), - m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone), m_NetID (I2PD_NET_ID), + m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone), + m_Testing (false), m_TestingV6 (false), m_NetID (I2PD_NET_ID), m_PublishReplyToken (0), m_IsHiddenMode (false) { } @@ -277,8 +278,29 @@ namespace i2p fk.write ((char *)m_SSU2Keys.get (), sizeof (SSU2PrivateKeys)); } + void RouterContext::SetTesting (bool testing) + { + if (testing != m_Testing) + { + m_Testing = testing; + if (m_Testing) + m_Error = eRouterErrorNone; + } + } + + void RouterContext::SetTestingV6 (bool testing) + { + if (testing != m_TestingV6) + { + m_TestingV6 = testing; + if (m_TestingV6) + m_ErrorV6 = eRouterErrorNone; + } + } + void RouterContext::SetStatus (RouterStatus status) { + SetTesting (false); if (status != m_Status) { m_Status = status; @@ -290,9 +312,6 @@ namespace i2p case eRouterStatusFirewalled: SetUnreachable (true, false); // ipv4 break; - case eRouterStatusTesting: - m_Error = eRouterErrorNone; - break; default: ; } @@ -301,6 +320,7 @@ namespace i2p void RouterContext::SetStatusV6 (RouterStatus status) { + SetTestingV6 (false); if (status != m_StatusV6) { m_StatusV6 = status; @@ -312,9 +332,6 @@ namespace i2p case eRouterStatusFirewalled: SetUnreachable (false, true); // ipv6 break; - case eRouterStatusTesting: - m_ErrorV6 = eRouterErrorNone; - break; default: ; } diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index b8183339..d49b5523 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -42,11 +42,10 @@ namespace garlic enum RouterStatus { eRouterStatusOK = 0, - eRouterStatusTesting = 1, - eRouterStatusFirewalled = 2, - eRouterStatusUnknown = 3, - eRouterStatusProxy = 4, - eRouterStatusMesh = 5 + eRouterStatusFirewalled = 1, + eRouterStatusUnknown = 2, + eRouterStatusProxy = 3, + eRouterStatusMesh = 4 }; enum RouterError @@ -121,10 +120,14 @@ namespace garlic uint64_t GetLastUpdateTime () const { return m_LastUpdateTime; }; uint64_t GetBandwidthLimit () const { return m_BandwidthLimit; }; uint64_t GetTransitBandwidthLimit () const { return (m_BandwidthLimit*m_ShareRatio)/100LL; }; + bool GetTesting () const { return m_Testing; }; + void SetTesting (bool testing); RouterStatus GetStatus () const { return m_Status; }; void SetStatus (RouterStatus status); RouterError GetError () const { return m_Error; }; void SetError (RouterError error) { m_Error = error; }; + bool GetTestingV6 () const { return m_TestingV6; }; + void SetTestingV6 (bool testing); RouterStatus GetStatusV6 () const { return m_StatusV6; }; void SetStatusV6 (RouterStatus status); RouterError GetErrorV6 () const { return m_ErrorV6; }; @@ -231,6 +234,7 @@ namespace garlic int m_ShareRatio; RouterStatus m_Status, m_StatusV6; RouterError m_Error, m_ErrorV6; + bool m_Testing, m_TestingV6; int m_NetID; std::unique_ptr m_NTCP2Keys; std::unique_ptr m_SSU2Keys; diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index ac42ca7a..53ef8db7 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1140,7 +1140,7 @@ namespace transport // timeout expired if (v4) { - if (i2p::context.GetStatus () == eRouterStatusTesting) + if (i2p::context.GetTesting ()) { // we still don't know if we need introducers ScheduleIntroducersUpdateTimer (); @@ -1163,7 +1163,7 @@ namespace transport } else { - if (i2p::context.GetStatusV6 () == eRouterStatusTesting) + if (i2p::context.GetTestingV6 ()) { // we still don't know if we need introducers ScheduleIntroducersUpdateTimerV6 (); diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 4a1395b3..54add930 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1651,8 +1651,8 @@ namespace transport break; case eSSU2SessionStateSessionCreatedReceived: case eSSU2SessionStateTokenReceived: - if ((m_RemoteEndpoint.address ().is_v4 () && i2p::context.GetStatus () == eRouterStatusTesting) || - (m_RemoteEndpoint.address ().is_v6 () && i2p::context.GetStatusV6 () == eRouterStatusTesting)) + if ((m_RemoteEndpoint.address ().is_v4 () && i2p::context.GetTesting ()) || + (m_RemoteEndpoint.address ().is_v6 () && i2p::context.GetTestingV6 ())) { if (m_Server.IsSyncClockFromPeers ()) { @@ -1750,14 +1750,14 @@ namespace transport LogPrint (eLogInfo, "SSU2: Our port ", ep.port (), " received from ", m_RemoteEndpoint, " is different from ", m_Server.GetPort (isV4)); if (isV4) { - if (i2p::context.GetStatus () == eRouterStatusTesting) + if (i2p::context.GetTesting ()) i2p::context.SetError (eRouterErrorSymmetricNAT); else if (m_State == eSSU2SessionStatePeerTest) i2p::context.SetError (eRouterErrorFullConeNAT); } else { - if (i2p::context.GetStatusV6 () == eRouterStatusTesting) + if (i2p::context.GetTestingV6 ()) i2p::context.SetErrorV6 (eRouterErrorSymmetricNAT); else if (m_State == eSSU2SessionStatePeerTest) i2p::context.SetErrorV6 (eRouterErrorFullConeNAT); @@ -2230,7 +2230,7 @@ namespace transport if (buf[1] == eSSU2PeerTestCodeAccept) { if (GetRouterStatus () == eRouterStatusUnknown) - SetRouterStatus (eRouterStatusTesting); + SetTestingState (true); auto r = i2p::data::netdb.FindRouter (buf + 3); // find Charlie if (r && it->second.first) { @@ -2256,13 +2256,17 @@ namespace transport } else { - if (GetRouterStatus () == eRouterStatusTesting) + if (GetTestingState ()) { - SetRouterStatus (eRouterStatusFirewalled); - if (m_Address->IsV4 ()) - m_Server.RescheduleIntroducersUpdateTimer (); - else - m_Server.RescheduleIntroducersUpdateTimerV6 (); + SetTestingState (false); + if (GetRouterStatus () != eRouterStatusFirewalled) + { + SetRouterStatus (eRouterStatusFirewalled); + if (m_Address->IsV4 ()) + m_Server.RescheduleIntroducersUpdateTimer (); + else + m_Server.RescheduleIntroducersUpdateTimerV6 (); + } } } LogPrint (eLogDebug, "SSU2: Peer test 4 received from ", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), @@ -2291,7 +2295,7 @@ namespace transport { LogPrint (eLogInfo, "SSU2: Peer test 4 error code ", (int)buf[1], " from ", i2p::data::GetIdentHashAbbreviation (buf[1] < 64 ? GetRemoteIdentity ()->GetIdentHash () : i2p::data::IdentHash (buf + 3))); - if (GetRouterStatus () == eRouterStatusTesting) + if (GetTestingState ()) SetRouterStatus (eRouterStatusUnknown); it->second.first->Done (); } @@ -2445,6 +2449,29 @@ namespace transport } } + bool SSU2Session::GetTestingState () const + { + if (m_Address) + { + if (m_Address->IsV4 ()) + return i2p::context.GetTesting (); + if (m_Address->IsV6 ()) + return i2p::context.GetTestingV6 (); + } + return false; + } + + void SSU2Session::SetTestingState (bool testing) const + { + if (m_Address) + { + if (m_Address->IsV4 ()) + i2p::context.SetTesting (testing); + else if (m_Address->IsV6 ()) + i2p::context.SetTestingV6 (testing); + } + } + size_t SSU2Session::CreateAddressBlock (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep) { if (len < 9) return 0; diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 304efdab..14d76971 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -308,6 +308,8 @@ namespace transport void AdjustMaxPayloadSize (); RouterStatus GetRouterStatus () const; void SetRouterStatus (RouterStatus status) const; + bool GetTestingState () const; + void SetTestingState(bool testing) const; std::shared_ptr ExtractRouterInfo (const uint8_t * buf, size_t size); void CreateNonce (uint64_t seqn, uint8_t * nonce); bool UpdateReceivePacketNum (uint32_t packetNum); // for Ack, returns false if duplicate diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 01e484f4..b452c05e 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -650,8 +650,8 @@ namespace transport auto router = i2p::data::netdb.GetRandomSSU2PeerTestRouter (true, excluded); // v4 if (router) { - if (i2p::context.GetStatus () != eRouterStatusTesting) - i2p::context.SetStatus (eRouterStatusTesting); + if (!i2p::context.GetTesting ()) + i2p::context.SetTesting (true); m_SSU2Server->StartPeerTest (router, true); excluded.insert (router->GetIdentHash ()); } @@ -669,8 +669,8 @@ namespace transport auto router = i2p::data::netdb.GetRandomSSU2PeerTestRouter (false, excluded); // v6 if (router) { - if (i2p::context.GetStatusV6 () != eRouterStatusTesting) - i2p::context.SetStatusV6 (eRouterStatusTesting); + if (!i2p::context.GetTestingV6 ()) + i2p::context.SetTestingV6 (true); m_SSU2Server->StartPeerTest (router, false); excluded.insert (router->GetIdentHash ()); } @@ -832,8 +832,8 @@ namespace transport ++it; } } - bool ipv4Testing = i2p::context.GetStatus () == eRouterStatusTesting; - bool ipv6Testing = i2p::context.GetStatusV6 () == eRouterStatusTesting; + bool ipv4Testing = i2p::context.GetTesting (); + bool ipv6Testing = i2p::context.GetTestingV6 (); // if still testing, repeat peer test if (ipv4Testing || ipv6Testing) PeerTest (ipv4Testing, ipv6Testing); From 38795a41cbbb21a756ecb4fd13f045e6f5f5811f Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 5 Aug 2023 08:55:06 -0400 Subject: [PATCH 19/23] don't publish introducers with zero iTag --- libi2pd/SSU2.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 53ef8db7..5d0e7d22 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1028,7 +1028,7 @@ namespace transport if (it1 != m_SessionsByRouterHash.end ()) { auto session = it1->second; - if (session->IsEstablished ()) + if (session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing ()) { session->SetCreationTime (session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION); if (std::find (newList.begin (), newList.end (), it) == newList.end ()) @@ -1040,11 +1040,12 @@ namespace transport for (const auto& it : sessions) { + uint32_t tag = it->GetRelayTag (); uint32_t exp = it->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION; - if (ts + SSU2_TO_INTRODUCER_SESSION_DURATION/2 > exp) + if (!tag || ts + SSU2_TO_INTRODUCER_SESSION_DURATION/2 > exp) continue; // don't pick too old session for introducer i2p::data::RouterInfo::Introducer introducer; - introducer.iTag = it->GetRelayTag (); + introducer.iTag = tag; introducer.iH = it->GetRemoteIdentity ()->GetIdentHash (); introducer.iExp = exp; excluded.insert (it->GetRemoteIdentity ()->GetIdentHash ()); From 9bac680f2a3181bb861beb2dbf739d92a5ab6597 Mon Sep 17 00:00:00 2001 From: Vort Date: Sat, 5 Aug 2023 17:49:22 +0300 Subject: [PATCH 20/23] improve transport session logging --- libi2pd/NTCP2.cpp | 23 ++++++++++++++++++----- libi2pd/SSU2Session.cpp | 15 ++++++++++++++- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index fa852f92..bbd93435 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -375,7 +375,16 @@ namespace transport m_Server.RemoveNTCP2Session (shared_from_this ()); m_SendQueue.clear (); m_SendQueueSize = 0; - LogPrint (eLogDebug, "NTCP2: Session terminated"); + auto remoteIdentity = GetRemoteIdentity (); + if (remoteIdentity) + { + LogPrint (eLogDebug, "NTCP2: Session with ", GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") terminated"); + } + else + { + LogPrint (eLogDebug, "NTCP2: Session with ", GetRemoteEndpoint (), " terminated"); + } } } @@ -691,11 +700,13 @@ namespace transport i2p::data::RouterInfo ri (buf.data () + 4, size - 1); // 1 byte block type + 2 bytes size + 1 byte flag if (ri.IsUnreachable ()) { - LogPrint (eLogError, "NTCP2: Signature verification failed in SessionConfirmed"); + LogPrint (eLogError, "NTCP2: RouterInfo verification failed in SessionConfirmed from ", GetRemoteEndpoint ()); SendTerminationAndTerminate (eNTCP2RouterInfoSignatureVerificationFail); return; } - auto ts = i2p::util::GetMillisecondsSinceEpoch (); + LogPrint(eLogDebug, "NTCP2: SessionConfirmed from ", GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (ri.GetIdentHash ()), ")"); + auto ts = i2p::util::GetMillisecondsSinceEpoch (); if (ts > ri.GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes { LogPrint (eLogError, "NTCP2: RouterInfo is too old in SessionConfirmed for ", (ts - ri.GetTimestamp ())/1000LL, " seconds"); @@ -1409,7 +1420,8 @@ namespace transport LogPrint (eLogError, "NTCP2: Can't connect to unspecified address"); return; } - LogPrint (eLogDebug, "NTCP2: Connecting to ", conn->GetRemoteEndpoint ()); + LogPrint (eLogDebug, "NTCP2: Connecting to ", conn->GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (conn->GetRemoteIdentity ()->GetIdentHash ()), ")"); GetService ().post([this, conn]() { if (this->AddNTCP2Session (conn)) @@ -1465,7 +1477,8 @@ namespace transport } else { - LogPrint (eLogDebug, "NTCP2: Connected to ", conn->GetRemoteEndpoint ()); + LogPrint (eLogDebug, "NTCP2: Connected to ", conn->GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (conn->GetRemoteIdentity ()->GetIdentHash ()), ")"); conn->ClientLogin (); } } diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 54add930..f0e539c7 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -114,6 +114,8 @@ namespace transport { if (m_State == eSSU2SessionStateUnknown || m_State == eSSU2SessionStateTokenReceived) { + LogPrint(eLogDebug, "SSU2: Connecting to ", GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ")"); ScheduleConnectTimer (); auto token = m_Server.FindOutgoingToken (m_RemoteEndpoint); if (token) @@ -269,7 +271,16 @@ namespace transport m_ReceivedI2NPMsgIDs.clear (); m_Server.RemoveSession (m_SourceConnID); transports.PeerDisconnected (shared_from_this ()); - LogPrint (eLogDebug, "SSU2: Session terminated"); + auto remoteIdentity = GetRemoteIdentity (); + if (remoteIdentity) + { + LogPrint (eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") terminated"); + } + else + { + LogPrint (eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (), " terminated"); + } } } @@ -298,6 +309,8 @@ namespace transport m_OnEstablished (); m_OnEstablished = nullptr; } + LogPrint(eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") established"); } void SSU2Session::Done () From 8447822c3596cadadfa6c7bd7ab0643ddd814b34 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 5 Aug 2023 15:25:16 -0400 Subject: [PATCH 21/23] don't publish intrducers with zero tag --- libi2pd/RouterInfo.cpp | 3 +++ libi2pd/SSU2.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 646711c1..399e26a1 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -1321,6 +1321,7 @@ namespace data int i = 0; for (const auto& introducer: address.ssu->introducers) { + if (!introducer.iTag) continue; if (introducer.iExp) // expiration is specified { WriteString ("iexp" + boost::lexical_cast(i), properties); @@ -1333,6 +1334,7 @@ namespace data i = 0; for (const auto& introducer: address.ssu->introducers) { + if (!introducer.iTag) continue; WriteString ("ih" + boost::lexical_cast(i), properties); properties << '='; char value[64]; @@ -1345,6 +1347,7 @@ namespace data i = 0; for (const auto& introducer: address.ssu->introducers) { + if (!introducer.iTag) continue; WriteString ("itag" + boost::lexical_cast(i), properties); properties << '='; WriteString (boost::lexical_cast(introducer.iTag), properties); diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 5d0e7d22..7099ba0c 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -995,7 +995,7 @@ namespace transport session = it1->second; excluded.insert (it); } - if (session && session->IsEstablished ()) + if (session && session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing ()) // still session with introducer? { if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) { From 7bcc905f05b1356bb2f02cdc2abfe5a6a516207c Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 7 Aug 2023 21:28:13 -0400 Subject: [PATCH 22/23] exclude SSU1 introducers --- libi2pd/RouterInfo.cpp | 2 +- libi2pd/RouterInfo.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 399e26a1..63cb79ef 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -579,7 +579,7 @@ namespace data int numValid = 0; for (auto& it: address->ssu->introducers) { - if (it.iTag && ts < it.iExp) + if (it.iTag && ts < it.iExp && !it.iH.IsZero ()) numValid++; else it.iTag = 0; diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 47ee1dae..9aff2240 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -125,7 +125,7 @@ namespace data struct Introducer { - Introducer (): iTag (0), iExp (0) {}; + Introducer (): iTag (0), iExp (0) { iH.Fill(0); }; IdentHash iH; uint32_t iTag; uint32_t iExp; From 627b8dca8334ad036f948013bc564abcee8c291b Mon Sep 17 00:00:00 2001 From: Chad Fraleigh Date: Sun, 13 Aug 2023 17:08:14 -0700 Subject: [PATCH 23/23] Fixed buf offset EVP_EncryptFinal_ex() to include outlen. --- libi2pd/Crypto.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 4a78f2b1..12087443 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -991,7 +991,7 @@ namespace crypto EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce); EVP_EncryptUpdate(ctx, NULL, &outlen, ad, adLen); EVP_EncryptUpdate(ctx, buf, &outlen, msg, msgLen); - EVP_EncryptFinal_ex(ctx, buf, &outlen); + EVP_EncryptFinal_ex(ctx, buf + outlen, &outlen); EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, buf + msgLen); } else