|
|
|
@ -333,15 +333,14 @@ namespace transport
@@ -333,15 +333,14 @@ namespace transport
|
|
|
|
|
if (in_RemoteRouter) // Alice
|
|
|
|
|
{ |
|
|
|
|
m_Establisher->m_RemoteIdentHash = GetRemoteIdentity ()->GetIdentHash (); |
|
|
|
|
if (!addr) |
|
|
|
|
addr = in_RemoteRouter->GetNTCP2Address (true); // we need a published address
|
|
|
|
|
if (addr) |
|
|
|
|
{ |
|
|
|
|
memcpy (m_Establisher->m_RemoteStaticKey, addr->ntcp2->staticKey, 32); |
|
|
|
|
memcpy (m_Establisher->m_IV, addr->ntcp2->iv, 16); |
|
|
|
|
m_RemoteEndpoint = boost::asio::ip::tcp::endpoint (addr->host, addr->port); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
LogPrint (eLogWarning, "NTCP2: Missing NTCP2 parameters"); |
|
|
|
|
LogPrint (eLogWarning, "NTCP2: Missing NTCP2 address"); |
|
|
|
|
} |
|
|
|
|
m_NextRouterInfoResendTime = i2p::util::GetSecondsSinceEpoch () + NTCP2_ROUTERINFO_RESEND_INTERVAL + |
|
|
|
|
rand ()%NTCP2_ROUTERINFO_RESEND_INTERVAL_THRESHOLD; |
|
|
|
@ -657,19 +656,13 @@ namespace transport
@@ -657,19 +656,13 @@ namespace transport
|
|
|
|
|
SendTerminationAndTerminate (eNTCP2Message3Error); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
auto addr = ri.GetNTCP2Address (false); // any NTCP2 address
|
|
|
|
|
auto addr = ri.GetNTCP2AddressWithStaticKey (m_Establisher->m_RemoteStaticKey); |
|
|
|
|
if (!addr) |
|
|
|
|
{ |
|
|
|
|
LogPrint (eLogError, "NTCP2: No NTCP2 address found in SessionConfirmed"); |
|
|
|
|
LogPrint (eLogError, "NTCP2: No NTCP2 address wth static key found in SessionConfirmed"); |
|
|
|
|
Terminate (); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (memcmp (addr->ntcp2->staticKey, m_Establisher->m_RemoteStaticKey, 32)) |
|
|
|
|
{ |
|
|
|
|
LogPrint (eLogError, "NTCP2: Static key mismatch in SessionConfirmed"); |
|
|
|
|
SendTerminationAndTerminate (eNTCP2IncorrectSParameter); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
i2p::data::netdb.PostI2NPMsg (CreateI2NPMessage (eI2NPDummyMsg, buf.data () + 3, size)); // TODO: should insert ri and not parse it twice
|
|
|
|
|
// TODO: process options
|
|
|
|
|
|
|
|
|
@ -1177,7 +1170,9 @@ namespace transport
@@ -1177,7 +1170,9 @@ namespace transport
|
|
|
|
|
{ |
|
|
|
|
try |
|
|
|
|
{ |
|
|
|
|
m_NTCP2Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService (), boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), address->port))); |
|
|
|
|
auto ep = m_Address4 ? boost::asio::ip::tcp::endpoint (m_Address4->address(), address->port): |
|
|
|
|
boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), address->port); |
|
|
|
|
m_NTCP2Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService (), ep)); |
|
|
|
|
} |
|
|
|
|
catch ( std::exception & ex ) |
|
|
|
|
{ |
|
|
|
@ -1274,10 +1269,15 @@ namespace transport
@@ -1274,10 +1269,15 @@ namespace transport
|
|
|
|
|
return nullptr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void NTCP2Server::Connect(const boost::asio::ip::address & address, uint16_t port, std::shared_ptr<NTCP2Session> conn) |
|
|
|
|
void NTCP2Server::Connect(std::shared_ptr<NTCP2Session> conn) |
|
|
|
|
{ |
|
|
|
|
LogPrint (eLogDebug, "NTCP2: Connecting to ", address ,":", port); |
|
|
|
|
GetService ().post([this, address, port, conn]() |
|
|
|
|
if (!conn || conn->GetRemoteEndpoint ().address ().is_unspecified ()) |
|
|
|
|
{ |
|
|
|
|
LogPrint (eLogError, "NTCP2: Can't connect to unspecified address"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
LogPrint (eLogDebug, "NTCP2: Connecting to ", conn->GetRemoteEndpoint ()); |
|
|
|
|
GetService ().post([this, conn]() |
|
|
|
|
{ |
|
|
|
|
if (this->AddNTCP2Session (conn)) |
|
|
|
|
{ |
|
|
|
@ -1290,12 +1290,32 @@ namespace transport
@@ -1290,12 +1290,32 @@ namespace transport
|
|
|
|
|
if (ecode != boost::asio::error::operation_aborted) |
|
|
|
|
{ |
|
|
|
|
LogPrint (eLogInfo, "NTCP2: Not connected in ", timeout, " seconds"); |
|
|
|
|
if (conn->GetRemoteIdentity ()) |
|
|
|
|
i2p::data::netdb.SetUnreachable (conn->GetRemoteIdentity ()->GetIdentHash (), true); |
|
|
|
|
conn->Terminate (); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
conn->GetSocket ().async_connect (boost::asio::ip::tcp::endpoint (address, port), std::bind (&NTCP2Server::HandleConnect, this, std::placeholders::_1, conn, timer)); |
|
|
|
|
// bind to local address
|
|
|
|
|
std::shared_ptr<boost::asio::ip::tcp::endpoint> localAddress; |
|
|
|
|
if (conn->GetRemoteEndpoint ().address ().is_v6 ()) |
|
|
|
|
{ |
|
|
|
|
if (i2p::util::net::IsYggdrasilAddress (conn->GetRemoteEndpoint ().address ())) |
|
|
|
|
localAddress = m_YggdrasilAddress; |
|
|
|
|
else |
|
|
|
|
localAddress = m_Address6; |
|
|
|
|
conn->GetSocket ().open (boost::asio::ip::tcp::v6 ()); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
localAddress = m_Address4; |
|
|
|
|
conn->GetSocket ().open (boost::asio::ip::tcp::v4 ()); |
|
|
|
|
} |
|
|
|
|
if (localAddress) |
|
|
|
|
{ |
|
|
|
|
boost::system::error_code ec; |
|
|
|
|
conn->GetSocket ().bind (*localAddress, ec); |
|
|
|
|
if (ec) |
|
|
|
|
LogPrint (eLogError, "NTCP2: can't bind to ", localAddress->address ().to_string (), ": ", ec.message ()); |
|
|
|
|
} |
|
|
|
|
conn->GetSocket ().async_connect (conn->GetRemoteEndpoint (), std::bind (&NTCP2Server::HandleConnect, this, std::placeholders::_1, conn, timer)); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
conn->Terminate (); |
|
|
|
@ -1312,7 +1332,7 @@ namespace transport
@@ -1312,7 +1332,7 @@ namespace transport
|
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
LogPrint (eLogDebug, "NTCP2: Connected to ", conn->GetSocket ().remote_endpoint ()); |
|
|
|
|
LogPrint (eLogDebug, "NTCP2: Connected to ", conn->GetRemoteEndpoint ()); |
|
|
|
|
conn->ClientLogin (); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1328,6 +1348,7 @@ namespace transport
@@ -1328,6 +1348,7 @@ namespace transport
|
|
|
|
|
LogPrint (eLogDebug, "NTCP2: Connected from ", ep); |
|
|
|
|
if (conn) |
|
|
|
|
{ |
|
|
|
|
conn->SetRemoteEndpoint (ep); |
|
|
|
|
conn->ServerLogin (); |
|
|
|
|
m_PendingIncomingSessions.push_back (conn); |
|
|
|
|
conn = nullptr; |
|
|
|
@ -1361,6 +1382,7 @@ namespace transport
@@ -1361,6 +1382,7 @@ namespace transport
|
|
|
|
|
LogPrint (eLogDebug, "NTCP2: Connected from ", ep); |
|
|
|
|
if (conn) |
|
|
|
|
{ |
|
|
|
|
conn->SetRemoteEndpoint (ep); |
|
|
|
|
conn->ServerLogin (); |
|
|
|
|
m_PendingIncomingSessions.push_back (conn); |
|
|
|
|
} |
|
|
|
@ -1415,13 +1437,18 @@ namespace transport
@@ -1415,13 +1437,18 @@ namespace transport
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void NTCP2Server::ConnectWithProxy (const std::string& host, uint16_t port, RemoteAddressType addrtype, std::shared_ptr<NTCP2Session> conn) |
|
|
|
|
void NTCP2Server::ConnectWithProxy (std::shared_ptr<NTCP2Session> conn) |
|
|
|
|
{ |
|
|
|
|
if(!m_ProxyEndpoint) return; |
|
|
|
|
GetService().post([this, host, port, addrtype, conn]() { |
|
|
|
|
if (!conn || conn->GetRemoteEndpoint ().address ().is_unspecified ()) |
|
|
|
|
{ |
|
|
|
|
LogPrint (eLogError, "NTCP2: Can't connect to unspecified address"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
GetService().post([this, conn]() |
|
|
|
|
{ |
|
|
|
|
if (this->AddNTCP2Session (conn)) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
auto timer = std::make_shared<boost::asio::deadline_timer>(GetService()); |
|
|
|
|
auto timeout = NTCP2_CONNECT_TIMEOUT * 5; |
|
|
|
|
conn->SetTerminationTimeout(timeout * 2); |
|
|
|
@ -1431,11 +1458,10 @@ namespace transport
@@ -1431,11 +1458,10 @@ namespace transport
|
|
|
|
|
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)); |
|
|
|
|
conn->GetSocket ().async_connect (*m_ProxyEndpoint, std::bind (&NTCP2Server::HandleProxyConnect, this, std::placeholders::_1, conn, timer)); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
@ -1447,7 +1473,7 @@ namespace transport
@@ -1447,7 +1473,7 @@ namespace transport
|
|
|
|
|
m_ProxyPort = port; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void NTCP2Server::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 addrtype) |
|
|
|
|
void NTCP2Server::HandleProxyConnect(const boost::system::error_code& ecode, std::shared_ptr<NTCP2Session> conn, std::shared_ptr<boost::asio::deadline_timer> timer) |
|
|
|
|
{ |
|
|
|
|
if (ecode) |
|
|
|
|
{ |
|
|
|
@ -1473,7 +1499,7 @@ namespace transport
@@ -1473,7 +1499,7 @@ namespace transport
|
|
|
|
|
}); |
|
|
|
|
auto readbuff = std::make_shared<std::vector<uint8_t> >(2); |
|
|
|
|
boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff->data (), 2), |
|
|
|
|
[this, readbuff, timer, conn, host, port, addrtype](const boost::system::error_code & ec, std::size_t transferred) |
|
|
|
|
[this, readbuff, timer, conn](const boost::system::error_code & ec, std::size_t transferred) |
|
|
|
|
{ |
|
|
|
|
if(ec) |
|
|
|
|
{ |
|
|
|
@ -1486,7 +1512,7 @@ namespace transport
@@ -1486,7 +1512,7 @@ namespace transport
|
|
|
|
|
{ |
|
|
|
|
if((*readbuff)[1] == 0x00) |
|
|
|
|
{ |
|
|
|
|
AfterSocksHandshake(conn, timer, host, port, addrtype); |
|
|
|
|
AfterSocksHandshake(conn, timer); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
else if ((*readbuff)[1] == 0xff) |
|
|
|
@ -1506,13 +1532,14 @@ namespace transport
@@ -1506,13 +1532,14 @@ namespace transport
|
|
|
|
|
} |
|
|
|
|
case eHTTPProxy: |
|
|
|
|
{ |
|
|
|
|
auto& ep = conn->GetRemoteEndpoint (); |
|
|
|
|
i2p::http::HTTPReq req; |
|
|
|
|
req.method = "CONNECT"; |
|
|
|
|
req.version ="HTTP/1.1"; |
|
|
|
|
if(addrtype == eIP6Address) |
|
|
|
|
req.uri = "[" + host + "]:" + std::to_string(port); |
|
|
|
|
if(ep.address ().is_v6 ()) |
|
|
|
|
req.uri = "[" + ep.address ().to_string() + "]:" + std::to_string(ep.port ()); |
|
|
|
|
else |
|
|
|
|
req.uri = host + ":" + std::to_string(port); |
|
|
|
|
req.uri = ep.address ().to_string() + ":" + std::to_string(ep.port ()); |
|
|
|
|
|
|
|
|
|
boost::asio::streambuf writebuff; |
|
|
|
|
std::ostream out(&writebuff); |
|
|
|
@ -1566,7 +1593,7 @@ namespace transport
@@ -1566,7 +1593,7 @@ namespace transport
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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) |
|
|
|
|
{ |
|
|
|
|
// build request
|
|
|
|
|
size_t sz = 6; // header + port
|
|
|
|
@ -1576,27 +1603,28 @@ namespace transport
@@ -1576,27 +1603,28 @@ namespace transport
|
|
|
|
|
(*buff)[1] = 0x01; |
|
|
|
|
(*buff)[2] = 0x00; |
|
|
|
|
|
|
|
|
|
if(addrtype == eIP4Address) |
|
|
|
|
auto& ep = conn->GetRemoteEndpoint (); |
|
|
|
|
if(ep.address ().is_v4 ()) |
|
|
|
|
{ |
|
|
|
|
(*buff)[3] = 0x01; |
|
|
|
|
auto addrbytes = boost::asio::ip::address::from_string(host).to_v4().to_bytes(); |
|
|
|
|
auto addrbytes = ep.address ().to_v4().to_bytes(); |
|
|
|
|
sz += 4; |
|
|
|
|
memcpy(buff->data () + 4, addrbytes.data(), 4); |
|
|
|
|
} |
|
|
|
|
else if (addrtype == eIP6Address) |
|
|
|
|
else if (ep.address ().is_v6 ()) |
|
|
|
|
{ |
|
|
|
|
(*buff)[3] = 0x04; |
|
|
|
|
auto addrbytes = boost::asio::ip::address::from_string(host).to_v6().to_bytes(); |
|
|
|
|
auto addrbytes = ep.address ().to_v6().to_bytes(); |
|
|
|
|
sz += 16; |
|
|
|
|
memcpy(buff->data () + 4, addrbytes.data(), 16); |
|
|
|
|
} |
|
|
|
|
else if (addrtype == eHostname) |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
// We mustn't really fall here because all connections are made to IP addresses
|
|
|
|
|
LogPrint(eLogError, "NTCP2: Tried to connect to domain name via socks proxy"); |
|
|
|
|
LogPrint(eLogError, "NTCP2: Tried to connect to unexpected address via proxy"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
htobe16buf(buff->data () + sz - 2, port); |
|
|
|
|
htobe16buf(buff->data () + sz - 2, ep.port ()); |
|
|
|
|
boost::asio::async_write(conn->GetSocket(), boost::asio::buffer(buff->data (), sz), boost::asio::transfer_all(), |
|
|
|
|
[buff](const boost::system::error_code & ec, std::size_t written) |
|
|
|
|
{ |
|
|
|
@ -1623,11 +1651,23 @@ namespace transport
@@ -1623,11 +1651,23 @@ namespace transport
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if(!e) |
|
|
|
|
i2p::data::netdb.SetUnreachable (conn->GetRemoteIdentity ()->GetIdentHash (), true); |
|
|
|
|
timer->cancel(); |
|
|
|
|
conn->Terminate(); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void NTCP2Server::SetLocalAddress (const boost::asio::ip::address& localAddress) |
|
|
|
|
{ |
|
|
|
|
auto addr = std::make_shared<boost::asio::ip::tcp::endpoint>(boost::asio::ip::tcp::endpoint(localAddress, 0)); |
|
|
|
|
if (localAddress.is_v6 ()) |
|
|
|
|
{ |
|
|
|
|
if (i2p::util::net::IsYggdrasilAddress (localAddress)) |
|
|
|
|
m_YggdrasilAddress = addr; |
|
|
|
|
else |
|
|
|
|
m_Address6 = addr; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
m_Address4 = addr; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|