Merge pull request #1478 from unlnown542a/openssl

add ntcp2proxy support
This commit is contained in:
orignal 2020-03-01 10:04:27 -05:00 committed by GitHub
commit de4cb74173
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 533 additions and 218 deletions

View File

@ -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

View File

@ -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

View File

@ -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);