From 440516e95fcc6708db2e705168caadd1ac4c93a0 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 18 Sep 2016 18:42:21 -0400 Subject: [PATCH 01/10] detect clock skew --- HTTPServer.cpp | 1 + RouterContext.h | 3 ++- SSUSession.cpp | 18 ++++++++++++++++++ SSUSession.h | 1 + 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 2e9a02ca..2e469f98 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -180,6 +180,7 @@ namespace http { case eRouterStatusOK: s << "OK"; break; case eRouterStatusTesting: s << "Testing"; break; case eRouterStatusFirewalled: s << "Firewalled"; break; + case eRouterStatusError: s << "Error"; break; default: s << "Unknown"; } s << "
\r\n"; diff --git a/RouterContext.h b/RouterContext.h index 27e0947d..23c03593 100644 --- a/RouterContext.h +++ b/RouterContext.h @@ -20,7 +20,8 @@ namespace i2p { eRouterStatusOK = 0, eRouterStatusTesting = 1, - eRouterStatusFirewalled = 2 + eRouterStatusFirewalled = 2, + eRouterStatusError = 3 }; class RouterContext: public i2p::garlic::GarlicDestination diff --git a/SSUSession.cpp b/SSUSession.cpp index 26c14570..ca714aed 100644 --- a/SSUSession.cpp +++ b/SSUSession.cpp @@ -272,6 +272,16 @@ namespace transport s.Insert (payload, 8); // relayTag and signed on time m_RelayTag = bufbe32toh (payload); payload += 4; // relayTag + if (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.SetStatus (eRouterStatusError); + } + } payload += 4; // signed on time // decrypt signature size_t signatureLen = m_RemoteIdentity->GetSignatureLen (); @@ -310,6 +320,14 @@ namespace transport SetRemoteIdentity (std::make_shared (payload, identitySize)); m_Data.UpdatePacketSize (m_RemoteIdentity->GetIdentHash ()); payload += identitySize; // identity + auto ts = i2p::util::GetSecondsSinceEpoch (); + uint32_t signedOnTime = bufbe32toh(payload); + if (signedOnTime < ts - SSU_CLOCK_SKEW || signedOnTime > ts + SSU_CLOCK_SKEW) + { + LogPrint (eLogError, "SSU message 'confirmed' time difference ", (int)ts - signedOnTime, " exceeds clock skew"); + Failed (); + return; + } if (m_SignedData) m_SignedData->Insert (payload, 4); // insert Alice's signed on time payload += 4; // signed-on time diff --git a/SSUSession.h b/SSUSession.h index 69669187..4838be2a 100644 --- a/SSUSession.h +++ b/SSUSession.h @@ -27,6 +27,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 // payload types (4 bits) const uint8_t PAYLOAD_TYPE_SESSION_REQUEST = 0; From a64e1b2aa62f28fa0d2e399afb9d23be8c3d1071 Mon Sep 17 00:00:00 2001 From: MXPLRS | Kirill Date: Mon, 19 Sep 2016 20:22:15 +0300 Subject: [PATCH 02/10] add sliders for LeaseSets --- HTTPServer.cpp | 44 +++++++++++++------------------------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 2e469f98..8a63658c 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -345,50 +345,32 @@ namespace http { void ShowLeasesSets(std::stringstream& s) { - s << "
LeaseSets:

"; + s << "
LeaseSets (click on to show info):

\r\n"; + int counter = 1; // for each lease set i2p::data::netdb.VisitLeaseSets( - [&s](const i2p::data::IdentHash dest, std::shared_ptr leaseSet) + [&s, &counter](const i2p::data::IdentHash dest, std::shared_ptr leaseSet) { // create copy of lease set so we extract leases i2p::data::LeaseSet ls(leaseSet->GetBuffer(), leaseSet->GetBufferLen()); - // begin lease set entry s << "
"; - // invalid ? + s << "'>\r\n"; if (!ls.IsValid()) - s << "
!! Invalid !!
"; - // ident - s << "
" << dest.ToBase32() << "
"; - // LeaseSet time - s << "
expires: " << ls.GetExpirationTime() << "
"; - // get non expired leases + s << "
!! Invalid !!
\r\n"; + s << "
\r\n"; + s << "\r\n

\r\n"; + s << "Expires: " << ls.GetExpirationTime() << "
\r\n"; auto leases = ls.GetNonExpiredLeases(); - // show non expired leases - s << "

Non Expired Leases: " << leases.size() << "
"; - // for each lease - s << "
"; + s << "Non Expired Leases: " << leases.size() << "
\r\n"; for ( auto & l : leases ) { - // begin lease - s << "
"; - // gateway - s << "
Gateway: " << l->tunnelGateway.ToBase64() << "
"; - // tunnel id - s << "
TunnelID: " << l->tunnelID << "
"; - // end date - s << "
EndDate: " << l->endDate << "
"; - // end lease - s << "
"; + s << "Gateway: " << l->tunnelGateway.ToBase64() << "
\r\n"; + s << "TunnelID: " << l->tunnelID << "
\r\n"; + s << "EndDate: " << l->endDate << "
\r\n"; } - // end for each lease - s << "
"; - // end lease set entry - s << "
"; - // linebreak - s << "
"; + s << "

\r\n
\r\n\r\n"; } ); // end for each lease set From 7a51407f6d9269b819614329b621f1bbd091bddc Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 19 Sep 2016 21:37:04 -0400 Subject: [PATCH 03/10] show error message in the web-console --- HTTPServer.cpp | 13 ++++++++++++- RouterContext.cpp | 3 ++- RouterContext.h | 11 ++++++++++- SSUSession.cpp | 2 +- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 8a63658c..487e9c83 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -180,7 +180,18 @@ namespace http { case eRouterStatusOK: s << "OK"; break; case eRouterStatusTesting: s << "Testing"; break; case eRouterStatusFirewalled: s << "Firewalled"; break; - case eRouterStatusError: s << "Error"; break; + case eRouterStatusError: + { + s << "Error"; + switch (i2p::context.GetError ()) + { + case eRouterErrorClockSkew: + s << "
Clock skew"; + break; + default: ; + } + break; + } default: s << "Unknown"; } s << "
\r\n"; diff --git a/RouterContext.cpp b/RouterContext.cpp index c92b575b..6824adb8 100644 --- a/RouterContext.cpp +++ b/RouterContext.cpp @@ -18,7 +18,7 @@ namespace i2p RouterContext::RouterContext (): m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false), - m_StartupTime (0), m_Status (eRouterStatusOK ) + m_StartupTime (0), m_Status (eRouterStatusOK), m_Error (eRouterErrorNone) { } @@ -95,6 +95,7 @@ namespace i2p if (status != m_Status) { m_Status = status; + m_Error = eRouterErrorNone; switch (m_Status) { case eRouterStatusOK: diff --git a/RouterContext.h b/RouterContext.h index 23c03593..b89b3140 100644 --- a/RouterContext.h +++ b/RouterContext.h @@ -24,6 +24,12 @@ namespace i2p eRouterStatusError = 3 }; + enum RouterError + { + eRouterErrorNone = 0, + eRouterErrorClockSkew = 1 + }; + class RouterContext: public i2p::garlic::GarlicDestination { public: @@ -50,7 +56,9 @@ namespace i2p uint64_t GetBandwidthLimit () const { return m_BandwidthLimit; }; RouterStatus GetStatus () const { return m_Status; }; void SetStatus (RouterStatus status); - + RouterError GetError () const { return m_Error; }; + void SetError (RouterError error) { m_Status = eRouterStatusError; m_Error = error; }; + void UpdatePort (int port); // called from Daemon void UpdateAddress (const boost::asio::ip::address& host); // called from SSU or Daemon bool AddIntroducer (const i2p::data::RouterInfo::Introducer& introducer); @@ -108,6 +116,7 @@ namespace i2p uint64_t m_StartupTime; // in seconds since epoch uint32_t m_BandwidthLimit; // allowed bandwidth RouterStatus m_Status; + RouterError m_Error; std::mutex m_GarlicMutex; }; diff --git a/SSUSession.cpp b/SSUSession.cpp index ca714aed..5cd59164 100644 --- a/SSUSession.cpp +++ b/SSUSession.cpp @@ -279,7 +279,7 @@ namespace transport 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.SetStatus (eRouterStatusError); + i2p::context.SetError (eRouterErrorClockSkew); } } payload += 4; // signed on time From 315f67225490d8e32078e58208b64147cfddc861 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 21 Sep 2016 12:02:52 -0400 Subject: [PATCH 04/10] Timestamp.cpp added --- Timestamp.cpp | 10 ++++++++++ Timestamp.h | 2 ++ android/jni/Android.mk | 1 + build/CMakeLists.txt | 1 + filelist.mk | 2 +- qt/i2pd_qt/i2pd_qt.pro | 3 ++- 6 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 Timestamp.cpp diff --git a/Timestamp.cpp b/Timestamp.cpp new file mode 100644 index 00000000..f935df62 --- /dev/null +++ b/Timestamp.cpp @@ -0,0 +1,10 @@ +#include "Timestamp.h" + +namespace i2p +{ +namespace util +{ + std::chrono::system_clock::duration g_TimeOffset = std::chrono::system_clock::duration::zero (); +} +} + diff --git a/Timestamp.h b/Timestamp.h index d48cb164..2e61d856 100644 --- a/Timestamp.h +++ b/Timestamp.h @@ -8,6 +8,8 @@ namespace i2p { namespace util { + extern std::chrono::system_clock::duration g_TimeOffset; + inline uint64_t GetMillisecondsSinceEpoch () { return std::chrono::duration_cast( diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 90a679b2..a31fcfb2 100755 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -57,6 +57,7 @@ LOCAL_SRC_FILES := DaemonAndroid.cpp i2pd_android.cpp \ ../../TunnelEndpoint.cpp \ ../../TunnelGateway.cpp \ ../../TunnelPool.cpp \ + ../../Timestamp.cpp \ ../../util.cpp \ ../../i2pd.cpp ../../UPnP.cpp diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 61b8fdf9..95f223ef 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -55,6 +55,7 @@ set (LIBI2PD_SRC "${CMAKE_SOURCE_DIR}/Datagram.cpp" "${CMAKE_SOURCE_DIR}/Family.cpp" "${CMAKE_SOURCE_DIR}/Signature.cpp" + "${CMAKE_SOURCE_DIR}/Timestamp.cpp" "${CMAKE_SOURCE_DIR}/api.cpp" ) diff --git a/filelist.mk b/filelist.mk index db243866..cb1263e3 100644 --- a/filelist.mk +++ b/filelist.mk @@ -5,7 +5,7 @@ LIB_SRC = \ SSUSession.cpp SSUData.cpp Streaming.cpp Identity.cpp TransitTunnel.cpp \ Transports.cpp Tunnel.cpp TunnelEndpoint.cpp TunnelPool.cpp TunnelGateway.cpp \ Destination.cpp Base.cpp I2PEndian.cpp FS.cpp Config.cpp Family.cpp \ - Config.cpp HTTP.cpp util.cpp api.cpp + Config.cpp HTTP.cpp Timestamp.cpp util.cpp api.cpp LIB_CLIENT_SRC = \ AddressBook.cpp BOB.cpp ClientContext.cpp I2PTunnel.cpp I2PService.cpp \ diff --git a/qt/i2pd_qt/i2pd_qt.pro b/qt/i2pd_qt/i2pd_qt.pro index 90ab6c10..0972f65c 100644 --- a/qt/i2pd_qt/i2pd_qt.pro +++ b/qt/i2pd_qt/i2pd_qt.pro @@ -35,7 +35,8 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \ ../../RouterInfo.cpp ../../SAM.cpp ../../Signature.cpp ../../SOCKS.cpp ../../SSU.cpp \ ../../SSUData.cpp ../../SSUSession.cpp ../../Streaming.cpp ../../TransitTunnel.cpp \ ../../Transports.cpp ../../Tunnel.cpp ../../TunnelEndpoint.cpp ../../TunnelGateway.cpp \ - ../../TunnelPool.cpp ../../UPnP.cpp ../../util.cpp ../../Gzip.cpp ../../i2pd.cpp + ../../TunnelPool.cpp ../../UPnP.cpp ../../Gzip.cpp ../../Timestamp.cpp ../../util.cpp \ + ../../i2pd.cpp HEADERS += DaemonQT.h mainwindow.h \ ../../HTTPServer.h ../../I2PControl.h ../../UPnP.h ../../Daemon.h ../../Config.h \ From 2ad927b677415b7f54f92701669d6676a53a3d2f Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 21 Sep 2016 16:18:51 -0400 Subject: [PATCH 05/10] NTP request --- Timestamp.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/Timestamp.cpp b/Timestamp.cpp index f935df62..fbe51ea1 100644 --- a/Timestamp.cpp +++ b/Timestamp.cpp @@ -1,3 +1,7 @@ +#include +#include +#include +#include "I2PEndian.h" #include "Timestamp.h" namespace i2p @@ -5,6 +9,42 @@ namespace i2p namespace util { std::chrono::system_clock::duration g_TimeOffset = std::chrono::system_clock::duration::zero (); + + void SyncTimeWithNTP (const std::string& address) + { + boost::asio::io_service service; + boost::asio::ip::udp::resolver::query query (boost::asio::ip::udp::v4 (), address, "ntp"); + boost::system::error_code ec; + auto it = boost::asio::ip::udp::resolver (service).resolve (query, ec); + if (!ec && it != boost::asio::ip::udp::resolver::iterator()) + { + auto ep = (*it).endpoint (); // take first one + boost::asio::ip::udp::socket socket (service); + socket.open (boost::asio::ip::udp::v4 (), ec); + if (!ec) + { + uint8_t request[48];// 48 bytes NTP request + memset (request, 0, 48); + request[0] = 0x80; // client mode, version 0 + uint8_t * response = new uint8_t[1500]; // MTU + size_t len = 0; + try + { + socket.send_to (boost::asio::buffer (request, 48), ep); + len = socket.receive_from (boost::asio::buffer (response, 1500), ep); + } + catch (std::exception& e) + { + } + if (len >= 8) + { + uint32_t ts = bufbe32toh (response + 4); + if (ts > 2208988800U) ts -= 2208988800U; // 1/1/1970 from 1/1/1900 + } + delete[] response; + } + } + } } } From dba355eccd01398cba53c43878cf4766f2b11008 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 23 Sep 2016 13:15:08 -0400 Subject: [PATCH 06/10] use atomic_store for addresses' list re-assignment --- RouterInfo.cpp | 12 +++++++----- RouterInfo.h | 3 ++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/RouterInfo.cpp b/RouterInfo.cpp index 9b2a4195..68c238ff 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -3,6 +3,8 @@ #include "I2PEndian.h" #include #include +#include +#include #include "version.h" #include "Crypto.h" #include "Base.h" @@ -17,14 +19,14 @@ namespace data { RouterInfo::RouterInfo (): m_Buffer (nullptr) { - m_Addresses = std::make_shared(); // create empty list + m_Addresses = boost::make_shared(); // create empty list } RouterInfo::RouterInfo (const std::string& fullPath): m_FullPath (fullPath), m_IsUpdated (false), m_IsUnreachable (false), m_SupportedTransports (0), m_Caps (0) { - m_Addresses = std::make_shared(); // create empty list + m_Addresses = boost::make_shared(); // create empty list m_Buffer = new uint8_t[MAX_RI_BUFFER_SIZE]; ReadFromFile (); } @@ -32,7 +34,7 @@ namespace data RouterInfo::RouterInfo (const uint8_t * buf, int len): m_IsUpdated (true), m_IsUnreachable (false), m_SupportedTransports (0), m_Caps (0) { - m_Addresses = std::make_shared(); // create empty list + m_Addresses = boost::make_shared(); // create empty list m_Buffer = new uint8_t[MAX_RI_BUFFER_SIZE]; memcpy (m_Buffer, buf, len); m_BufferLen = len; @@ -154,7 +156,7 @@ namespace data s.read ((char *)&m_Timestamp, sizeof (m_Timestamp)); m_Timestamp = be64toh (m_Timestamp); // read addresses - auto addresses = std::make_shared(); + auto addresses = boost::make_shared(); uint8_t numAddresses; s.read ((char *)&numAddresses, sizeof (numAddresses)); if (!s) return; bool introducers = false; @@ -255,7 +257,7 @@ namespace data m_SupportedTransports |= supportedTransports; } } - m_Addresses = addresses; + boost::atomic_store (&m_Addresses, addresses); // read peers uint8_t numPeers; s.read ((char *)&numPeers, sizeof (numPeers)); if (!s) return; diff --git a/RouterInfo.h b/RouterInfo.h index f4c077ef..e8a4ea75 100644 --- a/RouterInfo.h +++ b/RouterInfo.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "Identity.h" #include "Profiling.h" @@ -201,7 +202,7 @@ namespace data uint8_t * m_Buffer; size_t m_BufferLen; uint64_t m_Timestamp; - std::shared_ptr m_Addresses; + boost::shared_ptr m_Addresses; // TODO: use std::shared_ptr and std::atomic_store for gcc >= 4.9 std::map m_Properties; bool m_IsUpdated, m_IsUnreachable; uint8_t m_SupportedTransports, m_Caps; From 08c1359a275b2fb0a03afd4955e309fadbbf347e Mon Sep 17 00:00:00 2001 From: MXPLRS | Kirill Date: Sat, 24 Sep 2016 13:50:14 +0300 Subject: [PATCH 07/10] fixed MiniUPnP link --- docs/build_notes_windows.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/build_notes_windows.md b/docs/build_notes_windows.md index 827d0123..e0fb1d8c 100644 --- a/docs/build_notes_windows.md +++ b/docs/build_notes_windows.md @@ -97,7 +97,7 @@ Requirements for building: * [CMake](https://cmake.org/) (tested with 3.1.3) * [Visual Studio Community Edition](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx) (tested with VS2013 Update 4) * [Boost](http://www.boost.org/) (tested with 1.59) -* Optionally [MiniUPnP](http://miniupnp.free.f) (tested with 1.9), we need only few client headers +* Optionally [MiniUPnP](http://miniupnp.free.fr) (tested with 1.9), we need only few client headers * OpenSSL (tested with 1.0.1p and 1.0.2e), if building from sources (recommended), you'll need as well * [Netwide assembler](www.nasm.us) * Strawberry Perl or ActiveState Perl, do NOT try msys2 perl, it won't work From fa092c01623982895dc55be12cd46326b761cefc Mon Sep 17 00:00:00 2001 From: MXPLRS | Kirill Date: Sat, 24 Sep 2016 14:26:59 +0300 Subject: [PATCH 08/10] Fixed links --- docs/build_notes_windows.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/build_notes_windows.md b/docs/build_notes_windows.md index e0fb1d8c..a217d80d 100644 --- a/docs/build_notes_windows.md +++ b/docs/build_notes_windows.md @@ -27,7 +27,7 @@ msys2 ### x86 (32-bit architecture) -Get install file msys2-i686-20150916.exe from https://msys2.github.io. +Get install file msys2-i686-*.exe from https://msys2.github.io. open MSYS2 Shell (from Start menu). Install all prerequisites and download i2pd source: @@ -44,7 +44,7 @@ make ### x64 (64-bit architecture) -Get install file msys2-x86_64-20150916.exe from https://msys2.github.io. +Get install file msys2-x86_64-*.exe from https://msys2.github.io. open MSYS2 Shell (from Start menu). Install all prerequisites and download i2pd source: @@ -99,7 +99,7 @@ Requirements for building: * [Boost](http://www.boost.org/) (tested with 1.59) * Optionally [MiniUPnP](http://miniupnp.free.fr) (tested with 1.9), we need only few client headers * OpenSSL (tested with 1.0.1p and 1.0.2e), if building from sources (recommended), you'll need as well - * [Netwide assembler](www.nasm.us) + * [Netwide assembler](http://www.nasm.us/) * Strawberry Perl or ActiveState Perl, do NOT try msys2 perl, it won't work From e5e09c9b5119e8197c41526241790e66da2ecd21 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 24 Sep 2016 08:29:08 -0400 Subject: [PATCH 09/10] check for boost version --- RouterInfo.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/RouterInfo.cpp b/RouterInfo.cpp index 68c238ff..ff08286a 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -3,8 +3,10 @@ #include "I2PEndian.h" #include #include -#include #include +#if (BOOST_VERSION >= 105300) +#include +#endif #include "version.h" #include "Crypto.h" #include "Base.h" @@ -257,7 +259,11 @@ namespace data m_SupportedTransports |= supportedTransports; } } +#if (BOOST_VERSION >= 105300) boost::atomic_store (&m_Addresses, addresses); +#else + m_Addresses = addresses; // race condition +#endif // read peers uint8_t numPeers; s.read ((char *)&numPeers, sizeof (numPeers)); if (!s) return; From b03712a30e71cb654f259f894d519d6a9eb9d67e Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 25 Sep 2016 17:23:21 -0400 Subject: [PATCH 10/10] correct outbound tunnel selection --- I2CP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/I2CP.cpp b/I2CP.cpp index 0352cd15..41f81155 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -109,7 +109,7 @@ namespace client } else { - auto outboundTunnel = GetTunnelPool ()->GetNextOutboundTunnel (); + outboundTunnel = GetTunnelPool ()->GetNextOutboundTunnel (); auto leases = remote->GetNonExpiredLeases (); if (!leases.empty ()) remoteLease = leases[rand () % leases.size ()];