From b850a33d65d94b3235af757aec295b841a321b35 Mon Sep 17 00:00:00 2001 From: acetone <63557806+freeacetone@users.noreply.github.com> Date: Mon, 20 Jul 2026 14:31:11 +0300 Subject: [PATCH] ban router on invalid block in SSU2 SessionConfirmed --- libi2pd/SSU2Session.cpp | 17 ++++++++++++++++- libi2pd/SSU2Session.h | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index abc17b8f..8755cc06 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -86,7 +86,7 @@ namespace transport m_Server (server), m_Address (addr), m_RemoteTransports (0), m_RemotePeerTestTransports (0), m_RemoteVersion (0), m_DestConnID (0), m_SourceConnID (0), m_State (eSSU2SessionStateUnknown), m_SendPacketNum (0), m_ReceivePacketNum (0), m_LastDatetimeSentPacketNum (0), - m_IsDataReceived (false), m_RTT (SSU2_UNKNOWN_RTT), + m_IsDataReceived (false), m_IsInvalidMessage (false), m_RTT (SSU2_UNKNOWN_RTT), m_MsgLocalExpirationTimeout (I2NP_MESSAGE_LOCAL_EXPIRATION_TIMEOUT_MAX), m_MsgLocalSemiExpirationTimeout (I2NP_MESSAGE_LOCAL_EXPIRATION_TIMEOUT_MAX / 2), m_WindowSize (SSU2_MIN_WINDOW_SIZE), @@ -1428,6 +1428,13 @@ namespace transport // handle other blocks HandlePayload (decryptedPayload.data () + riSize + 3, decryptedPayload.size () - riSize - 3); + if (m_IsInvalidMessage) + { + LogPrint (eLogError, "SSU2: Invalid block in SessionConfirmed from ", + i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ()), ". Banned"); + i2p::transport::transports.AddBan (m_RemoteEndpoint.address ()); + return false; + } Established (); if (ri->GetCongestion () == i2p::data::RouterInfo::eRejectAll) @@ -1787,6 +1794,7 @@ namespace transport if (nextMsg->offset + size + 7 > nextMsg->maxLen) // 7 more bytes for full I2NP header { LogPrint (eLogWarning, "SSU2: I2NP message block size ", size, " exceeds max message size ", nextMsg->maxLen); + m_IsInvalidMessage = true; break; } nextMsg->len = nextMsg->offset + size + 7; // 7 more bytes for full I2NP header @@ -2127,6 +2135,7 @@ namespace transport if (msg->offset + len + 7 > msg->maxLen) { LogPrint (eLogWarning, "SSU2: First fragment size ", len, " exceeds max message size ", msg->maxLen); + m_IsInvalidMessage = true; return; } uint32_t msgID; memcpy (&msgID, buf + 1, 4); @@ -2161,6 +2170,12 @@ namespace transport void SSU2Session::HandleFollowOnFragment (const uint8_t * buf, size_t len) { if (len < 5) return; + if (len - 5 > SSU2_MAX_PACKET_SIZE) + { + LogPrint (eLogWarning, "SSU2: Follow-on fragment size ", len, " exceeds max packet size"); + m_IsInvalidMessage = true; + return; + } uint8_t fragmentNum = buf[0] >> 1; if (!fragmentNum || fragmentNum >= SSU2_MAX_NUM_FRAGMENTS) { diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index ff28c13d..180e95cb 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -402,7 +402,7 @@ namespace transport i2p::I2NPMessagesHandler m_Handler; std::list > m_IntermediateQueue; // from transports mutable std::mutex m_IntermediateQueueMutex; - bool m_IsDataReceived; + bool m_IsDataReceived, m_IsInvalidMessage; double m_RTT; int m_MsgLocalExpirationTimeout; int m_MsgLocalSemiExpirationTimeout;