Browse Source

[transports] validate IP when trying connect to remote peer for being in reserved IP range

Signed-off-by: R4SAS <r4sas@i2pmail.org>
pull/1559/head
R4SAS 4 years ago committed by R4SAS
parent
commit
85e9da82b0
  1. 6
      daemon/Daemon.cpp
  2. 1
      libi2pd/Config.cpp
  3. 1
      libi2pd/SSU.cpp
  4. 47
      libi2pd/Transports.cpp
  5. 5
      libi2pd/Transports.h
  6. 49
      libi2pd/util.cpp
  7. 1
      libi2pd/util.h

6
daemon/Daemon.cpp

@ -299,14 +299,16 @@ namespace i2p
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
bool ssu; i2p::config::GetOption("ssu", ssu); bool ssu; i2p::config::GetOption("ssu", ssu);
bool checkInReserved; i2p::config::GetOption("reservedrange", checkInReserved);
LogPrint(eLogInfo, "Daemon: starting Transports"); LogPrint(eLogInfo, "Daemon: starting Transports");
if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled"); if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled");
if(!ntcp2) LogPrint(eLogInfo, "Daemon: ntcp2 disabled"); if(!ntcp2) LogPrint(eLogInfo, "Daemon: ntcp2 disabled");
i2p::transport::transports.SetCheckReserved(checkInReserved);
i2p::transport::transports.Start(ntcp2, ssu); i2p::transport::transports.Start(ntcp2, ssu);
if (i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2()) if (i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
LogPrint(eLogInfo, "Daemon: Transports started"); LogPrint(eLogInfo, "Daemon: Transports started");
else else
{ {
LogPrint(eLogError, "Daemon: failed to start Transports"); LogPrint(eLogError, "Daemon: failed to start Transports");
/** shut down netdb right away */ /** shut down netdb right away */

1
libi2pd/Config.cpp

@ -51,6 +51,7 @@ namespace config {
("port", value<uint16_t>()->default_value(0), "Port to listen for incoming connections (default: auto)") ("port", value<uint16_t>()->default_value(0), "Port to listen for incoming connections (default: auto)")
("ipv4", value<bool>()->default_value(true), "Enable communication through ipv4 (default: enabled)") ("ipv4", value<bool>()->default_value(true), "Enable communication through ipv4 (default: enabled)")
("ipv6", bool_switch()->default_value(false), "Enable communication through ipv6 (default: disabled)") ("ipv6", bool_switch()->default_value(false), "Enable communication through ipv6 (default: disabled)")
("reservedrange", value<bool>()->default_value(true), "Check remote RI for being in blacklist of reserved IP ranges (default: enabled)")
("netid", value<int>()->default_value(I2PD_NET_ID), "Specify NetID. Main I2P is 2") ("netid", value<int>()->default_value(I2PD_NET_ID), "Specify NetID. Main I2P is 2")
("daemon", bool_switch()->default_value(false), "Router will go to background after start (default: disabled)") ("daemon", bool_switch()->default_value(false), "Router will go to background after start (default: disabled)")
("service", bool_switch()->default_value(false), "Router will use system folders like '/var/lib/i2pd' (default: disabled)") ("service", bool_switch()->default_value(false), "Router will use system folders like '/var/lib/i2pd' (default: disabled)")

1
libi2pd/SSU.cpp

@ -459,6 +459,7 @@ namespace transport
// otherwise create new session // otherwise create new session
auto session = std::make_shared<SSUSession> (*this, remoteEndpoint, router, peerTest); auto session = std::make_shared<SSUSession> (*this, remoteEndpoint, router, peerTest);
sessions[remoteEndpoint] = session; sessions[remoteEndpoint] = session;
// connect // connect
LogPrint (eLogDebug, "SSU: Creating new session to [", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), "] ", LogPrint (eLogDebug, "SSU: Creating new session to [", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), "] ",
remoteEndpoint.address ().to_string (), ":", remoteEndpoint.port ()); remoteEndpoint.address ().to_string (), ":", remoteEndpoint.port ());

47
libi2pd/Transports.cpp

@ -27,20 +27,20 @@ namespace transport
{ {
} }
template<typename Keys> template<typename Keys>
EphemeralKeysSupplier<Keys>::~EphemeralKeysSupplier () EphemeralKeysSupplier<Keys>::~EphemeralKeysSupplier ()
{ {
Stop (); Stop ();
} }
template<typename Keys> template<typename Keys>
void EphemeralKeysSupplier<Keys>::Start () void EphemeralKeysSupplier<Keys>::Start ()
{ {
m_IsRunning = true; m_IsRunning = true;
m_Thread = new std::thread (std::bind (&EphemeralKeysSupplier<Keys>::Run, this)); m_Thread = new std::thread (std::bind (&EphemeralKeysSupplier<Keys>::Run, this));
} }
template<typename Keys> template<typename Keys>
void EphemeralKeysSupplier<Keys>::Stop () void EphemeralKeysSupplier<Keys>::Stop ()
{ {
{ {
@ -56,7 +56,7 @@ namespace transport
} }
} }
template<typename Keys> template<typename Keys>
void EphemeralKeysSupplier<Keys>::Run () void EphemeralKeysSupplier<Keys>::Run ()
{ {
while (m_IsRunning) while (m_IsRunning)
@ -81,7 +81,7 @@ namespace transport
} }
} }
template<typename Keys> template<typename Keys>
void EphemeralKeysSupplier<Keys>::CreateEphemeralKeys (int num) void EphemeralKeysSupplier<Keys>::CreateEphemeralKeys (int num)
{ {
if (num > 0) if (num > 0)
@ -96,7 +96,7 @@ namespace transport
} }
} }
template<typename Keys> template<typename Keys>
std::shared_ptr<Keys> EphemeralKeysSupplier<Keys>::Acquire () std::shared_ptr<Keys> EphemeralKeysSupplier<Keys>::Acquire ()
{ {
{ {
@ -115,7 +115,7 @@ namespace transport
return pair; return pair;
} }
template<typename Keys> template<typename Keys>
void EphemeralKeysSupplier<Keys>::Return (std::shared_ptr<Keys> pair) void EphemeralKeysSupplier<Keys>::Return (std::shared_ptr<Keys> pair)
{ {
if (pair) if (pair)
@ -131,8 +131,8 @@ namespace transport
Transports transports; Transports transports;
Transports::Transports (): Transports::Transports ():
m_IsOnline (true), m_IsRunning (false), m_IsNAT (true), m_Thread (nullptr), m_Service (nullptr), m_IsOnline (true), m_IsRunning (false), m_IsNAT (true), m_СheckReserved(true), m_Thread (nullptr),
m_Work (nullptr), m_PeerCleanupTimer (nullptr), m_PeerTestTimer (nullptr), m_Service (nullptr), m_Work (nullptr), m_PeerCleanupTimer (nullptr), m_PeerTestTimer (nullptr),
m_SSUServer (nullptr), m_NTCP2Server (nullptr), m_SSUServer (nullptr), m_NTCP2Server (nullptr),
m_DHKeysPairSupplier (5), m_X25519KeysPairSupplier (5), // 5 pre-generated keys m_DHKeysPairSupplier (5), m_X25519KeysPairSupplier (5), // 5 pre-generated keys
m_TotalSentBytes(0), m_TotalReceivedBytes(0), m_TotalTransitTransmittedBytes (0), m_TotalSentBytes(0), m_TotalReceivedBytes(0), m_TotalTransitTransmittedBytes (0),
@ -170,7 +170,7 @@ namespace transport
m_IsRunning = true; m_IsRunning = true;
m_Thread = new std::thread (std::bind (&Transports::Run, this)); m_Thread = new std::thread (std::bind (&Transports::Run, this));
std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy); std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy);
i2p::http::URL proxyurl; i2p::http::URL proxyurl;
// create NTCP2. TODO: move to acceptor // create NTCP2. TODO: move to acceptor
if (enableNTCP2) if (enableNTCP2)
{ {
@ -252,7 +252,7 @@ namespace transport
delete m_SSUServer; delete m_SSUServer;
m_SSUServer = nullptr; m_SSUServer = nullptr;
} }
if (m_NTCP2Server) if (m_NTCP2Server)
{ {
m_NTCP2Server->Stop (); m_NTCP2Server->Stop ();
@ -372,7 +372,7 @@ namespace transport
} }
else else
{ {
LogPrint (eLogWarning, "Transports: delayed messages queue size to ", LogPrint (eLogWarning, "Transports: delayed messages queue size to ",
ident.ToBase64 (), " exceeds ", MAX_NUM_DELAYED_MESSAGES); ident.ToBase64 (), " exceeds ", MAX_NUM_DELAYED_MESSAGES);
std::unique_lock<std::mutex> l(m_PeersMutex); std::unique_lock<std::mutex> l(m_PeersMutex);
m_Peers.erase (it); m_Peers.erase (it);
@ -393,7 +393,7 @@ namespace transport
{ {
// NTCP2 have priority over NTCP // NTCP2 have priority over NTCP
auto address = peer.router->GetNTCP2Address (true, !context.SupportsV6 ()); // published only auto address = peer.router->GetNTCP2Address (true, !context.SupportsV6 ()); // published only
if (address && !peer.router->IsUnreachable ()) if (address && !peer.router->IsUnreachable () && (!m_СheckReserved || !i2p::util::net::IsInReservedRange(address->host)))
{ {
auto s = std::make_shared<NTCP2Session> (*m_NTCP2Server, peer.router); auto s = std::make_shared<NTCP2Session> (*m_NTCP2Server, peer.router);
@ -419,8 +419,11 @@ namespace transport
if (m_SSUServer && peer.router->IsSSU (!context.SupportsV6 ())) if (m_SSUServer && peer.router->IsSSU (!context.SupportsV6 ()))
{ {
auto address = peer.router->GetSSUAddress (!context.SupportsV6 ()); auto address = peer.router->GetSSUAddress (!context.SupportsV6 ());
m_SSUServer->CreateSession (peer.router, address->host, address->port); if (!m_СheckReserved || !i2p::util::net::IsInReservedRange(address->host))
return true; {
m_SSUServer->CreateSession (peer.router, address->host, address->port);
return true;
}
} }
} }
LogPrint (eLogInfo, "Transports: No NTCP or SSU addresses available"); LogPrint (eLogInfo, "Transports: No NTCP or SSU addresses available");
@ -556,7 +559,7 @@ namespace transport
{ {
m_X25519KeysPairSupplier.Return (pair); m_X25519KeysPairSupplier.Return (pair);
} }
void Transports::PeerConnected (std::shared_ptr<TransportSession> session) void Transports::PeerConnected (std::shared_ptr<TransportSession> session)
{ {
m_Service->post([session, this]() m_Service->post([session, this]()
@ -758,16 +761,16 @@ namespace transport
return false; return false;
} }
void Transports::SetOnline (bool online) void Transports::SetOnline (bool online)
{ {
if (m_IsOnline != online) if (m_IsOnline != online)
{ {
m_IsOnline = online; m_IsOnline = online;
if (online) if (online)
PeerTest (); PeerTest ();
else else
i2p::context.SetError (eRouterErrorOffline); i2p::context.SetError (eRouterErrorOffline);
} }
} }
} }
} }

5
libi2pd/Transports.h

@ -136,6 +136,9 @@ namespace transport
void PeerTest (); void PeerTest ();
void SetCheckReserved (bool check) { m_СheckReserved = check; };
bool IsCheckReserved () { return m_СheckReserved; };
private: private:
void Run (); void Run ();
@ -152,7 +155,7 @@ namespace transport
private: private:
volatile bool m_IsOnline; volatile bool m_IsOnline;
bool m_IsRunning, m_IsNAT; bool m_IsRunning, m_IsNAT, m_СheckReserved;
std::thread * m_Thread; std::thread * m_Thread;
boost::asio::io_service * m_Service; boost::asio::io_service * m_Service;
boost::asio::io_service::work * m_Work; boost::asio::io_service::work * m_Work;

49
libi2pd/util.cpp

@ -61,6 +61,9 @@ int inet_pton_xp(int af, const char *src, void *dst)
#include <ifaddrs.h> #include <ifaddrs.h>
#endif #endif
#define address_pair_v4(a,b) { boost::asio::ip::address_v4::from_string (a).to_ulong (), boost::asio::ip::address_v4::from_string (b).to_ulong () }
#define address_pair_v6(a,b) { boost::asio::ip::address_v6::from_string (a).to_bytes (), boost::asio::ip::address_v6::from_string (b).to_bytes () }
namespace i2p namespace i2p
{ {
namespace util namespace util
@ -391,6 +394,50 @@ namespace net
return boost::asio::ip::address::from_string(fallback); return boost::asio::ip::address::from_string(fallback);
#endif #endif
} }
}
bool IsInReservedRange(const boost::asio::ip::address& host) {
// https://en.wikipedia.org/wiki/Reserved_IP_addresses
if(host.is_v4())
{
static const std::vector< std::pair<uint32_t, uint32_t> > reservedIPv4Ranges {
address_pair_v4("0.0.0.0", "0.255.255.255"),
address_pair_v4("10.0.0.0", "10.255.255.255"),
address_pair_v4("100.64.0.0", "100.127.255.255"),
address_pair_v4("127.0.0.0", "127.255.255.255"),
address_pair_v4("169.254.0.0", "169.254.255.255"),
address_pair_v4("172.16.0.0", "172.31.255.255"),
address_pair_v4("192.0.0.0", "192.0.0.255"),
address_pair_v4("192.0.2.0", "192.0.2.255"),
address_pair_v4("192.88.99.0", "192.88.99.255"),
address_pair_v4("192.168.0.0", "192.168.255.255"),
address_pair_v4("198.18.0.0", "192.19.255.255"),
address_pair_v4("198.51.100.0", "198.51.100.255"),
address_pair_v4("203.0.113.0", "203.0.113.255"),
address_pair_v4("224.0.0.0", "255.255.255.255")
};
uint32_t ipv4_address = host.to_v4 ().to_ulong ();
for(const auto& it : reservedIPv4Ranges) {
if (ipv4_address >= it.first && ipv4_address <= it.second)
return true;
}
}
if(host.is_v6())
{
static const std::vector< std::pair<boost::asio::ip::address_v6::bytes_type, boost::asio::ip::address_v6::bytes_type> > reservedIPv6Ranges {
address_pair_v6("2001:db8::", "2001:db8:ffff:ffff:ffff:ffff:ffff:ffff"),
address_pair_v6("fc00::", "fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"),
address_pair_v6("fe80::", "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
};
boost::asio::ip::address_v6::bytes_type ipv6_address = host.to_v6 ().to_bytes ();
for(const auto& it : reservedIPv6Ranges) {
if (ipv6_address >= it.first && ipv6_address <= it.second)
return true;
}
}
return false;
}
} // net
} // util } // util
} // i2p } // i2p

1
libi2pd/util.h

@ -172,6 +172,7 @@ namespace util
{ {
int GetMTU (const boost::asio::ip::address& localAddress); int GetMTU (const boost::asio::ip::address& localAddress);
const boost::asio::ip::address GetInterfaceAddress(const std::string & ifname, bool ipv6=false); const boost::asio::ip::address GetInterfaceAddress(const std::string & ifname, bool ipv6=false);
bool IsInReservedRange(const boost::asio::ip::address& host);
} }
} }
} }

Loading…
Cancel
Save