diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index f06bf5c9..f02fde46 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2022, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -272,8 +272,9 @@ namespace config { "1.pool.ntp.org," "2.pool.ntp.org," "3.pool.ntp.org" - ), "Comma separated list of NTCP servers") + ), "Comma separated list of NTP servers") ("nettime.ntpsyncinterval", value()->default_value(72), "NTP sync interval in hours (default: 72)") + ("nettime.frompeers", value()->default_value(true), "Sync clock from transport peers (default: enabled)") ; options_description persist("Network information persisting options"); diff --git a/libi2pd/SSU.cpp b/libi2pd/SSU.cpp index 56da56d6..5df3ac05 100644 --- a/libi2pd/SSU.cpp +++ b/libi2pd/SSU.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2022, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -11,8 +11,9 @@ #include "Timestamp.h" #include "RouterContext.h" #include "NetDb.hpp" -#include "SSU.h" +#include "Config.h" #include "util.h" +#include "SSU.h" #ifdef __linux__ #include @@ -33,7 +34,8 @@ namespace transport m_Endpoint (boost::asio::ip::udp::v4 (), port), m_EndpointV6 (boost::asio::ip::udp::v6 (), port), m_Socket (m_ReceiversService), m_SocketV6 (m_ReceiversServiceV6), m_IntroducersUpdateTimer (m_Service), m_IntroducersUpdateTimerV6 (m_Service), - m_PeerTestsCleanupTimer (m_Service), m_TerminationTimer (m_Service), m_TerminationTimerV6 (m_Service) + m_PeerTestsCleanupTimer (m_Service), m_TerminationTimer (m_Service), m_TerminationTimerV6 (m_Service), + m_IsSyncClockFromPeers (true) { } @@ -90,6 +92,7 @@ namespace transport void SSUServer::Start () { + i2p::config::GetOption("nettime.frompeers", m_IsSyncClockFromPeers); m_IsRunning = true; m_Thread = new std::thread (std::bind (&SSUServer::Run, this)); if (context.SupportsV4 ()) diff --git a/libi2pd/SSU.h b/libi2pd/SSU.h index f763c671..25ce4d40 100644 --- a/libi2pd/SSU.h +++ b/libi2pd/SSU.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2022, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -69,6 +69,7 @@ namespace transport i2p::util::MemoryPool& GetSentMessagesPool () { return m_SentMessagesPool; }; uint16_t GetPort () const { return m_Endpoint.port (); }; + bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; }; void SetLocalAddress (const boost::asio::ip::address& localAddress); void Send (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to); @@ -136,6 +137,7 @@ namespace transport boost::asio::ip::udp::socket m_Socket, m_SocketV6; boost::asio::deadline_timer m_IntroducersUpdateTimer, m_IntroducersUpdateTimerV6, m_PeerTestsCleanupTimer, m_TerminationTimer, m_TerminationTimerV6; + bool m_IsSyncClockFromPeers; std::list m_Introducers, m_IntroducersV6; // introducers we are connected to std::map > m_Sessions, m_SessionsV6; std::map > m_Relays; // we are introducer diff --git a/libi2pd/SSUSession.cpp b/libi2pd/SSUSession.cpp index 54ad5604..9fce9e85 100644 --- a/libi2pd/SSUSession.cpp +++ b/libi2pd/SSUSession.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2022, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -274,16 +274,7 @@ namespace transport s.Insert (payload, 8); // relayTag and signed on time m_RelayTag = bufbe32toh (payload); payload += 4; // relayTag - if (ourIP.is_v4 () && i2p::context.GetStatus () == eRouterStatusTesting) - { - auto ts = i2p::util::GetSecondsSinceEpoch (); - uint32_t signedOnTime = bufbe32toh(payload); - if (signedOnTime < ts - SSU_CLOCK_SKEW || signedOnTime > ts + SSU_CLOCK_SKEW) - { - LogPrint (eLogError, "SSU: Clock skew detected ", (int)ts - signedOnTime, ". Check your clock"); - i2p::context.SetError (eRouterErrorClockSkew); - } - } + uint32_t signedOnTime = bufbe32toh(payload); payload += 4; // signed on time // decrypt signature size_t signatureLen = m_RemoteIdentity->GetSignatureLen (); @@ -295,6 +286,24 @@ namespace transport // verify signature if (s.Verify (m_RemoteIdentity, payload)) { + if (ourIP.is_v4 () && i2p::context.GetStatus () == eRouterStatusTesting) + { + auto ts = i2p::util::GetSecondsSinceEpoch (); + int offset = (int)ts - signedOnTime; + if (m_Server.IsSyncClockFromPeers ()) + { + if (std::abs (offset) > SSU_CLOCK_THRESHOLD) + { + LogPrint (eLogWarning, "SSU: Clock adjusted by ", -offset, " seconds"); + i2p::util::AdjustTimeOffset (-offset); + } + } + else if (std::abs (offset) > SSU_CLOCK_SKEW) + { + LogPrint (eLogError, "SSU: Clock skew detected ", offset, ". Check your clock"); + i2p::context.SetError (eRouterErrorClockSkew); + } + } LogPrint (eLogInfo, "SSU: Our external address is ", ourIP.to_string (), ":", ourPort); if (!i2p::util::net::IsInReservedRange (ourIP)) { diff --git a/libi2pd/SSUSession.h b/libi2pd/SSUSession.h index 4f7fa0f5..535de328 100644 --- a/libi2pd/SSUSession.h +++ b/libi2pd/SSUSession.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2022, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -36,6 +36,7 @@ namespace transport const int SSU_CONNECT_TIMEOUT = 5; // 5 seconds const int SSU_TERMINATION_TIMEOUT = 330; // 5.5 minutes const int SSU_CLOCK_SKEW = 60; // in seconds + const int SSU_CLOCK_THRESHOLD = 15; // in seconds, if more we should adjust const size_t SSU_MAX_I2NP_MESSAGE_SIZE = 32768; // payload types (4 bits) diff --git a/libi2pd/Timestamp.cpp b/libi2pd/Timestamp.cpp index 3673a58c..c8d752a6 100644 --- a/libi2pd/Timestamp.cpp +++ b/libi2pd/Timestamp.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2022, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -250,5 +250,10 @@ namespace util sprintf(date, "%04i%02i%02i", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); #endif } + + void AdjustTimeOffset (int64_t offset) + { + g_TimeOffset += offset; + } } } diff --git a/libi2pd/Timestamp.h b/libi2pd/Timestamp.h index b46f423d..518cd055 100644 --- a/libi2pd/Timestamp.h +++ b/libi2pd/Timestamp.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2022, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -26,7 +26,8 @@ namespace util void GetCurrentDate (char * date); // returns date as YYYYMMDD string, 9 bytes void GetDateString (uint64_t timestamp, char * date); // timestap is seconds since epoch, returns date as YYYYMMDD string, 9 bytes - + void AdjustTimeOffset (int64_t offset); // in seconds from current + class NTPTimeSync { public: