mirror of
https://github.com/PurpleI2P/i2pd
synced 2024-11-10 08:00:38 +03:00
Merge pull request #1478 from unlnown542a/openssl
add ntcp2proxy support
This commit is contained in:
commit
de4cb74173
@ -61,6 +61,7 @@ namespace config {
|
|||||||
("ntcp", value<bool>()->default_value(false), "Enable NTCP transport (default: disabled)")
|
("ntcp", value<bool>()->default_value(false), "Enable NTCP transport (default: disabled)")
|
||||||
("ssu", value<bool>()->default_value(true), "Enable SSU transport (default: enabled)")
|
("ssu", value<bool>()->default_value(true), "Enable SSU transport (default: enabled)")
|
||||||
("ntcpproxy", value<std::string>()->default_value(""), "Proxy URL for NTCP transport")
|
("ntcpproxy", value<std::string>()->default_value(""), "Proxy URL for NTCP transport")
|
||||||
|
("ntcp2proxy", value<std::string>()->default_value(""), "Proxy URL for NTCP2 transport")
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
("svcctl", value<std::string>()->default_value(""), "Windows service management ('install' or 'remove')")
|
("svcctl", value<std::string>()->default_value(""), "Windows service management ('install' or 'remove')")
|
||||||
("insomnia", bool_switch()->default_value(false), "Prevent system from sleeping (default: disabled)")
|
("insomnia", bool_switch()->default_value(false), "Prevent system from sleeping (default: disabled)")
|
||||||
@ -305,16 +306,16 @@ namespace config {
|
|||||||
std::cout << "i2pd version " << I2PD_VERSION << " (" << I2P_VERSION << ")" << std::endl;
|
std::cout << "i2pd version " << I2PD_VERSION << " (" << I2P_VERSION << ")" << std::endl;
|
||||||
std::cout << m_OptionsDesc;
|
std::cout << m_OptionsDesc;
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
else if (m_Options.count("version"))
|
else if (m_Options.count("version"))
|
||||||
{
|
{
|
||||||
std::cout << "i2pd version " << I2PD_VERSION << " (" << I2P_VERSION << ")" << std::endl;
|
std::cout << "i2pd version " << I2PD_VERSION << " (" << I2P_VERSION << ")" << std::endl;
|
||||||
std::cout << "Boost version "
|
std::cout << "Boost version "
|
||||||
<< BOOST_VERSION / 100000 << "." // maj. version
|
<< BOOST_VERSION / 100000 << "." // maj. version
|
||||||
<< BOOST_VERSION / 100 % 1000 << "." // min. version
|
<< BOOST_VERSION / 100 % 1000 << "." // min. version
|
||||||
<< BOOST_VERSION % 100 // patch version
|
<< BOOST_VERSION % 100 // patch version
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
#if defined(OPENSSL_VERSION_TEXT)
|
#if defined(OPENSSL_VERSION_TEXT)
|
||||||
std::cout << OPENSSL_VERSION_TEXT << std::endl;
|
std::cout << OPENSSL_VERSION_TEXT << std::endl;
|
||||||
#endif
|
#endif
|
||||||
#if defined(LIBRESSL_VERSION_TEXT)
|
#if defined(LIBRESSL_VERSION_TEXT)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -28,7 +28,7 @@ namespace i2p
|
|||||||
namespace transport
|
namespace transport
|
||||||
{
|
{
|
||||||
|
|
||||||
const size_t NTCP2_UNENCRYPTED_FRAME_MAX_SIZE = 65519;
|
const size_t NTCP2_UNENCRYPTED_FRAME_MAX_SIZE = 65519;
|
||||||
const int NTCP2_MAX_PADDING_RATIO = 6; // in %
|
const int NTCP2_MAX_PADDING_RATIO = 6; // in %
|
||||||
|
|
||||||
const int NTCP2_CONNECT_TIMEOUT = 5; // 5 seconds
|
const int NTCP2_CONNECT_TIMEOUT = 5; // 5 seconds
|
||||||
@ -36,7 +36,7 @@ namespace transport
|
|||||||
const int NTCP2_TERMINATION_TIMEOUT = 120; // 2 minutes
|
const int NTCP2_TERMINATION_TIMEOUT = 120; // 2 minutes
|
||||||
const int NTCP2_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds
|
const int NTCP2_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds
|
||||||
|
|
||||||
const int NTCP2_CLOCK_SKEW = 60; // in seconds
|
const int NTCP2_CLOCK_SKEW = 60; // in seconds
|
||||||
const int NTCP2_MAX_OUTGOING_QUEUE_SIZE = 500; // how many messages we can queue up
|
const int NTCP2_MAX_OUTGOING_QUEUE_SIZE = 500; // how many messages we can queue up
|
||||||
|
|
||||||
enum NTCP2BlockType
|
enum NTCP2BlockType
|
||||||
@ -46,8 +46,8 @@ namespace transport
|
|||||||
eNTCP2BlkRouterInfo, // 2
|
eNTCP2BlkRouterInfo, // 2
|
||||||
eNTCP2BlkI2NPMessage, // 3
|
eNTCP2BlkI2NPMessage, // 3
|
||||||
eNTCP2BlkTermination, // 4
|
eNTCP2BlkTermination, // 4
|
||||||
eNTCP2BlkPadding = 254
|
eNTCP2BlkPadding = 254
|
||||||
};
|
};
|
||||||
|
|
||||||
enum NTCP2TerminationReason
|
enum NTCP2TerminationReason
|
||||||
{
|
{
|
||||||
@ -69,16 +69,16 @@ namespace transport
|
|||||||
eNTCP2RouterInfoSignatureVerificationFail, // 15
|
eNTCP2RouterInfoSignatureVerificationFail, // 15
|
||||||
eNTCP2IncorrectSParameter, // 16
|
eNTCP2IncorrectSParameter, // 16
|
||||||
eNTCP2Banned, // 17
|
eNTCP2Banned, // 17
|
||||||
};
|
};
|
||||||
|
|
||||||
// RouterInfo flags
|
// RouterInfo flags
|
||||||
const uint8_t NTCP2_ROUTER_INFO_FLAG_REQUEST_FLOOD = 0x01;
|
const uint8_t NTCP2_ROUTER_INFO_FLAG_REQUEST_FLOOD = 0x01;
|
||||||
|
|
||||||
struct NTCP2Establisher
|
struct NTCP2Establisher
|
||||||
{
|
{
|
||||||
NTCP2Establisher ();
|
NTCP2Establisher ();
|
||||||
~NTCP2Establisher ();
|
~NTCP2Establisher ();
|
||||||
|
|
||||||
const uint8_t * GetPub () const { return m_EphemeralKeys.GetPublicKey (); };
|
const uint8_t * GetPub () const { return m_EphemeralKeys.GetPublicKey (); };
|
||||||
const uint8_t * GetRemotePub () const { return m_RemoteEphemeralPublicKey; }; // Y for Alice and X for Bob
|
const uint8_t * GetRemotePub () const { return m_RemoteEphemeralPublicKey; }; // Y for Alice and X for Bob
|
||||||
uint8_t * GetRemotePub () { return m_RemoteEphemeralPublicKey; }; // to set
|
uint8_t * GetRemotePub () { return m_RemoteEphemeralPublicKey; }; // to set
|
||||||
@ -114,19 +114,20 @@ namespace transport
|
|||||||
uint8_t m_RemoteEphemeralPublicKey[32]; // x25519
|
uint8_t m_RemoteEphemeralPublicKey[32]; // x25519
|
||||||
uint8_t m_RemoteStaticKey[32], m_IV[16], m_H[32] /*h*/, m_CK[64] /* [ck, k]*/;
|
uint8_t m_RemoteStaticKey[32], m_IV[16], m_H[32] /*h*/, m_CK[64] /* [ck, k]*/;
|
||||||
i2p::data::IdentHash m_RemoteIdentHash;
|
i2p::data::IdentHash m_RemoteIdentHash;
|
||||||
uint16_t m3p2Len;
|
uint16_t m3p2Len;
|
||||||
|
|
||||||
uint8_t * m_SessionRequestBuffer, * m_SessionCreatedBuffer, * m_SessionConfirmedBuffer;
|
uint8_t * m_SessionRequestBuffer, * m_SessionCreatedBuffer, * m_SessionConfirmedBuffer;
|
||||||
size_t m_SessionRequestBufferLen, m_SessionCreatedBufferLen;
|
size_t m_SessionRequestBufferLen, m_SessionCreatedBufferLen;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class NTCP2Server;
|
class NTCP2Server;
|
||||||
class NTCP2Session: public TransportSession, public std::enable_shared_from_this<NTCP2Session>
|
class NTCP2Session: public TransportSession, public std::enable_shared_from_this<NTCP2Session>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
NTCP2Session (NTCP2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter = nullptr);
|
|
||||||
|
NTCP2Session (NTCP2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter = nullptr);
|
||||||
~NTCP2Session ();
|
~NTCP2Session ();
|
||||||
void Terminate ();
|
void Terminate ();
|
||||||
void TerminateByTimeout ();
|
void TerminateByTimeout ();
|
||||||
@ -138,9 +139,9 @@ namespace transport
|
|||||||
bool IsEstablished () const { return m_IsEstablished; };
|
bool IsEstablished () const { return m_IsEstablished; };
|
||||||
bool IsTerminated () const { return m_IsTerminated; };
|
bool IsTerminated () const { return m_IsTerminated; };
|
||||||
|
|
||||||
void ClientLogin (); // Alice
|
void ClientLogin (); // Alice
|
||||||
void ServerLogin (); // Bob
|
void ServerLogin (); // Bob
|
||||||
|
|
||||||
void SendLocalRouterInfo (); // after handshake
|
void SendLocalRouterInfo (); // after handshake
|
||||||
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
||||||
|
|
||||||
@ -193,15 +194,15 @@ namespace transport
|
|||||||
|
|
||||||
std::unique_ptr<NTCP2Establisher> m_Establisher;
|
std::unique_ptr<NTCP2Establisher> m_Establisher;
|
||||||
// data phase
|
// data phase
|
||||||
uint8_t m_Kab[32], m_Kba[32], m_Sipkeysab[32], m_Sipkeysba[32];
|
uint8_t m_Kab[32], m_Kba[32], m_Sipkeysab[32], m_Sipkeysba[32];
|
||||||
const uint8_t * m_SendKey, * m_ReceiveKey;
|
const uint8_t * m_SendKey, * m_ReceiveKey;
|
||||||
#if OPENSSL_SIPHASH
|
#if OPENSSL_SIPHASH
|
||||||
EVP_PKEY * m_SendSipKey, * m_ReceiveSipKey;
|
EVP_PKEY * m_SendSipKey, * m_ReceiveSipKey;
|
||||||
EVP_MD_CTX * m_SendMDCtx, * m_ReceiveMDCtx;
|
EVP_MD_CTX * m_SendMDCtx, * m_ReceiveMDCtx;
|
||||||
#else
|
#else
|
||||||
const uint8_t * m_SendSipKey, * m_ReceiveSipKey;
|
const uint8_t * m_SendSipKey, * m_ReceiveSipKey;
|
||||||
#endif
|
#endif
|
||||||
uint16_t m_NextReceivedLen;
|
uint16_t m_NextReceivedLen;
|
||||||
uint8_t * m_NextReceivedBuffer, * m_NextSendBuffer;
|
uint8_t * m_NextReceivedBuffer, * m_NextSendBuffer;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
@ -220,6 +221,20 @@ namespace transport
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
enum RemoteAddressType
|
||||||
|
{
|
||||||
|
eIP4Address,
|
||||||
|
eIP6Address,
|
||||||
|
eHostname
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ProxyType
|
||||||
|
{
|
||||||
|
eNoProxy,
|
||||||
|
eSocksProxy,
|
||||||
|
eHTTPProxy
|
||||||
|
};
|
||||||
|
|
||||||
NTCP2Server ();
|
NTCP2Server ();
|
||||||
~NTCP2Server ();
|
~NTCP2Server ();
|
||||||
|
|
||||||
@ -230,15 +245,23 @@ namespace transport
|
|||||||
bool AddNTCP2Session (std::shared_ptr<NTCP2Session> session, bool incoming = false);
|
bool AddNTCP2Session (std::shared_ptr<NTCP2Session> session, bool incoming = false);
|
||||||
void RemoveNTCP2Session (std::shared_ptr<NTCP2Session> session);
|
void RemoveNTCP2Session (std::shared_ptr<NTCP2Session> session);
|
||||||
std::shared_ptr<NTCP2Session> FindNTCP2Session (const i2p::data::IdentHash& ident);
|
std::shared_ptr<NTCP2Session> FindNTCP2Session (const i2p::data::IdentHash& ident);
|
||||||
|
|
||||||
|
void ConnectWithProxy (const std::string& addr, uint16_t port, RemoteAddressType addrtype, std::shared_ptr<NTCP2Session> conn);
|
||||||
void Connect(const boost::asio::ip::address & address, uint16_t port, std::shared_ptr<NTCP2Session> conn);
|
void Connect(const boost::asio::ip::address & address, uint16_t port, std::shared_ptr<NTCP2Session> conn);
|
||||||
|
|
||||||
|
void AfterSocksHandshake(std::shared_ptr<NTCP2Session> conn, std::shared_ptr<boost::asio::deadline_timer> timer, const std::string & host, uint16_t port, RemoteAddressType addrtype);
|
||||||
|
|
||||||
|
|
||||||
|
bool UsingProxy() const { return m_ProxyType != eNoProxy; };
|
||||||
|
void UseProxy(ProxyType proxy, const std::string & address, uint16_t port);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void HandleAccept (std::shared_ptr<NTCP2Session> conn, const boost::system::error_code& error);
|
void HandleAccept (std::shared_ptr<NTCP2Session> conn, const boost::system::error_code& error);
|
||||||
void HandleAcceptV6 (std::shared_ptr<NTCP2Session> conn, const boost::system::error_code& error);
|
void HandleAcceptV6 (std::shared_ptr<NTCP2Session> conn, const boost::system::error_code& error);
|
||||||
|
|
||||||
void HandleConnect (const boost::system::error_code& ecode, std::shared_ptr<NTCP2Session> conn, std::shared_ptr<boost::asio::deadline_timer> timer);
|
void HandleConnect (const boost::system::error_code& ecode, std::shared_ptr<NTCP2Session> conn, std::shared_ptr<boost::asio::deadline_timer> timer);
|
||||||
|
void HandleProxyConnect(const boost::system::error_code& ecode, std::shared_ptr<NTCP2Session> conn, std::shared_ptr<boost::asio::deadline_timer> timer, const std::string & host, uint16_t port, RemoteAddressType adddrtype);
|
||||||
|
|
||||||
// timer
|
// timer
|
||||||
void ScheduleTermination ();
|
void ScheduleTermination ();
|
||||||
@ -248,9 +271,15 @@ namespace transport
|
|||||||
|
|
||||||
boost::asio::deadline_timer m_TerminationTimer;
|
boost::asio::deadline_timer m_TerminationTimer;
|
||||||
std::unique_ptr<boost::asio::ip::tcp::acceptor> m_NTCP2Acceptor, m_NTCP2V6Acceptor;
|
std::unique_ptr<boost::asio::ip::tcp::acceptor> m_NTCP2Acceptor, m_NTCP2V6Acceptor;
|
||||||
std::map<i2p::data::IdentHash, std::shared_ptr<NTCP2Session> > m_NTCP2Sessions;
|
std::map<i2p::data::IdentHash, std::shared_ptr<NTCP2Session> > m_NTCP2Sessions;
|
||||||
std::list<std::shared_ptr<NTCP2Session> > m_PendingIncomingSessions;
|
std::list<std::shared_ptr<NTCP2Session> > m_PendingIncomingSessions;
|
||||||
|
|
||||||
|
ProxyType m_ProxyType;
|
||||||
|
std::string m_ProxyAddress;
|
||||||
|
uint16_t m_ProxyPort;
|
||||||
|
boost::asio::ip::tcp::resolver m_Resolver;
|
||||||
|
boost::asio::ip::tcp::endpoint * m_ProxyEndpoint;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// for HTTP/I2PControl
|
// for HTTP/I2PControl
|
||||||
|
@ -157,6 +157,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 ntcpproxy; i2p::config::GetOption("ntcpproxy", ntcpproxy);
|
std::string ntcpproxy; i2p::config::GetOption("ntcpproxy", ntcpproxy);
|
||||||
|
std::string ntcp2proxy; i2p::config::GetOption("ntcp2proxy", ntcp2proxy);
|
||||||
i2p::http::URL proxyurl;
|
i2p::http::URL proxyurl;
|
||||||
uint16_t softLimit, hardLimit, threads;
|
uint16_t softLimit, hardLimit, threads;
|
||||||
i2p::config::GetOption("limits.ntcpsoft", softLimit);
|
i2p::config::GetOption("limits.ntcpsoft", softLimit);
|
||||||
@ -196,13 +197,36 @@ namespace transport
|
|||||||
LogPrint(eLogError, "Transports: invalid NTCP proxy url ", ntcpproxy);
|
LogPrint(eLogError, "Transports: invalid NTCP proxy url ", ntcpproxy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// create NTCP2. TODO: move to acceptor
|
// create NTCP2. TODO: move to acceptor
|
||||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||||
if (ntcp2)
|
if (ntcp2)
|
||||||
{
|
{
|
||||||
m_NTCP2Server = new NTCP2Server ();
|
if(ntcp2proxy.size())
|
||||||
m_NTCP2Server->Start ();
|
{
|
||||||
}
|
if(proxyurl.parse(ntcp2proxy))
|
||||||
|
{
|
||||||
|
if(proxyurl.schema == "socks" || proxyurl.schema == "http")
|
||||||
|
{
|
||||||
|
m_NTCP2Server = new NTCP2Server ();
|
||||||
|
NTCP2Server::ProxyType proxytype = NTCP2Server::eSocksProxy;
|
||||||
|
|
||||||
|
if (proxyurl.schema == "http")
|
||||||
|
proxytype = NTCP2Server::eHTTPProxy;
|
||||||
|
|
||||||
|
m_NTCP2Server->UseProxy(proxytype, proxyurl.host, proxyurl.port) ;
|
||||||
|
m_NTCP2Server->Start();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint(eLogError, "Transports: unsupported NTCP2 proxy URL ", ntcp2proxy);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint(eLogError, "Transports: invalid NTCP2 proxy url ", ntcp2proxy);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// m_NTCP2Server = new NTCP2Server ();
|
||||||
|
// m_NTCP2Server->Start ();
|
||||||
|
}
|
||||||
|
|
||||||
// create acceptors
|
// create acceptors
|
||||||
auto& addresses = context.GetRouterInfo ().GetAddresses ();
|
auto& addresses = context.GetRouterInfo ().GetAddresses ();
|
||||||
@ -405,24 +429,36 @@ namespace transport
|
|||||||
{
|
{
|
||||||
if (peer.router) // we have RI already
|
if (peer.router) // we have RI already
|
||||||
{
|
{
|
||||||
if (!peer.numAttempts) // NTCP2
|
if (!peer.numAttempts) // NTCP2
|
||||||
{
|
{
|
||||||
peer.numAttempts++;
|
peer.numAttempts++;
|
||||||
if (m_NTCP2Server) // we support NTCP2
|
if (m_NTCP2Server) // we support NTCP2
|
||||||
{
|
{
|
||||||
// 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)
|
if (address)
|
||||||
{
|
{
|
||||||
auto s = std::make_shared<NTCP2Session> (*m_NTCP2Server, peer.router);
|
auto s = std::make_shared<NTCP2Session> (*m_NTCP2Server, peer.router);
|
||||||
m_NTCP2Server->Connect (address->host, address->port, s);
|
|
||||||
return true;
|
if(m_NTCP2Server->UsingProxy())
|
||||||
}
|
{
|
||||||
}
|
NTCP2Server::RemoteAddressType remote = NTCP2Server::eIP4Address;
|
||||||
}
|
std::string addr = address->host.to_string();
|
||||||
|
|
||||||
|
if(address->host.is_v6())
|
||||||
|
remote = NTCP2Server::eIP6Address;
|
||||||
|
|
||||||
|
m_NTCP2Server->ConnectWithProxy(addr, address->port, remote, s);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_NTCP2Server->Connect (address->host, address->port, s);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (peer.numAttempts == 1) // NTCP1
|
if (peer.numAttempts == 1) // NTCP1
|
||||||
{
|
{
|
||||||
peer.numAttempts++;
|
peer.numAttempts++;
|
||||||
auto address = peer.router->GetNTCPAddress (!context.SupportsV6 ());
|
auto address = peer.router->GetNTCPAddress (!context.SupportsV6 ());
|
||||||
if (address && m_NTCPServer)
|
if (address && m_NTCPServer)
|
||||||
{
|
{
|
||||||
@ -650,14 +686,14 @@ namespace transport
|
|||||||
{
|
{
|
||||||
auto before = it->second.sessions.size ();
|
auto before = it->second.sessions.size ();
|
||||||
it->second.sessions.remove (session);
|
it->second.sessions.remove (session);
|
||||||
if (it->second.sessions.empty ())
|
if (it->second.sessions.empty ())
|
||||||
{
|
{
|
||||||
if (it->second.delayedMessages.size () > 0)
|
if (it->second.delayedMessages.size () > 0)
|
||||||
{
|
{
|
||||||
if (before > 0) // we had an active session before
|
if (before > 0) // we had an active session before
|
||||||
it->second.numAttempts = 0; // start over
|
it->second.numAttempts = 0; // start over
|
||||||
ConnectToPeer (ident, it->second);
|
ConnectToPeer (ident, it->second);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||||
|
Loading…
Reference in New Issue
Block a user