From ed5c5339825f750ef863cfb2b8cb07f9fc1d88f6 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 2 Aug 2022 20:02:55 -0400 Subject: [PATCH] recgnize symmetric NAT from SSU2 --- daemon/HTTPServer.cpp | 8 +++--- libi2pd/RouterContext.cpp | 3 ++- libi2pd/RouterContext.h | 4 ++- libi2pd/SSU2.cpp | 8 ++++++ libi2pd/SSU2.h | 1 + libi2pd/SSU2Session.cpp | 54 +++++++++++++++++++++++++++++++-------- libi2pd/SSU2Session.h | 1 + 7 files changed, 63 insertions(+), 16 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 2a083dea..d236ca3d 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -222,7 +222,7 @@ namespace http { s << "" << tr("ERROR") << ": " << string << "
\r\n"; } - static void ShowNetworkStatus (std::stringstream& s, RouterStatus status) + static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, RouterError error) { switch (status) { @@ -235,7 +235,7 @@ namespace http { case eRouterStatusError: { s << tr("Error"); - switch (i2p::context.GetError ()) + switch (error) { case eRouterErrorClockSkew: s << " - " << tr("Clock skew"); @@ -260,12 +260,12 @@ namespace http { ShowUptime(s, i2p::context.GetUptime ()); s << "
\r\n"; s << "" << tr("Network status") << ": "; - ShowNetworkStatus (s, i2p::context.GetStatus ()); + ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetError ()); s << "
\r\n"; if (i2p::context.SupportsV6 ()) { s << "" << tr("Network status v6") << ": "; - ShowNetworkStatus (s, i2p::context.GetStatusV6 ()); + ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetErrorV6 ()); s << "
\r\n"; } #if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY)) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 636d47ce..2095a465 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -29,7 +29,7 @@ namespace i2p RouterContext::RouterContext (): m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false), m_ShareRatio (100), m_Status (eRouterStatusUnknown), m_StatusV6 (eRouterStatusUnknown), - m_Error (eRouterErrorNone), m_NetID (I2PD_NET_ID) + m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone), m_NetID (I2PD_NET_ID) { } @@ -263,6 +263,7 @@ namespace i2p if (status != m_StatusV6) { m_StatusV6 = status; + m_ErrorV6 = eRouterErrorNone; switch (m_StatusV6) { case eRouterStatusOK: diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index 4946b7ca..9e02b5d5 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -109,6 +109,8 @@ namespace garlic RouterStatus GetStatusV6 () const { return m_StatusV6; }; void SetStatusV6 (RouterStatus status); void SetStatusV6SSU2 (RouterStatus status); + RouterError GetErrorV6 () const { return m_ErrorV6; }; + void SetErrorV6 (RouterError error) { m_StatusV6 = eRouterStatusError; m_ErrorV6 = error; }; int GetNetID () const { return m_NetID; }; void SetNetID (int netID) { m_NetID = netID; }; bool DecryptTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data); @@ -197,7 +199,7 @@ namespace garlic uint64_t m_BandwidthLimit; // allowed bandwidth int m_ShareRatio; RouterStatus m_Status, m_StatusV6; - RouterError m_Error; + RouterError m_Error, m_ErrorV6; int m_NetID; std::mutex m_GarlicMutex; std::unique_ptr m_NTCP2Keys; diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 551dd148..e551010a 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -155,6 +155,14 @@ namespace transport } return false; } + + uint16_t SSU2Server::GetPort (bool v4) const + { + boost::system::error_code ec; + boost::asio::ip::udp::endpoint ep = v4 ? m_SocketV4.local_endpoint (ec) : m_SocketV6.local_endpoint (ec); + if (ec) return 0; + return ep.port (); + } boost::asio::ip::udp::socket& SSU2Server::OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint) { diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 010c2c00..00e944e4 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -55,6 +55,7 @@ namespace transport boost::asio::io_service& GetService () { return GetIOService (); }; void SetLocalAddress (const boost::asio::ip::address& localAddress); bool IsSupported (const boost::asio::ip::address& addr) const; + uint16_t GetPort (bool v4) const; void AddSession (std::shared_ptr session); void RemoveSession (uint64_t connID); diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 475d7cef..e463e6fc 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1370,16 +1370,9 @@ namespace transport HandleAck (buf + offset, size); break; case eSSU2BlkAddress: - { - boost::asio::ip::udp::endpoint ep; - if (ExtractEndpoint (buf + offset, size, ep)) - { - LogPrint (eLogInfo, "SSU2: Our external address is ", ep); - if (!i2p::util::net::IsInReservedRange (ep.address ())) - i2p::context.UpdateAddress (ep.address ()); - } - break; - } + LogPrint (eLogDebug, "SSU2: Address"); + HandleAddress (buf + offset, size); + break; case eSSU2BlkIntroKey: break; case eSSU2BlkRelayTagRequest: @@ -1482,6 +1475,47 @@ namespace transport } } + void SSU2Session::HandleAddress (const uint8_t * buf, size_t len) + { + boost::asio::ip::udp::endpoint ep; + if (ExtractEndpoint (buf, len, ep)) + { + LogPrint (eLogInfo, "SSU2: Our external address is ", ep); + if (!i2p::util::net::IsInReservedRange (ep.address ())) + { + i2p::context.UpdateAddress (ep.address ()); + // check our port + bool isV4 = ep.address ().is_v4 (); + if (ep.port () != m_Server.GetPort (isV4)) + { + if (isV4) + { + if (i2p::context.GetStatus () == eRouterStatusTesting) + i2p::context.SetError (eRouterErrorSymmetricNAT); + } + else + { + if (i2p::context.GetStatusV6 () == eRouterStatusTesting) + i2p::context.SetErrorV6 (eRouterErrorSymmetricNAT); + } + } + else + { + if (isV4) + { + if (i2p::context.GetStatus () == eRouterStatusError && i2p::context.GetError () == eRouterErrorSymmetricNAT) + i2p::context.SetStatus (eRouterStatusTesting); + } + else + { + if (i2p::context.GetStatusV6 () == eRouterStatusError && i2p::context.GetErrorV6 () == eRouterErrorSymmetricNAT) + i2p::context.SetStatusV6 (eRouterStatusTesting); + } + } + } + } + } + void SSU2Session::HandleFirstFragment (const uint8_t * buf, size_t len) { uint32_t msgID; memcpy (&msgID, buf + 1, 4); diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 3971358c..eae593c2 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -278,6 +278,7 @@ namespace transport void HandlePayload (const uint8_t * buf, size_t len); void HandleAck (const uint8_t * buf, size_t len); void HandleAckRange (uint32_t firstPacketNum, uint32_t lastPacketNum, uint64_t ts); + void HandleAddress (const uint8_t * buf, size_t len); bool ExtractEndpoint (const uint8_t * buf, size_t size, boost::asio::ip::udp::endpoint& ep); size_t CreateEndpoint (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep); std::shared_ptr FindLocalAddress () const;