diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 2a9955c2..94609101 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -277,6 +277,7 @@ namespace config { ("ssu2.enabled", value()->default_value(true), "Enable SSU2 (default: enabled)") ("ssu2.published", value()->default_value(true), "Publish SSU2 (default: enabled)") ("ssu2.port", value()->default_value(0), "Port to listen for incoming SSU2 packets (default: auto)") + ("ssu2.proxy", value()->default_value(""), "Socks5 proxy URL for SSU2 transport") ; options_description nettime("Time sync options"); diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index c323002c..7f6fbd42 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -42,6 +42,11 @@ namespace transport if (!address) continue; if (address->transportStyle == i2p::data::RouterInfo::eTransportSSU2) { + if (m_IsThroughProxy) + { + found = true; + break; // we don't need port for proxy + } auto port = address->port; if (!port) { @@ -84,7 +89,11 @@ namespace transport } } if (found) + { m_ReceiveService.Start (); + if (m_IsThroughProxy) + ConnectToProxy (); + } ScheduleTermination (); ScheduleResend (false); } @@ -257,7 +266,10 @@ namespace transport { if (packet) { - ProcessNextPacket (packet->buf, packet->len, packet->from); + if (m_IsThroughProxy) + ProcessNextPacketFromProxy (packet->buf, packet->len); + else + ProcessNextPacket (packet->buf, packet->len, packet->from); m_PacketsPool.ReleaseMt (packet); if (m_LastSession && m_LastSession->GetState () != eSSU2SessionStateTerminated) m_LastSession->FlushData (); @@ -266,8 +278,12 @@ namespace transport void SSU2Server::HandleReceivedPackets (std::vector packets) { - for (auto& packet: packets) - ProcessNextPacket (packet->buf, packet->len, packet->from); + if (m_IsThroughProxy) + for (auto& packet: packets) + ProcessNextPacketFromProxy (packet->buf, packet->len); + else + for (auto& packet: packets) + ProcessNextPacket (packet->buf, packet->len, packet->from); m_PacketsPool.ReleaseMt (packets); if (m_LastSession && m_LastSession->GetState () != eSSU2SessionStateTerminated) m_LastSession->FlushData (); @@ -479,6 +495,11 @@ namespace transport void SSU2Server::Send (const uint8_t * header, size_t headerLen, const uint8_t * payload, size_t payloadLen, const boost::asio::ip::udp::endpoint& to) { + if (m_IsThroughProxy) + { + SendThroughProxy (header, headerLen, nullptr, 0, payload, payloadLen, to); + return; + } std::vector bufs { boost::asio::buffer (header, headerLen), @@ -498,6 +519,11 @@ namespace transport void SSU2Server::Send (const uint8_t * header, size_t headerLen, const uint8_t * headerX, size_t headerXLen, const uint8_t * payload, size_t payloadLen, const boost::asio::ip::udp::endpoint& to) { + if (m_IsThroughProxy) + { + SendThroughProxy (header, headerLen, headerX, headerXLen, payload, payloadLen, to); + return; + } std::vector bufs { boost::asio::buffer (header, headerLen), @@ -1250,5 +1276,23 @@ namespace transport ReadUDPAssociateSocket (); }); } + + bool SSU2Server::SetProxy (const std::string& address, uint16_t port) + { + boost::system::error_code ecode; + auto addr = boost::asio::ip::address::from_string (address, ecode); + if (!ecode && !addr.is_unspecified () && port) + { + m_IsThroughProxy = true; + m_ProxyEndpoint.reset (new boost::asio::ip::tcp::endpoint (addr, port)); + } + else + { + if (ecode) + LogPrint (eLogError, "SSU2: Invalid proxy address ", address, " ", ecode.message()); + return false; + } + return true; + } } } diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 6eff7109..767a9eb8 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -57,6 +57,7 @@ namespace transport void Stop (); boost::asio::io_service& GetService () { return GetIOService (); }; void SetLocalAddress (const boost::asio::ip::address& localAddress); + bool SetProxy (const std::string& address, uint16_t port); bool IsSupported (const boost::asio::ip::address& addr) const; uint16_t GetPort (bool v4) const; bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; }; diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 6dac23de..04ded36f 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -218,7 +218,23 @@ namespace transport } } // create SSU2 server - if (enableSSU2) m_SSU2Server = new SSU2Server (); + if (enableSSU2) + { + m_SSU2Server = new SSU2Server (); + std::string ssu2proxy; i2p::config::GetOption("ssu2.proxy", ssu2proxy); + if (!ssu2proxy.empty()) + { + if (proxyurl.parse (ssu2proxy) && proxyurl.schema == "socks") + { + if (m_SSU2Server->SetProxy (proxyurl.host, proxyurl.port)) + i2p::context.SetStatus (eRouterStatusProxy); + else + LogPrint(eLogError, "Transports: Can't set SSU2 proxy ", ssu2proxy); + } + else + LogPrint(eLogError, "Transports: Invalid SSU2 proxy URL ", ssu2proxy); + } + } // bind to interfaces bool ipv4; i2p::config::GetOption("ipv4", ipv4);