From 1419745a5d848ac283225230d1a76209253a4d61 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 17 Oct 2024 21:09:37 -0400 Subject: [PATCH] recognize symmetric NAT from peer test msg 7 --- libi2pd/SSU2OutOfSession.cpp | 29 +++++++++++++++++++++++++++++ libi2pd/SSU2OutOfSession.h | 2 ++ libi2pd/SSU2Session.h | 5 +++-- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/libi2pd/SSU2OutOfSession.cpp b/libi2pd/SSU2OutOfSession.cpp index c337938e..262f93a9 100644 --- a/libi2pd/SSU2OutOfSession.cpp +++ b/libi2pd/SSU2OutOfSession.cpp @@ -65,6 +65,12 @@ namespace transport return true; } + void SSU2PeerTestSession::HandleAddress (const uint8_t * buf, size_t len) + { + if (!ExtractEndpoint (buf, len, m_OurEndpoint)) + LogPrint (eLogWarning, "SSU2: Can't hanlde address block from peer test message"); + } + void SSU2PeerTestSession::HandlePeerTest (const uint8_t * buf, size_t len) { // msgs 5-7 @@ -112,6 +118,29 @@ namespace transport case 7: // Alice from Charlie 2 { m_PeerTestResendTimer.cancel (); // no more msg 6 resends + if (m_MsgNumReceived < 5 && m_OurEndpoint.port ()) // msg 5 was not received + { + if (m_OurEndpoint.address ().is_v4 ()) // ipv4 + { + if (i2p::context.GetStatus () == eRouterStatusFirewalled) + { + if (m_OurEndpoint.port () != GetServer ().GetPort (true)) + i2p::context.SetError (eRouterErrorSymmetricNAT); + else if (i2p::context.GetError () == eRouterErrorSymmetricNAT) + i2p::context.SetError (eRouterErrorNone); + } + } + else + { + if (i2p::context.GetStatusV6 () == eRouterStatusFirewalled) + { + if (m_OurEndpoint.port () != GetServer ().GetPort (false)) + i2p::context.SetErrorV6 (eRouterErrorSymmetricNAT); + else if (i2p::context.GetErrorV6 () == eRouterErrorSymmetricNAT) + i2p::context.SetErrorV6 (eRouterErrorNone); + } + } + } GetServer ().AddConnectedRecently (GetRemoteEndpoint (), i2p::util::GetSecondsSinceEpoch ()); GetServer ().RequestRemoveSession (GetConnID ()); break; diff --git a/libi2pd/SSU2OutOfSession.h b/libi2pd/SSU2OutOfSession.h index 6f2a9fbd..e8c55c3c 100644 --- a/libi2pd/SSU2OutOfSession.h +++ b/libi2pd/SSU2OutOfSession.h @@ -41,6 +41,7 @@ namespace transport void SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen, bool delayed = false); // PeerTest message void SendPeerTest (uint8_t msg); // send or resend m_SignedData void HandlePeerTest (const uint8_t * buf, size_t len) override; + void HandleAddress (const uint8_t * buf, size_t len) override; void ScheduleResend (uint8_t msg); @@ -50,6 +51,7 @@ namespace transport bool m_IsConnectedRecently, m_IsStatusChanged; std::vector m_SignedData; // for resends boost::asio::deadline_timer m_PeerTestResendTimer; + boost::asio::ip::udp::endpoint m_OurEndpoint; // as seen by peer }; const int SSU2_HOLE_PUNCH_RESEND_INTERVAL = 1000; // in milliseconds diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index ae0f18f4..e27671f8 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -296,6 +296,8 @@ namespace transport size_t CreateAddressBlock (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep); size_t CreatePaddingBlock (uint8_t * buf, size_t len, size_t minSize = 0); size_t CreatePeerTestBlock (uint8_t * buf, size_t len, uint8_t msg, SSU2PeerTestCode code, const uint8_t * routerHash, const uint8_t * signedData, size_t signedDataLen); + + bool ExtractEndpoint (const uint8_t * buf, size_t size, boost::asio::ip::udp::endpoint& ep); private: @@ -328,8 +330,7 @@ namespace transport void HandleRouterInfo (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); + virtual void HandleAddress (const uint8_t * buf, size_t len); size_t CreateEndpoint (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep); std::shared_ptr FindLocalAddress () const; void AdjustMaxPayloadSize ();