From 74a7e670027111c19492faddd2418d9928728b52 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 17 Jun 2016 11:03:33 -0400 Subject: [PATCH] implement restricted routes (initial) --- Config.cpp | 10 ++++++++-- Daemon.cpp | 16 ++++++++++++++-- NetDb.cpp | 10 +++++++++- NetDb.h | 5 +++-- RouterInfo.cpp | 6 +++++- RouterInfo.h | 3 +++ Transports.cpp | 24 ++++++++++++++++++++++++ Transports.h | 11 +++++++++++ TunnelPool.cpp | 12 ++++++++++-- 9 files changed, 87 insertions(+), 10 deletions(-) diff --git a/Config.cpp b/Config.cpp index e6d44d59..3ad8e1da 100644 --- a/Config.cpp +++ b/Config.cpp @@ -205,7 +205,12 @@ namespace config { #endif "Enable or disable elgamal precomputation table") ; - + + options_description trust("Trust options"); + trust.add_options() + ("trust.enabled", value()->default_value(false), "enable explicit trust options") + ("trust.family", value()->default_value(""), "Router Familiy to trust for first hops"); + m_OptionsDesc .add(general) .add(limits) @@ -216,7 +221,8 @@ namespace config { .add(bob) .add(i2cp) .add(i2pcontrol) - .add(precomputation) + .add(precomputation) + .add(trust) ; } diff --git a/Daemon.cpp b/Daemon.cpp index 7ca28a6f..3cd0efcb 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -192,7 +192,19 @@ namespace i2p i2p::context.SetFamily (family); if (family.length () > 0) LogPrint(eLogInfo, "Daemon: family set to ", family); - + + bool trust; i2p::config::GetOption("trust.enabled", trust); + if (trust) + { + LogPrint(eLogInfo, "Daemon: explicit trust enabled"); + std::string fam; i2p::config::GetOption("trust.family", fam); + if (fam.length() > 0) + { + LogPrint(eLogInfo, "Daemon: setting restricted routes to use family ", fam); + i2p::transport::transports.RestrictRoutes({fam}); + } else + LogPrint(eLogError, "Daemon: no family specified for restricted routes"); + } return true; } @@ -215,7 +227,7 @@ namespace i2p d.m_UPnP.Start (); #endif LogPrint(eLogInfo, "Daemon: starting Transports"); - i2p::transport::transports.Start(); + i2p::transport::transports.Start(); LogPrint(eLogInfo, "Daemon: starting Tunnels"); i2p::tunnel::tunnels.Start(); diff --git a/NetDb.cpp b/NetDb.cpp index d2afc50a..7c3983a9 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -851,7 +851,7 @@ namespace data { if (m_RouterInfos.empty()) return 0; - uint32_t ind = rand () % m_RouterInfos.size (); + uint32_t ind = rand () % m_RouterInfos.size (); for (int j = 0; j < 2; j++) { uint32_t i = 0; @@ -955,6 +955,14 @@ namespace data return res; } + std::shared_ptr NetDb::GetRandomRouterInFamily(const std::string & fam) const { + return GetRandomRouter( + [fam](std::shared_ptr router)->bool + { + return router->IsFamily(fam); + }); + } + std::shared_ptr NetDb::GetClosestNonFloodfill (const IdentHash& destination, const std::set& excluded) const { diff --git a/NetDb.h b/NetDb.h index 1c062358..96308ee7 100644 --- a/NetDb.h +++ b/NetDb.h @@ -62,6 +62,7 @@ namespace data std::vector GetClosestFloodfills (const IdentHash& destination, size_t num, std::set& excluded, bool closeThanUsOnly = false) const; std::shared_ptr GetClosestNonFloodfill (const IdentHash& destination, const std::set& excluded) const; + std::shared_ptr GetRandomRouterInFamily(const std::string & fam) const; void SetUnreachable (const IdentHash& ident, bool unreachable); void PostI2NPMsg (std::shared_ptr msg); @@ -86,8 +87,8 @@ namespace data void ManageRequests (); void ManageLookupResponses (); - template - std::shared_ptr GetRandomRouter (Filter filter) const; + template + std::shared_ptr GetRandomRouter (Filter filter) const; private: diff --git a/RouterInfo.cpp b/RouterInfo.cpp index 0ef2f623..3462d7d8 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -290,7 +290,11 @@ namespace data if (!m_SupportedTransports || !m_Addresses.size() || (UsesIntroducer () && !introducers)) SetUnreachable (true); - } + } + + bool RouterInfo::IsFamily(const std::string & fam) const { + return m_Family == fam; + } void RouterInfo::ExtractCaps (const char * value) { diff --git a/RouterInfo.h b/RouterInfo.h index a55924a8..8c8af691 100644 --- a/RouterInfo.h +++ b/RouterInfo.h @@ -171,6 +171,9 @@ namespace data void DeleteBuffer () { delete[] m_Buffer; m_Buffer = nullptr; }; bool IsNewer (const uint8_t * buf, size_t len) const; + /** return true if we are in a router family and the signature is valid */ + bool IsFamily(const std::string & fam) const; + // implements RoutingDestination const IdentHash& GetIdentHash () const { return m_RouterIdentity->GetIdentHash (); }; const uint8_t * GetEncryptionPublicKey () const { return m_RouterIdentity->GetStandardIdentity ().publicKey; }; diff --git a/Transports.cpp b/Transports.cpp index 2d3d423f..e9046966 100644 --- a/Transports.cpp +++ b/Transports.cpp @@ -612,6 +612,30 @@ namespace transport std::advance (it, rand () % m_Peers.size ()); return it != m_Peers.end () ? it->second.router : nullptr; } + void Transports::RestrictRoutes(std::vector families) + { + std::lock_guard lock(m_FamilyMutex); + m_TrustedFamilies.clear(); + for ( auto fam : families ) + m_TrustedFamilies.push_back(fam); + } + + bool Transports::RoutesRestricted() const { + std::lock_guard lock(m_FamilyMutex); + return m_TrustedFamilies.size() > 0; + } + + /** XXX: if routes are not restricted this dies */ + std::shared_ptr Transports::GetRestrictedPeer() const { + std::string fam; + { + std::lock_guard lock(m_FamilyMutex); + // TODO: random family (?) + fam = m_TrustedFamilies[0]; + } + boost::to_lower(fam); + return i2p::data::netdb.GetRandomRouterInFamily(fam); + } } } diff --git a/Transports.h b/Transports.h index 3bfe1f8b..6071d6b8 100644 --- a/Transports.h +++ b/Transports.h @@ -98,6 +98,13 @@ namespace transport size_t GetNumPeers () const { return m_Peers.size (); }; std::shared_ptr GetRandomPeer () const; + /** get a trusted first hop for restricted routes */ + std::shared_ptr GetRestrictedPeer() const; + /** do we want to use restricted routes? */ + bool RoutesRestricted() const; + /** restrict routes to use only these router families for first hops */ + void RestrictRoutes(std::vector families); + void PeerTest (); private: @@ -140,6 +147,10 @@ namespace transport uint64_t m_LastInBandwidthUpdateBytes, m_LastOutBandwidthUpdateBytes; uint64_t m_LastBandwidthUpdateTime; + /** which router families to trust for first hops */ + std::vector m_TrustedFamilies; + mutable std::mutex m_FamilyMutex; + public: // for HTTP only diff --git a/TunnelPool.cpp b/TunnelPool.cpp index 5e7e8ec4..8b4e33fe 100644 --- a/TunnelPool.cpp +++ b/TunnelPool.cpp @@ -331,9 +331,10 @@ namespace tunnel if (m_ExplicitPeers) return SelectExplicitPeers (peers, isInbound); auto prevHop = i2p::context.GetSharedRouterInfo (); int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops; + int firstHop = numHops - 1; if (i2p::transport::transports.GetNumPeers () > 25) { - auto r = i2p::transport::transports.GetRandomPeer (); + auto r = i2p::transport::transports.GetRandomPeer (); if (r && !r->GetProfile ()->IsBad ()) { prevHop = r; @@ -352,7 +353,14 @@ namespace tunnel } prevHop = hop; peers.push_back (hop->GetRouterIdentity ()); - } + } + if(i2p::transport::transports.RoutesRestricted()) + { + auto r = i2p::transport::transports.GetRestrictedPeer(); + /* replace first hop with restricted router */ + if(!r) return false; + peers[firstHop] = r->GetRouterIdentity(); + } return true; }