mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-04-27 19:27:49 +02:00
ri, transports, binding, reserved ip ranges
This commit is contained in:
parent
743fa745b7
commit
1e91b59f67
7 changed files with 128 additions and 94 deletions
|
@ -14,6 +14,7 @@
|
|||
#include "NTCPSession.h"
|
||||
#include "HTTP.h"
|
||||
#include "util.h"
|
||||
#include "Config.h"
|
||||
#ifdef WITH_EVENTS
|
||||
#include "Event.h"
|
||||
#endif
|
||||
|
@ -815,43 +816,52 @@ namespace transport
|
|||
else
|
||||
{
|
||||
// create acceptors
|
||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||
|
||||
auto& addresses = context.GetRouterInfo ().GetAddresses ();
|
||||
for (const auto& address: addresses)
|
||||
{
|
||||
if (!address) continue;
|
||||
if (address->transportStyle == i2p::data::RouterInfo::eTransportNTCP && !address->IsNTCP2 ())
|
||||
{
|
||||
if (address->host.is_v4())
|
||||
if (address->host.is_v4() && context.SupportsV4 () && ipv4)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_NTCPAcceptor = new boost::asio::ip::tcp::acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), address->port));
|
||||
m_NTCPAcceptor = new boost::asio::ip::tcp::acceptor (m_Service);
|
||||
m_NTCPAcceptor->open (boost::asio::ip::tcp::v4());
|
||||
m_NTCPAcceptor->set_option (boost::asio::socket_base::reuse_address (true));
|
||||
m_NTCPAcceptor->bind (boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), address->port));
|
||||
m_NTCPAcceptor->listen ();
|
||||
|
||||
LogPrint (eLogInfo, "NTCP: Start listening IPv4 TCP port ", address->port);
|
||||
auto conn = std::make_shared<NTCPSession>(*this);
|
||||
m_NTCPAcceptor->async_accept(conn->GetSocket (), std::bind (&NTCPServer::HandleAccept, this, conn, std::placeholders::_1));
|
||||
} catch ( std::exception & ex ) {
|
||||
/** fail to bind ip4 */
|
||||
LogPrint(eLogError, "NTCP: Failed to bind to ip4 port ",address->port, ex.what());
|
||||
/** fail to bind IPv4 */
|
||||
LogPrint(eLogError, "NTCP: Failed to bind to IPv4 port ",address->port, ex.what());
|
||||
continue;
|
||||
}
|
||||
|
||||
LogPrint (eLogInfo, "NTCP: Start listening TCP port ", address->port);
|
||||
auto conn = std::make_shared<NTCPSession>(*this);
|
||||
m_NTCPAcceptor->async_accept(conn->GetSocket (), std::bind (&NTCPServer::HandleAccept, this, conn, std::placeholders::_1));
|
||||
}
|
||||
else if (address->host.is_v6() && context.SupportsV6 ())
|
||||
else if (address->host.is_v6() && context.SupportsV6 () && ipv6)
|
||||
{
|
||||
m_NTCPV6Acceptor = new boost::asio::ip::tcp::acceptor (m_Service);
|
||||
try
|
||||
{
|
||||
m_NTCPV6Acceptor = new boost::asio::ip::tcp::acceptor (m_Service);
|
||||
m_NTCPV6Acceptor->open (boost::asio::ip::tcp::v6());
|
||||
m_NTCPV6Acceptor->set_option (boost::asio::ip::v6_only (true));
|
||||
m_NTCPV6Acceptor->set_option (boost::asio::socket_base::reuse_address (true));
|
||||
m_NTCPV6Acceptor->bind (boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), address->port));
|
||||
m_NTCPV6Acceptor->listen ();
|
||||
|
||||
LogPrint (eLogInfo, "NTCP: Start listening V6 TCP port ", address->port);
|
||||
LogPrint (eLogInfo, "NTCP: Start listening IPv6 TCP port ", address->port);
|
||||
auto conn = std::make_shared<NTCPSession> (*this);
|
||||
m_NTCPV6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCPServer::HandleAcceptV6, this, conn, std::placeholders::_1));
|
||||
} catch ( std::exception & ex ) {
|
||||
LogPrint(eLogError, "NTCP: failed to bind to ip6 port ", address->port);
|
||||
/** fail to bind IPv6 */
|
||||
LogPrint(eLogError, "NTCP: failed to bind to IPv6 port ", address->port);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -570,8 +570,10 @@ namespace i2p
|
|||
|
||||
bool RouterContext::Load ()
|
||||
{
|
||||
// read router keys
|
||||
std::ifstream fk (i2p::fs::DataDirPath (ROUTER_KEYS), std::ifstream::in | std::ifstream::binary);
|
||||
if (!fk.is_open ()) return false;
|
||||
if (!fk.is_open ())
|
||||
return false;
|
||||
fk.seekg (0, std::ios::end);
|
||||
size_t len = fk.tellg();
|
||||
fk.seekg (0, std::ios::beg);
|
||||
|
@ -589,6 +591,8 @@ namespace i2p
|
|||
m_Keys.FromBuffer (buf, len);
|
||||
delete[] buf;
|
||||
}
|
||||
fk.close();
|
||||
|
||||
// read NTCP2 keys if available
|
||||
std::ifstream n2k (i2p::fs::DataDirPath (NTCP2_KEYS), std::ifstream::in | std::ifstream::binary);
|
||||
if (n2k)
|
||||
|
@ -603,6 +607,7 @@ namespace i2p
|
|||
}
|
||||
n2k.close ();
|
||||
}
|
||||
|
||||
// read RouterInfo
|
||||
m_RouterInfo.SetRouterIdentity (GetIdentity ());
|
||||
i2p::data::RouterInfo routerInfo(i2p::fs::DataDirPath (ROUTER_INFO));
|
||||
|
@ -615,6 +620,11 @@ namespace i2p
|
|||
// Migration to 0.9.24. TODO: remove later
|
||||
m_RouterInfo.DeleteProperty ("coreVersion");
|
||||
m_RouterInfo.DeleteProperty ("stat_uptime");
|
||||
|
||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||
SetSupportsV4(ipv4);
|
||||
SetSupportsV6(ipv6);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -245,13 +245,15 @@ namespace data
|
|||
ExtractCaps (value);
|
||||
else if (!strcmp (key, "s")) // ntcp2 static key
|
||||
{
|
||||
if (!address->ntcp2) address->ntcp2.reset (new NTCP2Ext ());
|
||||
if (!address->ntcp2)
|
||||
address->ntcp2.reset (new NTCP2Ext ());
|
||||
supportedTransports |= (address->host.is_v4 ()) ? eNTCP2V4 : eNTCP2V6;
|
||||
Base64ToByteStream (value, strlen (value), address->ntcp2->staticKey, 32);
|
||||
}
|
||||
else if (!strcmp (key, "i")) // ntcp2 iv
|
||||
{
|
||||
if (!address->ntcp2) address->ntcp2.reset (new NTCP2Ext ());
|
||||
if (!address->ntcp2)
|
||||
address->ntcp2.reset (new NTCP2Ext ());
|
||||
supportedTransports |= (address->host.is_v4 ()) ? eNTCP2V4 : eNTCP2V6;
|
||||
Base64ToByteStream (value, strlen (value), address->ntcp2->iv, 16);
|
||||
address->ntcp2->isPublished = true; // presence if "i" means "published"
|
||||
|
@ -292,8 +294,10 @@ namespace data
|
|||
}
|
||||
if (!s) return;
|
||||
}
|
||||
if (introducers) supportedTransports |= eSSUV4; // in case if host is not presented
|
||||
if (isNTCP2Only && address->ntcp2) address->ntcp2->isNTCP2Only = true;
|
||||
if (introducers)
|
||||
supportedTransports |= eSSUV4; // in case if host is not presented
|
||||
if (isNTCP2Only && address->ntcp2)
|
||||
address->ntcp2->isNTCP2Only = true;
|
||||
if (supportedTransports)
|
||||
{
|
||||
addresses->push_back(address);
|
||||
|
@ -799,7 +803,7 @@ namespace data
|
|||
|
||||
bool RouterInfo::IsV6 () const
|
||||
{
|
||||
return m_SupportedTransports & (eNTCPV6 | eSSUV6);
|
||||
return m_SupportedTransports & (eNTCPV6 | eSSUV6 | eNTCP2V6);
|
||||
}
|
||||
|
||||
bool RouterInfo::IsV4 () const
|
||||
|
@ -819,7 +823,6 @@ namespace data
|
|||
m_SupportedTransports |= eNTCPV4 | eSSUV4 | eNTCP2V4;
|
||||
}
|
||||
|
||||
|
||||
void RouterInfo::DisableV6 ()
|
||||
{
|
||||
if (IsV6 ())
|
||||
|
@ -852,7 +855,6 @@ namespace data
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
bool RouterInfo::UsesIntroducer () const
|
||||
{
|
||||
return m_Caps & Caps::eUnreachable; // non-reachable
|
||||
|
|
|
@ -10,30 +10,17 @@ namespace i2p
|
|||
{
|
||||
namespace transport
|
||||
{
|
||||
|
||||
SSUServer::SSUServer (const boost::asio::ip::address & addr, int port):
|
||||
m_OnlyV6(true), m_IsRunning(false),
|
||||
m_Thread (nullptr), m_ThreadV6 (nullptr), m_ReceiversThread (nullptr),
|
||||
m_ReceiversThreadV6 (nullptr), m_Work (m_Service), m_WorkV6 (m_ServiceV6),
|
||||
m_ReceiversWork (m_ReceiversService), m_ReceiversWorkV6 (m_ReceiversServiceV6),
|
||||
m_EndpointV6 (addr, port), m_Socket (m_ReceiversService, m_Endpoint),
|
||||
m_SocketV6 (m_ReceiversServiceV6), m_IntroducersUpdateTimer (m_Service),
|
||||
m_PeerTestsCleanupTimer (m_Service), m_TerminationTimer (m_Service),
|
||||
m_TerminationTimerV6 (m_ServiceV6)
|
||||
{
|
||||
OpenSocketV6 ();
|
||||
}
|
||||
|
||||
SSUServer::SSUServer (int port):
|
||||
m_OnlyV6(false), m_IsRunning(false),
|
||||
m_Thread (nullptr), m_ThreadV6 (nullptr), m_ReceiversThread (nullptr),
|
||||
m_ReceiversThreadV6 (nullptr), m_Work (m_Service), m_WorkV6 (m_ServiceV6),
|
||||
m_IsRunning(false), m_Thread (nullptr), m_ThreadV6 (nullptr),
|
||||
m_ReceiversThread (nullptr), m_ReceiversThreadV6 (nullptr),
|
||||
m_Work (m_Service), m_WorkV6 (m_ServiceV6),
|
||||
m_ReceiversWork (m_ReceiversService), m_ReceiversWorkV6 (m_ReceiversServiceV6),
|
||||
m_Endpoint (boost::asio::ip::udp::v4 (), port), m_EndpointV6 (boost::asio::ip::udp::v6 (), port),
|
||||
m_Socket (m_ReceiversService), m_SocketV6 (m_ReceiversServiceV6),
|
||||
m_IntroducersUpdateTimer (m_Service), m_PeerTestsCleanupTimer (m_Service),
|
||||
m_TerminationTimer (m_Service), m_TerminationTimerV6 (m_ServiceV6)
|
||||
{
|
||||
if (context.SupportsV4 ())
|
||||
OpenSocket ();
|
||||
if (context.SupportsV6 ())
|
||||
OpenSocketV6 ();
|
||||
|
@ -63,7 +50,7 @@ namespace transport
|
|||
void SSUServer::Start ()
|
||||
{
|
||||
m_IsRunning = true;
|
||||
if (!m_OnlyV6)
|
||||
if (context.SupportsV4 ())
|
||||
{
|
||||
m_ReceiversThread = new std::thread (std::bind (&SSUServer::RunReceivers, this));
|
||||
m_Thread = new std::thread (std::bind (&SSUServer::Run, this));
|
||||
|
@ -795,4 +782,3 @@ namespace transport
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -227,10 +227,7 @@ namespace transport
|
|||
{
|
||||
if (m_SSUServer == nullptr && enableSSU)
|
||||
{
|
||||
if (address->host.is_v4())
|
||||
m_SSUServer = new SSUServer (address->port);
|
||||
else
|
||||
m_SSUServer = new SSUServer (address->host, address->port);
|
||||
LogPrint (eLogInfo, "Transports: Start listening UDP port ", address->port);
|
||||
try {
|
||||
m_SSUServer->Start ();
|
||||
|
@ -408,23 +405,19 @@ namespace transport
|
|||
if (!peer.numAttempts) // NTCP2
|
||||
{
|
||||
peer.numAttempts++;
|
||||
if (m_NTCP2Server) // we support NTCP2
|
||||
{
|
||||
// NTCP2 have priority over NTCP
|
||||
auto address = peer.router->GetNTCP2Address (true, !context.SupportsV6 ()); // published only
|
||||
if (address)
|
||||
{
|
||||
if (address && m_NTCP2Server && !i2p::util::net::IsInReservedRange(address->host))
|
||||
{ // we support NTCP2, it has priority over NTCP and remote address is not in reserved range
|
||||
auto s = std::make_shared<NTCP2Session> (*m_NTCP2Server, peer.router);
|
||||
m_NTCP2Server->Connect (address->host, address->port, s);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (peer.numAttempts == 1) // NTCP1
|
||||
{
|
||||
peer.numAttempts++;
|
||||
auto address = peer.router->GetNTCPAddress (!context.SupportsV6 ());
|
||||
if (address && m_NTCPServer)
|
||||
if (address && m_NTCPServer && !i2p::util::net::IsInReservedRange(address->host))
|
||||
{
|
||||
if (!peer.router->UsesIntroducer () && !peer.router->IsUnreachable ())
|
||||
{
|
||||
|
@ -457,14 +450,14 @@ namespace transport
|
|||
if (peer.numAttempts == 2)// SSU
|
||||
{
|
||||
peer.numAttempts++;
|
||||
if (m_SSUServer && peer.router->IsSSU (!context.SupportsV6 ()))
|
||||
{
|
||||
auto address = peer.router->GetSSUAddress (!context.SupportsV6 ());
|
||||
if (address && m_SSUServer && !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");
|
||||
LogPrint (eLogInfo, "Transports: No valid NTCP2, NTCP or SSU remote addresses available");
|
||||
peer.Done ();
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
m_Peers.erase (ident);
|
||||
|
|
|
@ -337,9 +337,41 @@ namespace net
|
|||
LogPrint(eLogWarning, "NetIface: cannot find ipv4 address for interface ", ifname);
|
||||
}
|
||||
return boost::asio::ip::address::from_string(fallback);
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool IsInReservedRange(const boost::asio::ip::address& host) {
|
||||
if(host.is_v6())
|
||||
return false; // for now checking only v4
|
||||
|
||||
// https://en.wikipedia.org/wiki/Reserved_IP_addresses
|
||||
std::string reservedIPv4Ranges[][2] = {
|
||||
{"0.0.0.0", "0.255.255.255"},
|
||||
{"10.0.0.0", "10.255.255.255"},
|
||||
{"100.64.0.0", "100.127.255.255"},
|
||||
{"127.0.0.0", "127.255.255.255"},
|
||||
{"169.254.0.0", "169.254.255.255"},
|
||||
{"172.16.0.0", "172.31.255.255"},
|
||||
{"192.0.0.0", "192.0.0.255"},
|
||||
{"192.0.2.0", "192.0.2.255"},
|
||||
{"192.88.99.0", "192.88.99.255"},
|
||||
{"192.168.0.0", "192.168.255.255"},
|
||||
{"198.18.0.0", "192.19.255.255"},
|
||||
{"198.51.100.0", "198.51.100.255"},
|
||||
{"203.0.113.0", "203.0.113.255"},
|
||||
{"224.0.0.0", "255.255.255.255"}
|
||||
};
|
||||
|
||||
for(int i = 0; i < sizeof(reservedIPv4Ranges); i++) {
|
||||
uint32_t rangeStart = boost::asio::ip::address_v4::from_string(reservedIPv4Ranges[i][0]).to_ulong();
|
||||
uint32_t rangeEnd = boost::asio::ip::address_v4::from_string(reservedIPv4Ranges[i][1]).to_ulong();
|
||||
uint32_t ip_address = host.to_v4().to_ulong();
|
||||
|
||||
if (ip_address >= rangeStart && ip_address <= rangeEnd)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // net
|
||||
} // util
|
||||
} // i2p
|
||||
|
|
|
@ -126,6 +126,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…
Add table
Add a link
Reference in a new issue