From 54ea2be8e0efd63d298600bb5f9374ae8d08dc1b Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 26 Mar 2026 21:09:41 -0400 Subject: [PATCH] don't select non-connected peer for first hop if too many connection from that subnet --- libi2pd/Transports.cpp | 52 ++++++++++++++++++++++++++++++------------ libi2pd/Transports.h | 3 +++ libi2pd/TunnelPool.cpp | 3 ++- 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 49176a93..40bd8446 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -1405,31 +1405,53 @@ namespace transport return m_BanList.emplace (addr, ts).second; } - boost::asio::ip::address Transports::GetNetworkAddress (std::shared_ptr session) const + boost::asio::ip::address Transports::GetNetworkAddress (const boost::asio::ip::address& addr) const { - if (session) + if (!addr.is_unspecified ()) { - auto networkAddr = session->GetRemoteAddress (); - if (!networkAddr.is_unspecified ()) + if (addr.is_v4 ()) + return boost::asio::ip::network_v4 (addr.to_v4 (), 24).network (); // /24 + else { - if (networkAddr.is_v4 ()) - return boost::asio::ip::network_v4 (networkAddr.to_v4 (), 24).network (); // /24 - else + if (i2p::util::net::IsYggdrasilAddress (addr)) { - if (i2p::util::net::IsYggdrasilAddress (networkAddr)) - { - // change to 2xx range - auto bytes = networkAddr.to_v6 ().to_bytes (); - bytes[0] = 0x02; - return boost::asio::ip::network_v6 (boost::asio::ip::address_v6 (bytes), 64).network (); // /64 - } - return boost::asio::ip::network_v6 (networkAddr.to_v6 (), 56).network (); // /56 + // change to 2xx range + auto bytes = addr.to_v6 ().to_bytes (); + bytes[0] = 0x02; + return boost::asio::ip::network_v6 (boost::asio::ip::address_v6 (bytes), 64).network (); // /64 } + return boost::asio::ip::network_v6 (addr.to_v6 (), 56).network (); // /56 } } return boost::asio::ip::address (); } + boost::asio::ip::address Transports::GetNetworkAddress (std::shared_ptr session) const + { + if (session) + return GetNetworkAddress (session->GetRemoteAddress ()); + return boost::asio::ip::address (); + } + + bool Transports::IsTooManyConnectionsFromSubnet (std::shared_ptr r) const + { + if (!r && !IsCheckReserved ()) return false; + auto addresses = r->GetAddresses (); + if (!addresses) return false; + for (auto& address : *addresses) + if (address && !address->host.is_unspecified ()) + { + auto networkAddr = GetNetworkAddress (address->host); + if (!networkAddr.is_unspecified ()) + { + std::lock_guard l( m_ConnectedNetworksMutex); + auto it = m_ConnectedNetworks.find (networkAddr); + if (it != m_ConnectedNetworks.end () && it->second > MAX_NUM_CONNECTIONS_FROM_SUBNET_FOR_PEER) return true; + } + } + return false; + } + void InitAddressFromIface () { bool ipv6; i2p::config::GetOption("ipv6", ipv6); diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index 5aab25d8..90cca0c6 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -199,6 +199,8 @@ namespace transport bool IsBanned (const boost::asio::ip::address& addr); bool AddBan (const boost::asio::ip::address& addr); + bool IsTooManyConnectionsFromSubnet (std::shared_ptr r) const; + private: void Run (); @@ -218,6 +220,7 @@ namespace transport template std::shared_ptr GetRandomPeer (Filter filter) const; boost::asio::ip::address GetNetworkAddress (std::shared_ptr session) const; + boost::asio::ip::address GetNetworkAddress (const boost::asio::ip::address& addr) const; private: diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index f8a1f3a7..e9e71ca4 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -578,7 +578,8 @@ namespace tunnel i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint, false); if (hop) { - if (!hop->HasProfile () || !hop->GetProfile ()->IsBad ()) + if ((!hop->HasProfile () || !hop->GetProfile ()->IsBad ()) && + (prevHop != i2p::context.GetSharedRouterInfo () || !i2p::transport::transports.IsTooManyConnectionsFromSubnet (hop))) break; } else if (tryClient)