mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-02-08 22:13:48 +01:00
[NTCP2] fix socks proxy support
Signed-off-by: R4SAS <r4sas@i2pmail.org>
This commit is contained in:
parent
27d69894d4
commit
1aa0da3382
6 changed files with 109 additions and 121 deletions
|
@ -97,7 +97,8 @@ namespace config {
|
||||||
("httpproxy.address", value<std::string>()->default_value("127.0.0.1"), "HTTP Proxy listen address")
|
("httpproxy.address", value<std::string>()->default_value("127.0.0.1"), "HTTP Proxy listen address")
|
||||||
("httpproxy.port", value<uint16_t>()->default_value(4444), "HTTP Proxy listen port")
|
("httpproxy.port", value<uint16_t>()->default_value(4444), "HTTP Proxy listen port")
|
||||||
("httpproxy.keys", value<std::string>()->default_value(""), "File to persist HTTP Proxy keys")
|
("httpproxy.keys", value<std::string>()->default_value(""), "File to persist HTTP Proxy keys")
|
||||||
("httpproxy.signaturetype", value<i2p::data::SigningKeyType>()->default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519), "Signature type for new keys. 7 (EdDSA) by default")
|
("httpproxy.signaturetype", value<i2p::data::SigningKeyType>()->
|
||||||
|
default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519), "Signature type for new keys. 7 (EdDSA) by default")
|
||||||
("httpproxy.inbound.length", value<std::string>()->default_value("3"), "HTTP proxy inbound tunnel length")
|
("httpproxy.inbound.length", value<std::string>()->default_value("3"), "HTTP proxy inbound tunnel length")
|
||||||
("httpproxy.outbound.length", value<std::string>()->default_value("3"), "HTTP proxy outbound tunnel length")
|
("httpproxy.outbound.length", value<std::string>()->default_value("3"), "HTTP proxy outbound tunnel length")
|
||||||
("httpproxy.inbound.quantity", value<std::string>()->default_value("5"), "HTTP proxy inbound tunnels quantity")
|
("httpproxy.inbound.quantity", value<std::string>()->default_value("5"), "HTTP proxy inbound tunnels quantity")
|
||||||
|
@ -114,7 +115,8 @@ namespace config {
|
||||||
("socksproxy.address", value<std::string>()->default_value("127.0.0.1"), "SOCKS Proxy listen address")
|
("socksproxy.address", value<std::string>()->default_value("127.0.0.1"), "SOCKS Proxy listen address")
|
||||||
("socksproxy.port", value<uint16_t>()->default_value(4447), "SOCKS Proxy listen port")
|
("socksproxy.port", value<uint16_t>()->default_value(4447), "SOCKS Proxy listen port")
|
||||||
("socksproxy.keys", value<std::string>()->default_value(""), "File to persist SOCKS Proxy keys")
|
("socksproxy.keys", value<std::string>()->default_value(""), "File to persist SOCKS Proxy keys")
|
||||||
("socksproxy.signaturetype", value<i2p::data::SigningKeyType>()->default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519), "Signature type for new keys. 7 (EdDSA) by default")
|
("socksproxy.signaturetype", value<i2p::data::SigningKeyType>()->
|
||||||
|
default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519), "Signature type for new keys. 7 (EdDSA) by default")
|
||||||
("socksproxy.inbound.length", value<std::string>()->default_value("3"), "SOCKS proxy inbound tunnel length")
|
("socksproxy.inbound.length", value<std::string>()->default_value("3"), "SOCKS proxy inbound tunnel length")
|
||||||
("socksproxy.outbound.length", value<std::string>()->default_value("3"), "SOCKS proxy outbound tunnel length")
|
("socksproxy.outbound.length", value<std::string>()->default_value("3"), "SOCKS proxy outbound tunnel length")
|
||||||
("socksproxy.inbound.quantity", value<std::string>()->default_value("5"), "SOCKS proxy inbound tunnels quantity")
|
("socksproxy.inbound.quantity", value<std::string>()->default_value("5"), "SOCKS proxy inbound tunnels quantity")
|
||||||
|
|
|
@ -1148,7 +1148,7 @@ namespace transport
|
||||||
|
|
||||||
NTCP2Server::NTCP2Server ():
|
NTCP2Server::NTCP2Server ():
|
||||||
RunnableServiceWithWork ("NTCP2"), m_TerminationTimer (GetService ()),
|
RunnableServiceWithWork ("NTCP2"), m_TerminationTimer (GetService ()),
|
||||||
m_Resolver(GetService ())
|
m_Resolver(GetService ()), m_ProxyType(eNoProxy), m_ProxyEndpoint(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1164,25 +1164,23 @@ namespace transport
|
||||||
StartIOService ();
|
StartIOService ();
|
||||||
if(UsingProxy())
|
if(UsingProxy())
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "NTCP2: USING PROXY ");
|
LogPrint(eLogInfo, "NTCP2: Using proxy to connect to peers");
|
||||||
// TODO: resolve proxy until it is resolved
|
// TODO: resolve proxy until it is resolved
|
||||||
boost::asio::ip::tcp::resolver::query q(m_ProxyAddress, std::to_string(m_ProxyPort));
|
boost::asio::ip::tcp::resolver::query q(m_ProxyAddress, std::to_string(m_ProxyPort));
|
||||||
boost::system::error_code e;
|
boost::system::error_code e;
|
||||||
auto itr = m_Resolver.resolve(q, e);
|
auto itr = m_Resolver.resolve(q, e);
|
||||||
if(e)
|
if(e)
|
||||||
{
|
|
||||||
LogPrint(eLogError, "NTCP2: Failed to resolve proxy ", e.message());
|
LogPrint(eLogError, "NTCP2: Failed to resolve proxy ", e.message());
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_ProxyEndpoint.reset (new boost::asio::ip::tcp::endpoint(*itr));
|
m_ProxyEndpoint.reset (new boost::asio::ip::tcp::endpoint(*itr));
|
||||||
if (m_ProxyEndpoint)
|
if (m_ProxyEndpoint)
|
||||||
LogPrint(eLogError, "NTCP2: m_ProxyEndpoint ", *m_ProxyEndpoint);
|
LogPrint(eLogDebug, "NTCP2: m_ProxyEndpoint ", *m_ProxyEndpoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "NTCP2: NOTUSING PROXY ");
|
LogPrint(eLogInfo, "NTCP2: Proxy is not used");
|
||||||
auto& addresses = context.GetRouterInfo ().GetAddresses ();
|
auto& addresses = context.GetRouterInfo ().GetAddresses ();
|
||||||
for (const auto& address: addresses)
|
for (const auto& address: addresses)
|
||||||
{
|
{
|
||||||
|
@ -1426,6 +1424,31 @@ namespace transport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NTCP2Server::ConnectWithProxy (const std::string& host, uint16_t port, RemoteAddressType addrtype, std::shared_ptr<NTCP2Session> conn)
|
||||||
|
{
|
||||||
|
if(!m_ProxyEndpoint) return;
|
||||||
|
GetService().post([this, host, port, addrtype, conn]() {
|
||||||
|
if (this->AddNTCP2Session (conn))
|
||||||
|
{
|
||||||
|
|
||||||
|
auto timer = std::make_shared<boost::asio::deadline_timer>(GetService());
|
||||||
|
auto timeout = NTCP_CONNECT_TIMEOUT * 5;
|
||||||
|
conn->SetTerminationTimeout(timeout * 2);
|
||||||
|
timer->expires_from_now (boost::posix_time::seconds(timeout));
|
||||||
|
timer->async_wait ([conn, timeout](const boost::system::error_code& ecode)
|
||||||
|
{
|
||||||
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
|
{
|
||||||
|
LogPrint (eLogInfo, "NTCP2: Not connected in ", timeout, " seconds");
|
||||||
|
i2p::data::netdb.SetUnreachable (conn->GetRemoteIdentity ()->GetIdentHash (), true);
|
||||||
|
conn->Terminate ();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
conn->GetSocket ().async_connect (*m_ProxyEndpoint, std::bind (&NTCP2Server::HandleProxyConnect, this, std::placeholders::_1, conn, timer, host, port, addrtype));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void NTCP2Server::UseProxy(ProxyType proxytype, const std::string & addr, uint16_t port)
|
void NTCP2Server::UseProxy(ProxyType proxytype, const std::string & addr, uint16_t port)
|
||||||
{
|
{
|
||||||
m_ProxyType = proxytype;
|
m_ProxyType = proxytype;
|
||||||
|
@ -1552,35 +1575,10 @@ namespace transport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTCP2Server::ConnectWithProxy (const std::string& host, uint16_t port, RemoteAddressType addrtype, std::shared_ptr<NTCP2Session> conn)
|
|
||||||
{
|
|
||||||
if(!m_ProxyEndpoint) return;
|
|
||||||
GetService().post([this, host, port, addrtype, conn]() {
|
|
||||||
if (this->AddNTCP2Session (conn))
|
|
||||||
{
|
|
||||||
|
|
||||||
auto timer = std::make_shared<boost::asio::deadline_timer>(GetService());
|
|
||||||
auto timeout = NTCP_CONNECT_TIMEOUT * 5;
|
|
||||||
conn->SetTerminationTimeout(timeout * 2);
|
|
||||||
timer->expires_from_now (boost::posix_time::seconds(timeout));
|
|
||||||
timer->async_wait ([conn, timeout](const boost::system::error_code& ecode)
|
|
||||||
{
|
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
|
||||||
{
|
|
||||||
LogPrint (eLogInfo, "NTCP2: Not connected in ", timeout, " seconds");
|
|
||||||
i2p::data::netdb.SetUnreachable (conn->GetRemoteIdentity ()->GetIdentHash (), true);
|
|
||||||
conn->Terminate ();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
conn->GetSocket ().async_connect (*m_ProxyEndpoint, std::bind (&NTCP2Server::HandleProxyConnect, this, std::placeholders::_1, conn, timer, host, port, addrtype));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void NTCP2Server::AfterSocksHandshake(std::shared_ptr<NTCP2Session> conn, std::shared_ptr<boost::asio::deadline_timer> timer, const std::string & host, uint16_t port, RemoteAddressType addrtype)
|
void NTCP2Server::AfterSocksHandshake(std::shared_ptr<NTCP2Session> conn, std::shared_ptr<boost::asio::deadline_timer> timer, const std::string & host, uint16_t port, RemoteAddressType addrtype)
|
||||||
{
|
{
|
||||||
// build request
|
// build request
|
||||||
size_t sz = 0;
|
size_t sz = 6; // header + port
|
||||||
auto buff = std::make_shared<std::vector<int8_t> >(256);
|
auto buff = std::make_shared<std::vector<int8_t> >(256);
|
||||||
auto readbuff = std::make_shared<std::vector<int8_t> >(256);
|
auto readbuff = std::make_shared<std::vector<int8_t> >(256);
|
||||||
(*buff)[0] = 0x05;
|
(*buff)[0] = 0x05;
|
||||||
|
@ -1590,36 +1588,26 @@ namespace transport
|
||||||
if(addrtype == eIP4Address)
|
if(addrtype == eIP4Address)
|
||||||
{
|
{
|
||||||
(*buff)[3] = 0x01;
|
(*buff)[3] = 0x01;
|
||||||
auto addr = boost::asio::ip::address::from_string(host).to_v4();
|
auto addrbytes = boost::asio::ip::address::from_string(host).to_v4().to_bytes();
|
||||||
auto addrbytes = addr.to_bytes();
|
sz += 4;
|
||||||
auto addrsize = addrbytes.size();
|
memcpy(buff->data () + 4, addrbytes.data(), 4);
|
||||||
memcpy(buff->data () + 4, addrbytes.data(), addrsize);
|
|
||||||
}
|
}
|
||||||
else if (addrtype == eIP6Address)
|
else if (addrtype == eIP6Address)
|
||||||
{
|
{
|
||||||
(*buff)[3] = 0x04;
|
(*buff)[3] = 0x04;
|
||||||
auto addr = boost::asio::ip::address::from_string(host).to_v6();
|
auto addrbytes = boost::asio::ip::address::from_string(host).to_v6().to_bytes();
|
||||||
auto addrbytes = addr.to_bytes();
|
sz += 16;
|
||||||
auto addrsize = addrbytes.size();
|
memcpy(buff->data () + 4, addrbytes.data(), 16);
|
||||||
memcpy(buff->data () + 4, addrbytes.data(), addrsize);
|
|
||||||
}
|
}
|
||||||
else if (addrtype == eHostname)
|
else if (addrtype == eHostname)
|
||||||
{
|
{
|
||||||
(*buff)[3] = 0x03;
|
// We mustn't really fall here because all connections are made to IP addresses
|
||||||
size_t addrsize = host.size();
|
LogPrint(eLogError, "NTCP2: Tried to connect to domain name via socks proxy");
|
||||||
sz = addrsize + 1 + 4;
|
|
||||||
if (2 + sz > buff->size ())
|
|
||||||
{
|
|
||||||
// too big
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(*buff)[4] = (uint8_t) addrsize;
|
htobe16buf(buff->data () + sz - 2, port);
|
||||||
memcpy(buff->data() + 5, host.c_str(), addrsize);
|
|
||||||
}
|
|
||||||
htobe16buf(buff->data () + sz, port);
|
|
||||||
sz += 2;
|
|
||||||
boost::asio::async_write(conn->GetSocket(), boost::asio::buffer(buff->data (), sz), boost::asio::transfer_all(),
|
boost::asio::async_write(conn->GetSocket(), boost::asio::buffer(buff->data (), sz), boost::asio::transfer_all(),
|
||||||
[](const boost::system::error_code & ec, std::size_t written)
|
[buff](const boost::system::error_code & ec, std::size_t written)
|
||||||
{
|
{
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
|
@ -1650,6 +1638,5 @@ namespace transport
|
||||||
conn->Terminate();
|
conn->Terminate();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -274,7 +274,7 @@ namespace transport
|
||||||
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 =eNoProxy;
|
ProxyType m_ProxyType;
|
||||||
std::string m_ProxyAddress;
|
std::string m_ProxyAddress;
|
||||||
uint16_t m_ProxyPort;
|
uint16_t m_ProxyPort;
|
||||||
boost::asio::ip::tcp::resolver m_Resolver;
|
boost::asio::ip::tcp::resolver m_Resolver;
|
||||||
|
|
|
@ -1193,7 +1193,6 @@ namespace transport
|
||||||
|
|
||||||
void NTCPServer::AfterSocksHandshake(std::shared_ptr<NTCPSession> conn, std::shared_ptr<boost::asio::deadline_timer> timer, const std::string & host, uint16_t port, RemoteAddressType addrtype)
|
void NTCPServer::AfterSocksHandshake(std::shared_ptr<NTCPSession> conn, std::shared_ptr<boost::asio::deadline_timer> timer, const std::string & host, uint16_t port, RemoteAddressType addrtype)
|
||||||
{
|
{
|
||||||
|
|
||||||
// build request
|
// build request
|
||||||
size_t sz = 0;
|
size_t sz = 0;
|
||||||
uint8_t buff[256];
|
uint8_t buff[256];
|
||||||
|
|
|
@ -176,7 +176,7 @@ namespace transport
|
||||||
|
|
||||||
if (proxyurl.schema == "http")
|
if (proxyurl.schema == "http")
|
||||||
proxytype = NTCPServer::eHTTPProxy;
|
proxytype = NTCPServer::eHTTPProxy;
|
||||||
m_NTCPServer->UseProxy(proxytype, proxyurl.host, proxyurl.port) ;
|
m_NTCPServer->UseProxy(proxytype, proxyurl.host, proxyurl.port);
|
||||||
m_NTCPServer->Start();
|
m_NTCPServer->Start();
|
||||||
if(!m_NTCPServer->NetworkIsReady())
|
if(!m_NTCPServer->NetworkIsReady())
|
||||||
{
|
{
|
||||||
|
@ -209,7 +209,7 @@ namespace transport
|
||||||
if (proxyurl.schema == "http")
|
if (proxyurl.schema == "http")
|
||||||
proxytype = NTCP2Server::eHTTPProxy;
|
proxytype = NTCP2Server::eHTTPProxy;
|
||||||
|
|
||||||
m_NTCP2Server->UseProxy(proxytype, proxyurl.host, proxyurl.port) ;
|
m_NTCP2Server->UseProxy(proxytype, proxyurl.host, proxyurl.port);
|
||||||
m_NTCP2Server->Start();
|
m_NTCP2Server->Start();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -226,7 +226,7 @@ namespace proxy
|
||||||
|
|
||||||
boost::asio::const_buffers_1 SOCKSHandler::GenerateSOCKS5Response(SOCKSHandler::errTypes error, SOCKSHandler::addrTypes type, const SOCKSHandler::address &addr, uint16_t port)
|
boost::asio::const_buffers_1 SOCKSHandler::GenerateSOCKS5Response(SOCKSHandler::errTypes error, SOCKSHandler::addrTypes type, const SOCKSHandler::address &addr, uint16_t port)
|
||||||
{
|
{
|
||||||
size_t size = 6;
|
size_t size = 6; // header + port
|
||||||
assert(error <= SOCKS5_ADDR_UNSUP);
|
assert(error <= SOCKS5_ADDR_UNSUP);
|
||||||
m_response[0] = '\x05'; //Version
|
m_response[0] = '\x05'; //Version
|
||||||
m_response[1] = error; //Response code
|
m_response[1] = error; //Response code
|
||||||
|
@ -235,15 +235,15 @@ namespace proxy
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ADDR_IPV4:
|
case ADDR_IPV4:
|
||||||
size = 10;
|
size += 4;
|
||||||
htobe32buf(m_response + 4, addr.ip);
|
htobe32buf(m_response + 4, addr.ip);
|
||||||
break;
|
break;
|
||||||
case ADDR_IPV6:
|
case ADDR_IPV6:
|
||||||
size = 22;
|
size += 16;
|
||||||
memcpy(m_response + 4, addr.ipv6, 16);
|
memcpy(m_response + 4, addr.ipv6, 16);
|
||||||
break;
|
break;
|
||||||
case ADDR_DNS:
|
case ADDR_DNS:
|
||||||
size = 7 + addr.dns.size;
|
size += (1 + addr.dns.size); /* name length + domain name */
|
||||||
m_response[4] = addr.dns.size;
|
m_response[4] = addr.dns.size;
|
||||||
memcpy(m_response + 5, addr.dns.value, addr.dns.size);
|
memcpy(m_response + 5, addr.dns.value, addr.dns.size);
|
||||||
// replace type to IPv4 for support socks5 clients
|
// replace type to IPv4 for support socks5 clients
|
||||||
|
|
Loading…
Add table
Reference in a new issue