mirror of
https://github.com/PurpleI2P/i2pd
synced 2024-11-10 00:00:29 +03:00
[transports] validate IP when trying connect to remote peer for being in reserved IP range
Signed-off-by: R4SAS <r4sas@i2pmail.org>
This commit is contained in:
parent
99d046ca11
commit
85e9da82b0
@ -299,14 +299,16 @@ namespace i2p
|
||||
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||
bool checkInReserved; i2p::config::GetOption("reservedrange", checkInReserved);
|
||||
LogPrint(eLogInfo, "Daemon: starting Transports");
|
||||
if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled");
|
||||
if(!ntcp2) LogPrint(eLogInfo, "Daemon: ntcp2 disabled");
|
||||
|
||||
i2p::transport::transports.SetCheckReserved(checkInReserved);
|
||||
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");
|
||||
else
|
||||
else
|
||||
{
|
||||
LogPrint(eLogError, "Daemon: failed to start Transports");
|
||||
/** shut down netdb right away */
|
||||
|
@ -51,6 +51,7 @@ namespace config {
|
||||
("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)")
|
||||
("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")
|
||||
("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)")
|
||||
|
@ -459,6 +459,7 @@ namespace transport
|
||||
// otherwise create new session
|
||||
auto session = std::make_shared<SSUSession> (*this, remoteEndpoint, router, peerTest);
|
||||
sessions[remoteEndpoint] = session;
|
||||
|
||||
// connect
|
||||
LogPrint (eLogDebug, "SSU: Creating new session to [", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), "] ",
|
||||
remoteEndpoint.address ().to_string (), ":", remoteEndpoint.port ());
|
||||
|
@ -27,20 +27,20 @@ namespace transport
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Keys>
|
||||
template<typename Keys>
|
||||
EphemeralKeysSupplier<Keys>::~EphemeralKeysSupplier ()
|
||||
{
|
||||
Stop ();
|
||||
}
|
||||
|
||||
template<typename Keys>
|
||||
template<typename Keys>
|
||||
void EphemeralKeysSupplier<Keys>::Start ()
|
||||
{
|
||||
m_IsRunning = true;
|
||||
m_Thread = new std::thread (std::bind (&EphemeralKeysSupplier<Keys>::Run, this));
|
||||
}
|
||||
|
||||
template<typename Keys>
|
||||
template<typename Keys>
|
||||
void EphemeralKeysSupplier<Keys>::Stop ()
|
||||
{
|
||||
{
|
||||
@ -56,7 +56,7 @@ namespace transport
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Keys>
|
||||
template<typename Keys>
|
||||
void EphemeralKeysSupplier<Keys>::Run ()
|
||||
{
|
||||
while (m_IsRunning)
|
||||
@ -81,7 +81,7 @@ namespace transport
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Keys>
|
||||
template<typename Keys>
|
||||
void EphemeralKeysSupplier<Keys>::CreateEphemeralKeys (int num)
|
||||
{
|
||||
if (num > 0)
|
||||
@ -96,7 +96,7 @@ namespace transport
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Keys>
|
||||
template<typename Keys>
|
||||
std::shared_ptr<Keys> EphemeralKeysSupplier<Keys>::Acquire ()
|
||||
{
|
||||
{
|
||||
@ -115,7 +115,7 @@ namespace transport
|
||||
return pair;
|
||||
}
|
||||
|
||||
template<typename Keys>
|
||||
template<typename Keys>
|
||||
void EphemeralKeysSupplier<Keys>::Return (std::shared_ptr<Keys> pair)
|
||||
{
|
||||
if (pair)
|
||||
@ -131,8 +131,8 @@ namespace transport
|
||||
Transports transports;
|
||||
|
||||
Transports::Transports ():
|
||||
m_IsOnline (true), m_IsRunning (false), m_IsNAT (true), m_Thread (nullptr), m_Service (nullptr),
|
||||
m_Work (nullptr), m_PeerCleanupTimer (nullptr), m_PeerTestTimer (nullptr),
|
||||
m_IsOnline (true), m_IsRunning (false), m_IsNAT (true), m_СheckReserved(true), m_Thread (nullptr),
|
||||
m_Service (nullptr), m_Work (nullptr), m_PeerCleanupTimer (nullptr), m_PeerTestTimer (nullptr),
|
||||
m_SSUServer (nullptr), m_NTCP2Server (nullptr),
|
||||
m_DHKeysPairSupplier (5), m_X25519KeysPairSupplier (5), // 5 pre-generated keys
|
||||
m_TotalSentBytes(0), m_TotalReceivedBytes(0), m_TotalTransitTransmittedBytes (0),
|
||||
@ -170,7 +170,7 @@ namespace transport
|
||||
m_IsRunning = true;
|
||||
m_Thread = new std::thread (std::bind (&Transports::Run, this));
|
||||
std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy);
|
||||
i2p::http::URL proxyurl;
|
||||
i2p::http::URL proxyurl;
|
||||
// create NTCP2. TODO: move to acceptor
|
||||
if (enableNTCP2)
|
||||
{
|
||||
@ -252,7 +252,7 @@ namespace transport
|
||||
delete m_SSUServer;
|
||||
m_SSUServer = nullptr;
|
||||
}
|
||||
|
||||
|
||||
if (m_NTCP2Server)
|
||||
{
|
||||
m_NTCP2Server->Stop ();
|
||||
@ -372,7 +372,7 @@ namespace transport
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "Transports: delayed messages queue size to ",
|
||||
LogPrint (eLogWarning, "Transports: delayed messages queue size to ",
|
||||
ident.ToBase64 (), " exceeds ", MAX_NUM_DELAYED_MESSAGES);
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
m_Peers.erase (it);
|
||||
@ -393,7 +393,7 @@ namespace transport
|
||||
{
|
||||
// NTCP2 have priority over NTCP
|
||||
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);
|
||||
|
||||
@ -419,8 +419,11 @@ namespace transport
|
||||
if (m_SSUServer && peer.router->IsSSU (!context.SupportsV6 ()))
|
||||
{
|
||||
auto address = peer.router->GetSSUAddress (!context.SupportsV6 ());
|
||||
m_SSUServer->CreateSession (peer.router, address->host, address->port);
|
||||
return true;
|
||||
if (!m_СheckReserved || !i2p::util::net::IsInReservedRange(address->host))
|
||||
{
|
||||
m_SSUServer->CreateSession (peer.router, address->host, address->port);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
LogPrint (eLogInfo, "Transports: No NTCP or SSU addresses available");
|
||||
@ -556,7 +559,7 @@ namespace transport
|
||||
{
|
||||
m_X25519KeysPairSupplier.Return (pair);
|
||||
}
|
||||
|
||||
|
||||
void Transports::PeerConnected (std::shared_ptr<TransportSession> session)
|
||||
{
|
||||
m_Service->post([session, this]()
|
||||
@ -758,16 +761,16 @@ namespace transport
|
||||
return false;
|
||||
}
|
||||
|
||||
void Transports::SetOnline (bool online)
|
||||
{
|
||||
void Transports::SetOnline (bool online)
|
||||
{
|
||||
if (m_IsOnline != online)
|
||||
{
|
||||
m_IsOnline = online;
|
||||
{
|
||||
m_IsOnline = online;
|
||||
if (online)
|
||||
PeerTest ();
|
||||
else
|
||||
i2p::context.SetError (eRouterErrorOffline);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -136,6 +136,9 @@ namespace transport
|
||||
|
||||
void PeerTest ();
|
||||
|
||||
void SetCheckReserved (bool check) { m_СheckReserved = check; };
|
||||
bool IsCheckReserved () { return m_СheckReserved; };
|
||||
|
||||
private:
|
||||
|
||||
void Run ();
|
||||
@ -152,7 +155,7 @@ namespace transport
|
||||
private:
|
||||
|
||||
volatile bool m_IsOnline;
|
||||
bool m_IsRunning, m_IsNAT;
|
||||
bool m_IsRunning, m_IsNAT, m_СheckReserved;
|
||||
std::thread * m_Thread;
|
||||
boost::asio::io_service * m_Service;
|
||||
boost::asio::io_service::work * m_Work;
|
||||
|
@ -61,6 +61,9 @@ int inet_pton_xp(int af, const char *src, void *dst)
|
||||
#include <ifaddrs.h>
|
||||
#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 util
|
||||
@ -391,6 +394,50 @@ namespace net
|
||||
return boost::asio::ip::address::from_string(fallback);
|
||||
#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
|
||||
} // i2p
|
||||
|
@ -172,6 +172,7 @@ namespace util
|
||||
{
|
||||
int GetMTU (const boost::asio::ip::address& localAddress);
|
||||
const boost::asio::ip::address GetInterfaceAddress(const std::string & ifname, bool ipv6=false);
|
||||
bool IsInReservedRange(const boost::asio::ip::address& host);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user