From e1356965308b3554d001003b9bce737603030ffa Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 3 Jun 2020 16:05:19 -0400 Subject: [PATCH 01/49] support multiple encryption keys through the I2CP --- libi2pd/Crypto.cpp | 9 ++++++++- libi2pd/Crypto.h | 2 +- libi2pd/CryptoKey.cpp | 2 +- libi2pd/CryptoKey.h | 3 ++- libi2pd_client/I2CP.cpp | 44 +++++++++++++++++++++++++++-------------- libi2pd_client/I2CP.h | 9 +++++---- 6 files changed, 46 insertions(+), 23 deletions(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 6db124c0..2f10e91d 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -375,15 +375,22 @@ namespace crypto #endif } - void X25519Keys::SetPrivateKey (const uint8_t * priv) + void X25519Keys::SetPrivateKey (const uint8_t * priv, bool calculatePublic) { #if OPENSSL_X25519 if (m_Ctx) EVP_PKEY_CTX_free (m_Ctx); if (m_Pkey) EVP_PKEY_free (m_Pkey); m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32); m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL); + if (calculatePublic) + { + size_t len = 32; + EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len); + } #else memcpy (m_PrivateKey, priv, 32); + if (calculatePublic) + GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx); #endif } diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 56c8c10b..9ca3163f 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -88,7 +88,7 @@ namespace crypto void GenerateKeys (); const uint8_t * GetPublicKey () const { return m_PublicKey; }; void GetPrivateKey (uint8_t * priv) const; - void SetPrivateKey (const uint8_t * priv); // wihout calculating public + void SetPrivateKey (const uint8_t * priv, bool calculatePublic = false); void Agree (const uint8_t * pub, uint8_t * shared); private: diff --git a/libi2pd/CryptoKey.cpp b/libi2pd/CryptoKey.cpp index d786e193..b8f66e4d 100644 --- a/libi2pd/CryptoKey.cpp +++ b/libi2pd/CryptoKey.cpp @@ -166,7 +166,7 @@ namespace crypto memcpy (pub, m_PublicKey, 32); } - ECIESX25519AEADRatchetDecryptor::ECIESX25519AEADRatchetDecryptor (const uint8_t * priv) + ECIESX25519AEADRatchetDecryptor::ECIESX25519AEADRatchetDecryptor (const uint8_t * priv, bool calculatePublic) { m_StaticKeys.SetPrivateKey (priv); } diff --git a/libi2pd/CryptoKey.h b/libi2pd/CryptoKey.h index 1c8b0a71..fb69558f 100644 --- a/libi2pd/CryptoKey.h +++ b/libi2pd/CryptoKey.h @@ -145,11 +145,12 @@ namespace crypto { public: - ECIESX25519AEADRatchetDecryptor (const uint8_t * priv); + ECIESX25519AEADRatchetDecryptor (const uint8_t * priv, bool calculatePublic = false); ~ECIESX25519AEADRatchetDecryptor () {}; bool Decrypt (const uint8_t * epub, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding); // agree with static and return in sharedSecret (32 bytes) size_t GetPublicKeyLen () const { return 32; }; + const uint8_t * GetPubicKey () const { return m_StaticKeys.GetPublicKey (); }; private: diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index fef5d6b6..5a2f0901 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -55,12 +55,18 @@ namespace client void I2CPDestination::SetEncryptionPrivateKey (const uint8_t * key) { - memcpy (m_EncryptionPrivateKey, key, 256); - m_Decryptor = i2p::data::PrivateKeys::CreateDecryptor (m_Identity->GetCryptoKeyType (), m_EncryptionPrivateKey); + m_Decryptor = i2p::data::PrivateKeys::CreateDecryptor (m_Identity->GetCryptoKeyType (), key); } + void I2CPDestination::SetECIESx25519EncryptionPrivateKey (const uint8_t * key) + { + m_ECIESx25519Decryptor = std::make_shared(key, true); // calculate public + } + bool I2CPDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const { + if (preferredCrypto == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET && m_ECIESx25519Decryptor) + return m_ECIESx25519Decryptor->Decrypt (encrypted, data, ctx, true); if (m_Decryptor) return m_Decryptor->Decrypt (encrypted, data, ctx, true); else @@ -68,6 +74,19 @@ namespace client return false; } + const uint8_t * I2CPDestination::GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const + { + if (keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET && m_ECIESx25519Decryptor) + return m_ECIESx25519Decryptor->GetPubicKey (); + return nullptr; + } + + bool I2CPDestination::SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const + { + return keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET ? (bool)m_ECIESx25519Decryptor : m_EncryptionKeyType == keyType; + } + + void I2CPDestination::HandleDataMessage (const uint8_t * buf, size_t len) { uint32_t length = bufbe32toh (buf); @@ -77,7 +96,8 @@ namespace client void I2CPDestination::CreateNewLeaseSet (std::vector > tunnels) { - i2p::data::LocalLeaseSet ls (m_Identity, m_EncryptionPrivateKey, tunnels); // we don't care about encryption key + uint8_t priv[256] = {0}; + i2p::data::LocalLeaseSet ls (m_Identity, priv, tunnels); // we don't care about encryption key, we need leases only m_LeaseSetExpirationTime = ls.GetExpirationTime (); uint8_t * leases = ls.GetLeases (); leases[-1] = tunnels.size (); @@ -572,28 +592,22 @@ namespace client offset += ls.GetBufferLen (); // private keys int numPrivateKeys = buf[offset]; offset++; - uint16_t currentKeyType = 0; - const uint8_t * currentKey = nullptr; for (int i = 0; i < numPrivateKeys; i++) { if (offset + 4 > len) return; uint16_t keyType = bufbe16toh (buf + offset); offset += 2; // encryption type uint16_t keyLen = bufbe16toh (buf + offset); offset += 2; // private key length if (offset + keyLen > len) return; - if (!currentKey || keyType > currentKeyType) + if (keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET) + m_Destination->SetECIESx25519EncryptionPrivateKey (buf + offset); + else { - currentKeyType = keyType; - currentKey = buf + offset; + m_Destination->SetEncryptionType (keyType); + m_Destination->SetEncryptionPrivateKey (buf + offset); } offset += keyLen; } - // TODO: support multiple keys - if (currentKey) - { - m_Destination->SetEncryptionPrivateKey (currentKey); - m_Destination->SetEncryptionType (currentKeyType); - } - + m_Destination->LeaseSet2Created (storeType, ls.GetBuffer (), ls.GetBufferLen ()); } } diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index f4e83f06..db38ecdc 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -75,14 +75,15 @@ namespace client void SetEncryptionPrivateKey (const uint8_t * key); void SetEncryptionType (i2p::data::CryptoKeyType keyType) { m_EncryptionKeyType = keyType; }; + void SetECIESx25519EncryptionPrivateKey (const uint8_t * key); void LeaseSetCreated (const uint8_t * buf, size_t len); // called from I2CPSession void LeaseSet2Created (uint8_t storeType, const uint8_t * buf, size_t len); // called from I2CPSession void SendMsgTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint32_t nonce); // called from I2CPSession // implements LocalDestination bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const; - bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const { return m_EncryptionKeyType == keyType; }; - // TODO: implement GetEncryptionPublicKey + bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const; + const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const; // for 4 only std::shared_ptr GetIdentity () const { return m_Identity; }; protected: @@ -101,9 +102,9 @@ namespace client std::shared_ptr m_Owner; std::shared_ptr m_Identity; - uint8_t m_EncryptionPrivateKey[256]; i2p::data::CryptoKeyType m_EncryptionKeyType; - std::shared_ptr m_Decryptor; + std::shared_ptr m_Decryptor; // standard + std::shared_ptr m_ECIESx25519Decryptor; uint64_t m_LeaseSetExpirationTime; }; From 438a225487d023f0f88905f0e1e1bbad07905801 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 3 Jun 2020 19:58:36 -0400 Subject: [PATCH 02/49] pass calculatePublic --- libi2pd/CryptoKey.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/CryptoKey.cpp b/libi2pd/CryptoKey.cpp index b8f66e4d..4518a347 100644 --- a/libi2pd/CryptoKey.cpp +++ b/libi2pd/CryptoKey.cpp @@ -168,7 +168,7 @@ namespace crypto ECIESX25519AEADRatchetDecryptor::ECIESX25519AEADRatchetDecryptor (const uint8_t * priv, bool calculatePublic) { - m_StaticKeys.SetPrivateKey (priv); + m_StaticKeys.SetPrivateKey (priv, calculatePublic); } bool ECIESX25519AEADRatchetDecryptor::Decrypt (const uint8_t * epub, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding) From 4ae41513acd14a370514e029ebf9c4a8b32af3f5 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 4 Jun 2020 18:19:38 -0400 Subject: [PATCH 03/49] save new session with NSR tagset --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 11 ++++++----- libi2pd/ECIESX25519AEADRatchetSession.h | 14 +++++++++++++- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 310d263e..a578131d 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -150,7 +150,8 @@ namespace garlic uint8_t tagsetKey[32]; i2p::crypto::HKDF (m_CK, nullptr, 0, "SessionReplyTags", tagsetKey, 32); // tagsetKey = HKDF(chainKey, ZEROLEN, "SessionReplyTags", 32) // Session Tag Ratchet - auto tagsetNsr = std::make_shared(shared_from_this ()); + auto tagsetNsr = (m_State == eSessionStateNewSessionReceived) ? std::make_shared(shared_from_this ()): + std::make_shared(shared_from_this ()); tagsetNsr->DHInitialize (m_CK, tagsetKey); // tagset_nsr = DH_INITIALIZE(chainKey, tagsetKey) tagsetNsr->NextSessionTagRatchet (); return tagsetNsr; @@ -416,8 +417,8 @@ namespace garlic bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) { // we are Bob - m_NSRTagset = CreateNewSessionTagset (); - uint64_t tag = m_NSRTagset->GetNextSessionTag (); + m_NSRSendTagset = CreateNewSessionTagset (); + uint64_t tag = m_NSRSendTagset->GetNextSessionTag (); size_t offset = 0; memcpy (out + offset, &tag, 8); @@ -475,7 +476,7 @@ namespace garlic bool ECIESX25519AEADRatchetSession::NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) { // we are Bob and sent NSR already - uint64_t tag = m_NSRTagset->GetNextSessionTag (); // next tag + uint64_t tag = m_NSRSendTagset->GetNextSessionTag (); // next tag memcpy (out, &tag, 8); memcpy (out + 8, m_NSREncodedKey, 32); // recalculate h with new tag @@ -625,7 +626,7 @@ namespace garlic { case eSessionStateNewSessionReplySent: m_State = eSessionStateEstablished; - m_NSRTagset = nullptr; + m_NSRSendTagset = nullptr; #if (__cplusplus >= 201703L) // C++ 17 or higher [[fallthrough]]; #endif diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index 108788d5..d121842d 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -79,6 +79,18 @@ namespace garlic uint64_t m_ExpirationTimestamp = 0; }; + class NSRatchetTagSet: public RatchetTagSet + { + public: + + NSRatchetTagSet (std::shared_ptr session): + RatchetTagSet (session), m_DummySession (session) {}; + + private: + + std::shared_ptr m_DummySession; // we need a strong pointer for NS + }; + enum ECIESx25519BlockType { eECIESx25519BlkDateTime = 0, @@ -171,7 +183,7 @@ namespace garlic i2p::crypto::X25519Keys m_EphemeralKeys; SessionState m_State = eSessionStateNew; uint64_t m_SessionCreatedTimestamp = 0, m_LastActivityTimestamp = 0; // incoming - std::shared_ptr m_SendTagset, m_NSRTagset; + std::shared_ptr m_SendTagset, m_NSRSendTagset; std::unique_ptr m_Destination;// TODO: might not need it std::list > m_AckRequests; // (tagsetid, index) bool m_SendReverseKey = false, m_SendForwardKey = false; From 55ff6beb7d76f89c1ae7237ba6b8ab5fa5727a14 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 5 Jun 2020 09:23:50 -0400 Subject: [PATCH 04/49] don't create ECIESx25519 again if key was not changed --- libi2pd_client/I2CP.cpp | 6 +++++- libi2pd_client/I2CP.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index 5a2f0901..b0f334f5 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -60,7 +60,11 @@ namespace client void I2CPDestination::SetECIESx25519EncryptionPrivateKey (const uint8_t * key) { - m_ECIESx25519Decryptor = std::make_shared(key, true); // calculate public + if (!m_ECIESx25519Decryptor || memcmp (m_ECIESx25519PrivateKey, key, 32)) // new key? + { + m_ECIESx25519Decryptor = std::make_shared(key, true); // calculate public + memcpy (m_ECIESx25519PrivateKey, key, 32); + } } bool I2CPDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index db38ecdc..adb648f4 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -105,6 +105,7 @@ namespace client i2p::data::CryptoKeyType m_EncryptionKeyType; std::shared_ptr m_Decryptor; // standard std::shared_ptr m_ECIESx25519Decryptor; + uint8_t m_ECIESx25519PrivateKey[32]; uint64_t m_LeaseSetExpirationTime; }; From 6735b2686b6c13a36546dd794ee49b4d583565e0 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 5 Jun 2020 15:41:30 -0400 Subject: [PATCH 05/49] set LeaseSet2 for ECIESx25519 --- libi2pd/Destination.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index cd447773..6d5fb916 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -892,7 +892,11 @@ namespace client encryptionKey->GenerateKeys (); encryptionKey->CreateDecryptor (); if (it == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET) + { m_ECIESx25519EncryptionKey.reset (encryptionKey); + if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET) + SetLeaseSetType (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2); // Rathets must use LeaseSet2 + } else m_StandardEncryptionKey.reset (encryptionKey); } From 221c14cf0e2ae481bbaa7edfd4257511e02ec9ac Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 7 Jun 2020 16:24:11 -0400 Subject: [PATCH 06/49] don't lookup UDP session if port was not changed --- libi2pd_client/I2PTunnel.cpp | 28 ++++++++++++++++++---------- libi2pd_client/I2PTunnel.h | 5 +++-- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 5b384bff..ea2517d7 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -634,7 +634,7 @@ namespace client uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); std::vector removePorts; for (const auto & s : m_Sessions) { - if (now - s.second.second >= delta) + if (now - s.second->second >= delta) removePorts.push_back(s.first); } for(auto port : removePorts) { @@ -761,7 +761,7 @@ namespace client m_RemoteIdent(nullptr), m_ResolveThread(nullptr), m_LocalSocket(localDestination->GetService(), localEndpoint), - RemotePort(remotePort), + RemotePort(remotePort), m_LastPort (0), m_cancel_resolve(false) { auto dgram = m_LocalDest->CreateDatagramDestination(gzip); @@ -796,16 +796,24 @@ namespace client return; // drop, remote not resolved } auto remotePort = m_RecvEndpoint.port(); - auto itr = m_Sessions.find(remotePort); - if (itr == m_Sessions.end()) { - // track new udp convo - m_Sessions[remotePort] = {boost::asio::ip::udp::endpoint(m_RecvEndpoint), 0}; - } + if (!m_LastPort || m_LastPort != remotePort) + { + auto itr = m_Sessions.find(remotePort); + if (itr != m_Sessions.end()) + m_LastSession = itr->second; + else + { + m_LastSession = std::make_shared(boost::asio::ip::udp::endpoint(m_RecvEndpoint), 0); + m_Sessions.emplace (remotePort, m_LastSession); + } + m_LastPort = remotePort; + } // send off to remote i2p destination LogPrint(eLogDebug, "UDP Client: send ", transferred, " to ", m_RemoteIdent->ToBase32(), ":", RemotePort); m_LocalDest->GetDatagramDestination()->SendDatagramTo(m_RecvBuff, transferred, *m_RemoteIdent, remotePort, RemotePort); // mark convo as active - m_Sessions[remotePort].second = i2p::util::GetMillisecondsSinceEpoch(); + if (m_LastSession) + m_LastSession->second = i2p::util::GetMillisecondsSinceEpoch(); RecvFromLocal(); } @@ -851,9 +859,9 @@ namespace client // found convo if (len > 0) { LogPrint(eLogDebug, "UDP Client: got ", len, "B from ", from.GetIdentHash().ToBase32()); - m_LocalSocket.send_to(boost::asio::buffer(buf, len), itr->second.first); + m_LocalSocket.send_to(boost::asio::buffer(buf, len), itr->second->first); // mark convo as active - itr->second.second = i2p::util::GetMillisecondsSinceEpoch(); + itr->second->second = i2p::util::GetMillisecondsSinceEpoch(); } } else diff --git a/libi2pd_client/I2PTunnel.h b/libi2pd_client/I2PTunnel.h index d4db80d8..99934196 100644 --- a/libi2pd_client/I2PTunnel.h +++ b/libi2pd_client/I2PTunnel.h @@ -276,7 +276,7 @@ namespace client void TryResolving(); const std::string m_Name; std::mutex m_SessionsMutex; - std::map m_Sessions; // maps i2p port -> local udp convo + std::unordered_map > m_Sessions; // maps i2p port -> local udp convo const std::string m_RemoteDest; std::shared_ptr m_LocalDest; const boost::asio::ip::udp::endpoint m_LocalEndpoint; @@ -285,8 +285,9 @@ namespace client boost::asio::ip::udp::socket m_LocalSocket; boost::asio::ip::udp::endpoint m_RecvEndpoint; uint8_t m_RecvBuff[I2P_UDP_MAX_MTU]; - uint16_t RemotePort; + uint16_t RemotePort, m_LastPort; bool m_cancel_resolve; + std::shared_ptr m_LastSession; }; class I2PServerTunnel: public I2PService From 6d7847f2dfc2da364f5303207f3665533bfbbbbc Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 9 Jun 2020 16:26:45 -0400 Subject: [PATCH 07/49] send bulk datagrams --- libi2pd/Datagram.cpp | 14 ++++++++++++-- libi2pd/Datagram.h | 3 ++- libi2pd_client/I2PTunnel.cpp | 18 ++++++++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 04792bc5..5a6b8d90 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -56,6 +56,11 @@ namespace datagram session->SendMsg(msg); } + void DatagramDestination::FlushSendQueue (const i2p::data::IdentHash & ident) + { + ObtainSession(ident)->FlushSendQueue (); + } + void DatagramDestination::HandleDatagram (uint16_t fromPort, uint16_t toPort,uint8_t * const &buf, size_t len) { i2p::data::IdentityEx identity; @@ -366,6 +371,7 @@ namespace datagram void DatagramSession::FlushSendQueue () { + if (m_SendQueue.empty ()) return; std::vector send; auto routingPath = GetSharedRoutingPath(); // if we don't have a routing path we will drop all queued messages @@ -380,7 +386,6 @@ namespace datagram routingPath->outboundTunnel->SendTunnelDataMsg(send); } m_SendQueue.clear(); - ScheduleFlushSendQueue(); } void DatagramSession::ScheduleFlushSendQueue() @@ -388,7 +393,12 @@ namespace datagram boost::posix_time::milliseconds dlt(10); m_SendQueueTimer.expires_from_now(dlt); auto self = shared_from_this(); - m_SendQueueTimer.async_wait([self](const boost::system::error_code & ec) { if(ec) return; self->FlushSendQueue(); }); + m_SendQueueTimer.async_wait([self](const boost::system::error_code & ec) + { + if(ec) return; + self->FlushSendQueue(); + self->ScheduleFlushSendQueue(); + }); } } } diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index e81f738a..b7abcc03 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -59,6 +59,7 @@ namespace datagram /** send an i2np message to remote endpoint for this session */ void SendMsg(std::shared_ptr msg); + void FlushSendQueue(); /** get the last time in milliseconds for when we used this datagram session */ uint64_t LastActivity() const { return m_LastUse; } @@ -84,7 +85,6 @@ namespace datagram private: - void FlushSendQueue(); void ScheduleFlushSendQueue(); void HandleSend(std::shared_ptr msg); @@ -122,6 +122,7 @@ namespace datagram void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0); void SendRawDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0); + void FlushSendQueue (const i2p::data::IdentHash & ident); void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, bool isRaw = false); void SetReceiver (const Receiver& receiver) { m_Receiver = receiver; }; diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index ea2517d7..048c9962 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -811,6 +811,24 @@ namespace client // send off to remote i2p destination LogPrint(eLogDebug, "UDP Client: send ", transferred, " to ", m_RemoteIdent->ToBase32(), ":", RemotePort); m_LocalDest->GetDatagramDestination()->SendDatagramTo(m_RecvBuff, transferred, *m_RemoteIdent, remotePort, RemotePort); + size_t numPackets = 0; + while (numPackets < i2p::datagram::DATAGRAM_SEND_QUEUE_MAX_SIZE) + { + boost::system::error_code ec; + size_t moreBytes = m_LocalSocket.available(ec); + if (ec || !moreBytes) break; + transferred = m_LocalSocket.receive_from (boost::asio::buffer (m_RecvBuff, I2P_UDP_MAX_MTU), m_RecvEndpoint, 0, ec); + remotePort = m_RecvEndpoint.port(); + // TODO: check remotePort + m_LocalDest->GetDatagramDestination()->SendDatagramTo(m_RecvBuff, transferred, *m_RemoteIdent, remotePort, RemotePort); + numPackets++; + } + if (numPackets) + { + LogPrint(eLogDebug, "UDP Client: sent ", numPackets, " more packets to ", m_RemoteIdent->ToBase32()); + m_LocalDest->GetDatagramDestination()->FlushSendQueue (*m_RemoteIdent); + } + // mark convo as active if (m_LastSession) m_LastSession->second = i2p::util::GetMillisecondsSinceEpoch(); From f077836bf5518d4fe19aea425dbaa7b5b12eaea1 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 9 Jun 2020 19:20:24 -0400 Subject: [PATCH 08/49] store DatagramSession for bulk --- libi2pd/Datagram.cpp | 53 ++++++++++++++++++++++++------------ libi2pd/Datagram.h | 7 ++++- libi2pd_client/I2PTunnel.cpp | 9 +++--- 3 files changed, 45 insertions(+), 24 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 5a6b8d90..c4877106 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -34,31 +34,48 @@ namespace datagram void DatagramDestination::SendDatagramTo(const uint8_t * payload, size_t len, const i2p::data::IdentHash & identity, uint16_t fromPort, uint16_t toPort) { - if (m_Owner->GetIdentity ()->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) - { - uint8_t hash[32]; - SHA256(payload, len, hash); - m_Owner->Sign (hash, 32, m_Signature.data ()); - } - else - m_Owner->Sign (payload, len, m_Signature.data ()); - - auto session = ObtainSession(identity); - auto msg = CreateDataMessage ({{m_From.data (), m_From.size ()}, {m_Signature.data (), m_Signature.size ()}, {payload, len}}, - fromPort, toPort, false, !session->IsRatchets ()); // datagram - session->SendMsg(msg); + SendDatagram (ObtainSession(identity), payload, len, fromPort, toPort); } void DatagramDestination::SendRawDatagramTo(const uint8_t * payload, size_t len, const i2p::data::IdentHash & identity, uint16_t fromPort, uint16_t toPort) { - auto session = ObtainSession(identity); - auto msg = CreateDataMessage ({{payload, len}}, fromPort, toPort, true, !session->IsRatchets ()); // raw - session->SendMsg(msg); + SendRawDatagram (ObtainSession(identity), payload, len, fromPort, toPort); } - void DatagramDestination::FlushSendQueue (const i2p::data::IdentHash & ident) + std::shared_ptr DatagramDestination::GetSession(const i2p::data::IdentHash & ident) { - ObtainSession(ident)->FlushSendQueue (); + return ObtainSession(ident); + } + + void DatagramDestination::SendDatagram (std::shared_ptr session, const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort) + { + if (session) + { + if (m_Owner->GetIdentity ()->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) + { + uint8_t hash[32]; + SHA256(payload, len, hash); + m_Owner->Sign (hash, 32, m_Signature.data ()); + } + else + m_Owner->Sign (payload, len, m_Signature.data ()); + + auto msg = CreateDataMessage ({{m_From.data (), m_From.size ()}, {m_Signature.data (), m_Signature.size ()}, {payload, len}}, + fromPort, toPort, false, !session->IsRatchets ()); // datagram + session->SendMsg(msg); + } + } + + void DatagramDestination::SendRawDatagram (std::shared_ptr session, const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort) + { + if (session) + session->SendMsg(CreateDataMessage ({{payload, len}}, fromPort, toPort, true, !session->IsRatchets ())); // raw + } + + void DatagramDestination::FlushSendQueue (std::shared_ptr session) + { + if (session) + session->FlushSendQueue (); } void DatagramDestination::HandleDatagram (uint16_t fromPort, uint16_t toPort,uint8_t * const &buf, size_t len) diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index b7abcc03..fa9d2371 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -122,7 +122,12 @@ namespace datagram void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0); void SendRawDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0); - void FlushSendQueue (const i2p::data::IdentHash & ident); + + std::shared_ptr GetSession(const i2p::data::IdentHash & ident); + void SendDatagram (std::shared_ptr session, const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort); + void SendRawDatagram (std::shared_ptr session, const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort); + void FlushSendQueue (std::shared_ptr session); + void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, bool isRaw = false); void SetReceiver (const Receiver& receiver) { m_Receiver = receiver; }; diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 048c9962..0b2bb7e0 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -810,7 +810,8 @@ namespace client } // send off to remote i2p destination LogPrint(eLogDebug, "UDP Client: send ", transferred, " to ", m_RemoteIdent->ToBase32(), ":", RemotePort); - m_LocalDest->GetDatagramDestination()->SendDatagramTo(m_RecvBuff, transferred, *m_RemoteIdent, remotePort, RemotePort); + auto session = m_LocalDest->GetDatagramDestination()->GetSession (*m_RemoteIdent); + m_LocalDest->GetDatagramDestination()->SendDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort); size_t numPackets = 0; while (numPackets < i2p::datagram::DATAGRAM_SEND_QUEUE_MAX_SIZE) { @@ -820,14 +821,12 @@ namespace client transferred = m_LocalSocket.receive_from (boost::asio::buffer (m_RecvBuff, I2P_UDP_MAX_MTU), m_RecvEndpoint, 0, ec); remotePort = m_RecvEndpoint.port(); // TODO: check remotePort - m_LocalDest->GetDatagramDestination()->SendDatagramTo(m_RecvBuff, transferred, *m_RemoteIdent, remotePort, RemotePort); + m_LocalDest->GetDatagramDestination()->SendDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort); numPackets++; } if (numPackets) - { LogPrint(eLogDebug, "UDP Client: sent ", numPackets, " more packets to ", m_RemoteIdent->ToBase32()); - m_LocalDest->GetDatagramDestination()->FlushSendQueue (*m_RemoteIdent); - } + m_LocalDest->GetDatagramDestination()->FlushSendQueue (session); // mark convo as active if (m_LastSession) From a8f227f7594ae827764d1e7445cfe1824da689bf Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 9 Jun 2020 21:48:47 -0400 Subject: [PATCH 09/49] send raw follow-on datagrams --- libi2pd_client/I2PTunnel.cpp | 22 +++++++++++++++++----- libi2pd_client/I2PTunnel.h | 2 ++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 0b2bb7e0..48b1e79d 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -611,12 +611,23 @@ namespace client void I2PUDPServerTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) { - std::lock_guard lock(m_SessionsMutex); - auto session = ObtainUDPSession(from, toPort, fromPort); - session->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint); - session->LastActivity = i2p::util::GetMillisecondsSinceEpoch(); + { + std::lock_guard lock(m_SessionsMutex); + m_LastSession = ObtainUDPSession(from, toPort, fromPort); + } + m_LastSession->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint); + m_LastSession->LastActivity = i2p::util::GetMillisecondsSinceEpoch(); } + void I2PUDPServerTunnel::HandleRecvFromI2PRaw (uint16_t, uint16_t, const uint8_t * buf, size_t len) + { + if (m_LastSession) + { + m_LastSession->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint); + m_LastSession->LastActivity = i2p::util::GetMillisecondsSinceEpoch(); + } + } + void I2PUDPServerTunnel::ExpireStale(const uint64_t delta) { std::lock_guard lock(m_SessionsMutex); uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); @@ -714,6 +725,7 @@ namespace client m_LocalDest->Start(); auto dgram = m_LocalDest->CreateDatagramDestination(gzip); dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); + dgram->SetRawReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2PRaw, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); } I2PUDPServerTunnel::~I2PUDPServerTunnel() @@ -821,7 +833,7 @@ namespace client transferred = m_LocalSocket.receive_from (boost::asio::buffer (m_RecvBuff, I2P_UDP_MAX_MTU), m_RecvEndpoint, 0, ec); remotePort = m_RecvEndpoint.port(); // TODO: check remotePort - m_LocalDest->GetDatagramDestination()->SendDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort); + m_LocalDest->GetDatagramDestination()->SendRawDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort); numPackets++; } if (numPackets) diff --git a/libi2pd_client/I2PTunnel.h b/libi2pd_client/I2PTunnel.h index 99934196..19e44e79 100644 --- a/libi2pd_client/I2PTunnel.h +++ b/libi2pd_client/I2PTunnel.h @@ -237,6 +237,7 @@ namespace client private: void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); + void HandleRecvFromI2PRaw (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); UDPSessionPtr ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort); private: @@ -248,6 +249,7 @@ namespace client std::mutex m_SessionsMutex; std::vector m_Sessions; std::shared_ptr m_LocalDest; + UDPSessionPtr m_LastSession; }; class I2PUDPClientTunnel From 0639cce784a0506cff7be8fbc6b9edb2b9a420b7 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Wed, 10 Jun 2020 05:11:26 +0300 Subject: [PATCH 10/49] [SAM] fix ECDSA signatures names Signed-off-by: R4SAS --- libi2pd_client/SAM.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 2c6b711d..4723d168 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -1015,8 +1015,8 @@ namespace client { {"DSA_SHA1", i2p::data::SIGNING_KEY_TYPE_DSA_SHA1}, {"ECDSA_SHA256_P256", i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256}, - {"ECDSA_SHA256_P384", i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA384_P384}, - {"ECDSA_SHA256_P521", i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA512_P521}, + {"ECDSA_SHA384_P384", i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA384_P384}, + {"ECDSA_SHA512_P521", i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA512_P521}, {"EdDSA_SHA512_Ed25519", i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519}, {"GOST_GOSTR3411256_GOSTR3410CRYPTOPROA", i2p::data::SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256}, {"GOST_GOSTR3411512_GOSTR3410TC26A512", i2p::data::SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512}, From a33cad4b709fe62a488cbcd7447e3f35dd8ab3bf Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 10 Jun 2020 11:57:40 -0400 Subject: [PATCH 11/49] eliminate datagram send timer --- libi2pd/Datagram.cpp | 26 +++++++------------------- libi2pd/Datagram.h | 3 --- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index c4877106..99318ec9 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -34,12 +34,16 @@ namespace datagram void DatagramDestination::SendDatagramTo(const uint8_t * payload, size_t len, const i2p::data::IdentHash & identity, uint16_t fromPort, uint16_t toPort) { - SendDatagram (ObtainSession(identity), payload, len, fromPort, toPort); + auto session = ObtainSession(identity); + SendDatagram (session, payload, len, fromPort, toPort); + FlushSendQueue (session); } void DatagramDestination::SendRawDatagramTo(const uint8_t * payload, size_t len, const i2p::data::IdentHash & identity, uint16_t fromPort, uint16_t toPort) { - SendRawDatagram (ObtainSession(identity), payload, len, fromPort, toPort); + auto session = ObtainSession(identity); + SendRawDatagram (session, payload, len, fromPort, toPort); + FlushSendQueue (session); } std::shared_ptr DatagramDestination::GetSession(const i2p::data::IdentHash & ident) @@ -218,7 +222,6 @@ namespace datagram const i2p::data::IdentHash & remoteIdent) : m_LocalDestination(localDestination), m_RemoteIdent(remoteIdent), - m_SendQueueTimer(localDestination->GetService()), m_RequestingLS(false) { } @@ -226,12 +229,10 @@ namespace datagram void DatagramSession::Start () { m_LastUse = i2p::util::GetMillisecondsSinceEpoch (); - ScheduleFlushSendQueue(); } void DatagramSession::Stop () { - m_SendQueueTimer.cancel (); } void DatagramSession::SendMsg(std::shared_ptr msg) @@ -383,7 +384,7 @@ namespace datagram if (msg || m_SendQueue.empty ()) m_SendQueue.push_back(msg); // flush queue right away if full - if(m_SendQueue.size() >= DATAGRAM_SEND_QUEUE_MAX_SIZE) FlushSendQueue(); + if(!msg || m_SendQueue.size() >= DATAGRAM_SEND_QUEUE_MAX_SIZE) FlushSendQueue(); } void DatagramSession::FlushSendQueue () @@ -404,18 +405,5 @@ namespace datagram } m_SendQueue.clear(); } - - void DatagramSession::ScheduleFlushSendQueue() - { - boost::posix_time::milliseconds dlt(10); - m_SendQueueTimer.expires_from_now(dlt); - auto self = shared_from_this(); - m_SendQueueTimer.async_wait([self](const boost::system::error_code & ec) - { - if(ec) return; - self->FlushSendQueue(); - self->ScheduleFlushSendQueue(); - }); - } } } diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index fa9d2371..2aabcb1f 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -85,8 +85,6 @@ namespace datagram private: - void ScheduleFlushSendQueue(); - void HandleSend(std::shared_ptr msg); std::shared_ptr GetSharedRoutingPath(); @@ -101,7 +99,6 @@ namespace datagram std::shared_ptr m_RoutingSession; std::shared_ptr m_CurrentRemoteLease; std::shared_ptr m_CurrentOutboundTunnel; - boost::asio::deadline_timer m_SendQueueTimer; std::vector > m_SendQueue; uint64_t m_LastUse; bool m_RequestingLS; From 44bb8f6f1691176978390b753a325b92b42fbf00 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 10 Jun 2020 21:19:37 -0400 Subject: [PATCH 12/49] allocated datagram I2NP from memory pool --- libi2pd/Datagram.cpp | 18 ++++++------------ libi2pd/Datagram.h | 4 ++-- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 99318ec9..5a196c3a 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -152,7 +152,7 @@ namespace datagram const std::vector >& payloads, uint16_t fromPort, uint16_t toPort, bool isRaw, bool checksum) { - auto msg = NewI2NPMessage (); + auto msg = m_I2NPMsgsPool.AcquireShared (); uint8_t * buf = msg->GetPayload (); buf += 4; // reserve for length size_t size = m_Gzip ? m_Deflator.Deflate (payloads, buf, msg->maxLen - msg->len) : @@ -239,9 +239,11 @@ namespace datagram { // we used this session m_LastUse = i2p::util::GetMillisecondsSinceEpoch(); - // schedule send - auto self = shared_from_this(); - m_LocalDestination->GetService().post(std::bind(&DatagramSession::HandleSend, self, msg)); + if (msg || m_SendQueue.empty ()) + m_SendQueue.push_back(msg); + // flush queue right away if full + if (!msg || m_SendQueue.size() >= DATAGRAM_SEND_QUEUE_MAX_SIZE) + FlushSendQueue(); } DatagramSession::Info DatagramSession::GetSessionInfo() const @@ -379,14 +381,6 @@ namespace datagram if(ls && ls->GetExpirationTime() > oldExpire) m_RemoteLeaseSet = ls; } - void DatagramSession::HandleSend(std::shared_ptr msg) - { - if (msg || m_SendQueue.empty ()) - m_SendQueue.push_back(msg); - // flush queue right away if full - if(!msg || m_SendQueue.size() >= DATAGRAM_SEND_QUEUE_MAX_SIZE) FlushSendQueue(); - } - void DatagramSession::FlushSendQueue () { if (m_SendQueue.empty ()) return; diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index 2aabcb1f..94fe422c 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -85,8 +85,6 @@ namespace datagram private: - void HandleSend(std::shared_ptr msg); - std::shared_ptr GetSharedRoutingPath(); void HandleLeaseSetUpdated(std::shared_ptr ls); @@ -119,6 +117,7 @@ namespace datagram void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0); void SendRawDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0); + // TODO: implement calls from other thread from SAM std::shared_ptr GetSession(const i2p::data::IdentHash & ident); void SendDatagram (std::shared_ptr session, const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort); @@ -168,6 +167,7 @@ namespace datagram i2p::data::GzipInflator m_Inflator; i2p::data::GzipDeflator m_Deflator; std::vector m_From, m_Signature; + i2p::util::MemoryPool > m_I2NPMsgsPool; }; } } From 6a0174293e0e828d52b06cb5d261cdf183a865ec Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 11 Jun 2020 22:04:32 -0400 Subject: [PATCH 13/49] send raw datagrams in opposite direction --- libi2pd_client/I2PTunnel.cpp | 61 ++++++++++++++++++++++++------------ libi2pd_client/I2PTunnel.h | 4 +++ 2 files changed, 45 insertions(+), 20 deletions(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 48b1e79d..74175b14 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -611,6 +611,7 @@ namespace client void I2PUDPServerTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) { + if (!m_LastSession || m_LastSession->Identity.GetLL()[0] != from.GetIdentHash ().GetLL()[0]) { std::lock_guard lock(m_SessionsMutex); m_LastSession = ObtainUDPSession(from, toPort, fromPort); @@ -658,7 +659,7 @@ namespace client auto ih = from.GetIdentHash(); for (auto & s : m_Sessions ) { - if ( s->Identity == ih) + if (s->Identity.GetLL()[0] == ih.GetLL()[0]) { /** found existing session */ LogPrint(eLogDebug, "UDPServer: found session ", s->IPSocket.local_endpoint(), " ", ih.ToBase32()); @@ -707,11 +708,25 @@ namespace client { LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint); LastActivity = i2p::util::GetMillisecondsSinceEpoch(); - m_Destination->SendDatagramTo(m_Buffer, len, Identity, LocalPort, RemotePort); + auto session = m_Destination->GetSession (Identity); + m_Destination->SendDatagram(session, m_Buffer, len, LocalPort, RemotePort); + size_t numPackets = 0; + while (numPackets < i2p::datagram::DATAGRAM_SEND_QUEUE_MAX_SIZE) + { + boost::system::error_code ec; + size_t moreBytes = IPSocket.available(ec); + if (ec || !moreBytes) break; + len = IPSocket.receive_from (boost::asio::buffer (m_Buffer, I2P_UDP_MAX_MTU), FromEndpoint, 0, ec); + m_Destination->SendRawDatagram (session, m_Buffer, len, LocalPort, RemotePort); + numPackets++; + } + if (numPackets > 0) + LogPrint(eLogDebug, "UDPSession: forward more ", numPackets, "packets B from ", FromEndpoint); + m_Destination->FlushSendQueue (session); Receive(); - } else { + } + else LogPrint(eLogError, "UDPSession: ", ecode.message()); - } } I2PUDPServerTunnel::I2PUDPServerTunnel(const std::string & name, std::shared_ptr localDestination, @@ -781,6 +796,8 @@ namespace client std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); + dgram->SetRawReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2PRaw, this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); } void I2PUDPClientTunnel::Start() { @@ -880,26 +897,30 @@ namespace client void I2PUDPClientTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) { if(m_RemoteIdent && from.GetIdentHash() == *m_RemoteIdent) - { - auto itr = m_Sessions.find(toPort); - // found convo ? - if(itr != m_Sessions.end()) - { - // found convo - if (len > 0) { - LogPrint(eLogDebug, "UDP Client: got ", len, "B from ", from.GetIdentHash().ToBase32()); - m_LocalSocket.send_to(boost::asio::buffer(buf, len), itr->second->first); - // mark convo as active - itr->second->second = i2p::util::GetMillisecondsSinceEpoch(); - } - } - else - LogPrint(eLogWarning, "UDP Client: not tracking udp session using port ", (int) toPort); - } + HandleRecvFromI2PRaw (fromPort, toPort, buf, len); else LogPrint(eLogWarning, "UDP Client: unwarranted traffic from ", from.GetIdentHash().ToBase32()); } + void I2PUDPClientTunnel::HandleRecvFromI2PRaw(uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) + { + auto itr = m_Sessions.find(toPort); + // found convo ? + if(itr != m_Sessions.end()) + { + // found convo + if (len > 0) + { + LogPrint(eLogDebug, "UDP Client: got ", len, "B from ", m_RemoteIdent ? m_RemoteIdent->ToBase32() : ""); + m_LocalSocket.send_to(boost::asio::buffer(buf, len), itr->second->first); + // mark convo as active + itr->second->second = i2p::util::GetMillisecondsSinceEpoch(); + } + } + else + LogPrint(eLogWarning, "UDP Client: not tracking udp session using port ", (int) toPort); + } + I2PUDPClientTunnel::~I2PUDPClientTunnel() { auto dgram = m_LocalDest->GetDatagramDestination(); if (dgram) dgram->ResetReceiver(); diff --git a/libi2pd_client/I2PTunnel.h b/libi2pd_client/I2PTunnel.h index 19e44e79..19d553da 100644 --- a/libi2pd_client/I2PTunnel.h +++ b/libi2pd_client/I2PTunnel.h @@ -275,7 +275,11 @@ namespace client void RecvFromLocal(); void HandleRecvFromLocal(const boost::system::error_code & e, std::size_t transferred); void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); + void HandleRecvFromI2PRaw(uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void TryResolving(); + + private: + const std::string m_Name; std::mutex m_SessionsMutex; std::unordered_map > m_Sessions; // maps i2p port -> local udp convo From 5993cc857a94abd10ebf05fbe7c1426719a1b9a4 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 12 Jun 2020 16:03:12 -0400 Subject: [PATCH 14/49] start new tunnel message if remining is too small --- libi2pd/TunnelGateway.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/TunnelGateway.cpp b/libi2pd/TunnelGateway.cpp index 8f01bc4e..317926ae 100644 --- a/libi2pd/TunnelGateway.cpp +++ b/libi2pd/TunnelGateway.cpp @@ -66,7 +66,7 @@ namespace tunnel // length of bytes doesn't fit full tunnel message // every follow-on fragment adds 7 bytes size_t nonFit = (fullMsgLen + numFollowOnFragments*7) % TUNNEL_DATA_MAX_PAYLOAD_SIZE; - if (!nonFit || nonFit > m_RemainingSize) + if (!nonFit || nonFit > m_RemainingSize || m_RemainingSize < fullMsgLen/5) { CompleteCurrentTunnelDataMessage (); CreateCurrentTunnelDataMessage (); From 5e0a8ed2324b4a6966fff0fe2b70a21e3c15dd14 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 12 Jun 2020 16:06:07 -0400 Subject: [PATCH 15/49] set UDP receive buffer size --- libi2pd_client/I2PTunnel.cpp | 3 +++ libi2pd_client/I2PTunnel.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 74175b14..d05a97b7 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -692,6 +692,7 @@ namespace client LocalPort(ourPort), RemotePort(theirPort) { + IPSocket.set_option (boost::asio::socket_base::receive_buffer_size (I2P_UDP_MAX_MTU )); memcpy(Identity, to->data(), 32); Receive(); } @@ -791,6 +792,8 @@ namespace client RemotePort(remotePort), m_LastPort (0), m_cancel_resolve(false) { + m_LocalSocket.set_option (boost::asio::socket_base::receive_buffer_size (I2P_UDP_MAX_MTU )); + auto dgram = m_LocalDest->CreateDatagramDestination(gzip); dgram->SetReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, diff --git a/libi2pd_client/I2PTunnel.h b/libi2pd_client/I2PTunnel.h index 19d553da..eb1d8ed9 100644 --- a/libi2pd_client/I2PTunnel.h +++ b/libi2pd_client/I2PTunnel.h @@ -167,7 +167,7 @@ namespace client const uint64_t I2P_UDP_SESSION_TIMEOUT = 1000 * 60 * 2; /** max size for i2p udp */ - const size_t I2P_UDP_MAX_MTU = i2p::datagram::MAX_DATAGRAM_SIZE; + const size_t I2P_UDP_MAX_MTU = 64*1024; struct UDPSession { From 61897ae16c151f67e73bb3f13c3c0e513acb05e9 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 12 Jun 2020 20:42:54 -0400 Subject: [PATCH 16/49] crypto.ratchet.inboundTags --- libi2pd/Destination.cpp | 3 +++ libi2pd/Destination.h | 2 ++ libi2pd/ECIESX25519AEADRatchetSession.cpp | 31 +++++++++++++++++------ libi2pd/Garlic.cpp | 3 ++- libi2pd/Garlic.h | 3 +++ libi2pd_client/ClientContext.cpp | 2 ++ 6 files changed, 35 insertions(+), 9 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 6d5fb916..a764224c 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -56,6 +56,9 @@ namespace client if (it != params->end ()) numTags = std::stoi(it->second); LogPrint (eLogInfo, "Destination: parameters for tunnel set to: ", inQty, " inbound (", inLen, " hops), ", outQty, " outbound (", outLen, " hops), ", numTags, " tags"); + it = params->find (I2CP_PARAM_RATCHET_INBOUND_TAGS); + if (it != params->end ()) + SetNumRatchetInboundTags (std::stoi(it->second)); it = params->find (I2CP_PARAM_EXPLICIT_PEERS); if (it != params->end ()) { diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 139423c6..1d5c0a55 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -57,6 +57,8 @@ namespace client const int STREAM_REQUEST_TIMEOUT = 60; //in seconds const char I2CP_PARAM_TAGS_TO_SEND[] = "crypto.tagsToSend"; const int DEFAULT_TAGS_TO_SEND = 40; + const char I2CP_PARAM_RATCHET_INBOUND_TAGS[] = "crypto.ratchet.inboundTags"; + const char I2CP_PARAM_RATCHET_OUTBOUND_TAGS[] = "crypto.ratchet.outboundTags"; // not used yet const char I2CP_PARAM_INBOUND_NICKNAME[] = "inbound.nickname"; const char I2CP_PARAM_OUTBOUND_NICKNAME[] = "outbound.nickname"; const char I2CP_PARAM_LEASESET_TYPE[] = "i2cp.leaseSetType"; diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index a578131d..ad91382f 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -341,7 +341,8 @@ namespace garlic newTagset->SetTagSetID (tagsetID); newTagset->DHInitialize (receiveTagset->GetNextRootKey (), tagsetKey); newTagset->NextSessionTagRatchet (); - GenerateMoreReceiveTags (newTagset, ECIESX25519_MAX_NUM_GENERATED_TAGS); + GenerateMoreReceiveTags (newTagset, (GetOwner () && GetOwner ()->GetNumRatchetInboundTags () > 0) ? + GetOwner ()->GetNumRatchetInboundTags () : ECIESX25519_MAX_NUM_GENERATED_TAGS); receiveTagset->Expire (); LogPrint (eLogDebug, "Garlic: next receive tagset ", tagsetID, " created"); } @@ -459,7 +460,8 @@ namespace garlic m_SendTagset = std::make_shared(shared_from_this ()); m_SendTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba) m_SendTagset->NextSessionTagRatchet (); - GenerateMoreReceiveTags (receiveTagset, ECIESX25519_MIN_NUM_GENERATED_TAGS); + GenerateMoreReceiveTags (receiveTagset, (GetOwner () && GetOwner ()->GetNumRatchetInboundTags () > 0) ? + GetOwner ()->GetNumRatchetInboundTags () : ECIESX25519_MIN_NUM_GENERATED_TAGS); i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", m_NSRKey, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32) // encrypt payload if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + offset, len + 16, true)) // encrypt @@ -548,7 +550,8 @@ namespace garlic auto receiveTagset = std::make_shared(shared_from_this ()); receiveTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba) receiveTagset->NextSessionTagRatchet (); - GenerateMoreReceiveTags (receiveTagset, ECIESX25519_MIN_NUM_GENERATED_TAGS); + GenerateMoreReceiveTags (receiveTagset, (GetOwner () && GetOwner ()->GetNumRatchetInboundTags () > 0) ? + GetOwner ()->GetNumRatchetInboundTags () : ECIESX25519_MIN_NUM_GENERATED_TAGS); } i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", keydata, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32) // decrypt payload @@ -610,11 +613,23 @@ namespace garlic return false; } HandlePayload (payload, len - 16, receiveTagset, index); - int moreTags = ECIESX25519_MIN_NUM_GENERATED_TAGS + (index >> 2); // N/4 - if (moreTags > ECIESX25519_MAX_NUM_GENERATED_TAGS) moreTags = ECIESX25519_MAX_NUM_GENERATED_TAGS; - moreTags -= (receiveTagset->GetNextIndex () - index); - if (moreTags > 0 && GetOwner ()) - GenerateMoreReceiveTags (receiveTagset, moreTags); + if (GetOwner ()) + { + int moreTags = 0; + if (GetOwner ()->GetNumRatchetInboundTags () > 0) // override in settings? + { + if (receiveTagset->GetNextIndex () - index < GetOwner ()->GetNumRatchetInboundTags ()/2) + moreTags = GetOwner ()->GetNumRatchetInboundTags (); + } + else + { + moreTags = ECIESX25519_MIN_NUM_GENERATED_TAGS + (index >> 2); // N/4 + if (moreTags > ECIESX25519_MAX_NUM_GENERATED_TAGS) moreTags = ECIESX25519_MAX_NUM_GENERATED_TAGS; + moreTags -= (receiveTagset->GetNextIndex () - index); + } + if (moreTags > 0) + GenerateMoreReceiveTags (receiveTagset, moreTags); + } return true; } diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 1170634d..84a0519e 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -432,7 +432,8 @@ namespace garlic return ret; } - GarlicDestination::GarlicDestination (): m_NumTags (32) // 32 tags by default + GarlicDestination::GarlicDestination (): m_NumTags (32), // 32 tags by default + m_NumRatchetInboundTags (0) // 0 means standard { m_Ctx = BN_CTX_new (); } diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index 6b34231a..70893bec 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -232,6 +232,8 @@ namespace garlic void CleanUp (); void SetNumTags (int numTags) { m_NumTags = numTags; }; int GetNumTags () const { return m_NumTags; }; + void SetNumRatchetInboundTags (int numTags) { m_NumRatchetInboundTags = numTags; }; + int GetNumRatchetInboundTags () const { return m_NumRatchetInboundTags; }; std::shared_ptr GetRoutingSession (std::shared_ptr destination, bool attachLeaseSet); void CleanupExpiredTags (); void RemoveDeliveryStatusSession (uint32_t msgID); @@ -278,6 +280,7 @@ namespace garlic std::unordered_map m_Sessions; std::unordered_map, ECIESX25519AEADRatchetSessionPtr> m_ECIESx25519Sessions; // static key -> session // incoming + int m_NumRatchetInboundTags; std::unordered_map, std::hash > > m_Tags; std::unordered_map m_ECIESx25519Tags; // session tag -> session // DeliveryStatus diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 54007c95..0348aeeb 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -461,6 +461,8 @@ namespace client } std::string explicitPeers = GetI2CPStringOption(section, I2CP_PARAM_EXPLICIT_PEERS, ""); if (explicitPeers.length () > 0) options[I2CP_PARAM_EXPLICIT_PEERS] = explicitPeers; + std::string ratchetInboundTags = GetI2CPStringOption(section, I2CP_PARAM_RATCHET_INBOUND_TAGS, ""); + if (ratchetInboundTags.length () > 0) options[I2CP_PARAM_RATCHET_INBOUND_TAGS] = ratchetInboundTags; } void ClientContext::ReadI2CPOptionsFromConfig (const std::string& prefix, std::map& options) const From 79858d4372f1754363ce61059208f5ba4c4329d5 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sat, 13 Jun 2020 18:19:24 +0300 Subject: [PATCH 17/49] [webconsole] adaptive styling Signed-off-by: R4SAS --- android/assets/tunnels.conf | 2 +- daemon/HTTPServer.cpp | 60 ++++++++++++++++++++++++------------- 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/android/assets/tunnels.conf b/android/assets/tunnels.conf index e95fdf2e..c39a0220 100644 --- a/android/assets/tunnels.conf +++ b/android/assets/tunnels.conf @@ -1,4 +1,4 @@ -[IRC-IRC2P] +#[IRC-IRC2P] #type = client #address = 127.0.0.1 #port = 6668 diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 7268ae01..a9588436 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -63,23 +63,40 @@ namespace http { " body { font: 100%/1.5em sans-serif; margin: 0; padding: 1.5em; background: #FAFAFA; color: #103456; }\r\n" " a, .slide label { text-decoration: none; color: #894C84; }\r\n" " a:hover, .slide label:hover { color: #FAFAFA; background: #894C84; }\r\n" - " a.button { -webkit-appearance: button; -moz-appearance: button; appearance: button; text-decoration: none; color: initial; padding: 0 5px; }\r\n" - " .header { font-size: 2.5em; text-align: center; margin: 1.5em 0; color: #894C84; }\r\n" - " .wrapper { margin: 0 auto; padding: 1em; max-width: 60em; }\r\n" - " .left { float: left; position: absolute; }\r\n" - " .right { float: left; font-size: 1em; margin-left: 13em; max-width: 46em; overflow: auto; }\r\n" + " a.button { -webkit-appearance: button; -moz-appearance: button; appearance: button; text-decoration: none;\r\n" + " color: initial; padding: 0 5px; border: 1px solid #894C84; }\r\n" + " .header { font-size: 2.5em; text-align: center; margin: 1em 0; color: #894C84; }\r\n" + " .wrapper { margin: 0 auto; padding: 1em; max-width: 56em; }\r\n" + " .menu { float: left; } .menu a { display: block; padding: 2px; }\r\n" + " .content { float: left; font-size: 1em; margin-left: 4em; max-width: 46em; overflow: auto; }\r\n" " .tunnel.established { color: #56B734; }\r\n" " .tunnel.expiring { color: #D3AE3F; }\r\n" " .tunnel.failed { color: #D33F3F; }\r\n" " .tunnel.building { color: #434343; }\r\n" " caption { font-size: 1.5em; text-align: center; color: #894C84; }\r\n" " table { display: table; border-collapse: collapse; text-align: center; }\r\n" - " table.extaddr { text-align: left; }\r\n table.services { width: 100%; }" + " table.extaddr { text-align: left; } table.services { width: 100%; }\r\n" " .streamdest { width: 120px; max-width: 240px; overflow: hidden; text-overflow: ellipsis;}\r\n" " .slide div.content, .slide [type='checkbox'] { display: none; }\r\n" " .slide [type='checkbox']:checked ~ div.content { display: block; margin-top: 0; padding: 0; }\r\n" " .disabled:after { color: #D33F3F; content: \"Disabled\" }\r\n" " .enabled:after { color: #56B734; content: \"Enabled\" }\r\n" + " @media screen and (max-width: 980px) {\r\n" /* adaptive style */ + " .menu { width: 100%; display: block; float: none; position: unset; font-size: 24px;\r\n" + " text-align: center; }\r\n" + " .content { float: none; margin: 0; margin-top: 16px; max-width: 100%; width: 100%; font-size: 1.2em;\r\n" + " text-align: center; line-height: 28px; }\r\n" + " a, .slide label { /* margin-right: 10px; */ display: block; /* font-size: 18px; */ }\r\n" + " .header { margin: 0.5em 0; } small {display: block}\r\n" + " a.button { -webkit-appearance: button; -moz-appearance: button; appearance: button; text-decoration: none;\r\n" + " color: initial; margin-top: 10px; padding: 6px; border: 1px solid #894c84; width: -webkit-fill-available; }\r\n" + " input { width: 35%; height: 50px; text-align: center; /* margin-top: 15px; */ padding: 5px;\r\n" + " border: 2px solid #ccc; -webkit-border-radius: 5px; border-radius: 5px; font-size: 35px; }\r\n" + " textarea { width: -webkit-fill-available; height: auto; padding:5px; border:2px solid #ccc;\r\n" + " -webkit-border-radius: 5px; border-radius: 5px; font-size: 22px; }\r\n" + " button[type=submit] { padding: 5px 15px; background: #ccc; border: 0 none; cursor: pointer;\r\n" + " -webkit-border-radius: 5px; border-radius: 5px; position: relative; height: 50px; display: -webkit-inline-box; margin-top: 25px; }\r\n" + " }\r\n" /* adaptive style */ "\r\n"; const char HTTP_PAGE_TUNNELS[] = "tunnels"; @@ -181,30 +198,31 @@ namespace http { #else " \r\n" #endif + " \r\n" " \r\n" " Purple I2P " VERSION " Webconsole\r\n" << cssStyles << "\r\n"; s << "\r\n" - "
i2pd webconsole
\r\n" - "
\r\n" - "
\r\n" - " Main page
\r\n
\r\n" - " Router commands
\r\n" - " Local destinations
\r\n"; + "
i2pd webconsole
\r\n" + "
\r\n" + "
\r\n" + " Main page
\r\n" + " Router commands\r\n" + " Local destinations\r\n"; if (i2p::context.IsFloodfill ()) - s << " LeaseSets
\r\n"; + s << " LeaseSets\r\n"; s << - " Tunnels
\r\n" - " Transit tunnels
\r\n" - " Transports
\r\n" - " I2P tunnels
\r\n"; + " Tunnels\r\n" + " Transit tunnels\r\n" + " Transports\r\n" + " I2P tunnels\r\n"; if (i2p::client::context.GetSAMBridge ()) - s << " SAM sessions
\r\n"; + s << " SAM sessions\r\n"; s << "
\r\n" - "
"; + "
"; } static void ShowPageTail (std::stringstream& s) @@ -416,7 +434,7 @@ namespace http { out_tags += it.second->GetNumOutgoingTags (); } s << "
\r\n\r\n" - << "
\r\n\r\n" << tmp_s.str () << "
DestinationAmount
\r\n
\r\n
\r\n"; + << "
\r\n\r\n\r\n\r\n" << tmp_s.str () << "
DestinationAmount
\r\n
\r\n
\r\n"; } else s << "Outgoing: 0
\r\n"; s << "
\r\n"; @@ -432,7 +450,7 @@ namespace http { ecies_sessions++; } s << "
\r\n\r\n" - << "
\r\n\r\n" << tmp_s.str () << "
DestinationStatus
\r\n
\r\n
\r\n"; + << "
\r\n\r\n\r\n\r\n" << tmp_s.str () << "
DestinationStatus
\r\n
\r\n
\r\n"; } else s << "Tags sessions: 0
\r\n"; s << "
\r\n"; From a5fed64f38c7f0b21f31297161ef15fa50f1d79e Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sat, 13 Jun 2020 18:33:39 +0300 Subject: [PATCH 18/49] [webconsole] update sliders html and css Signed-off-by: R4SAS --- daemon/HTTPServer.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index a9588436..41f198c8 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -66,7 +66,7 @@ namespace http { " a.button { -webkit-appearance: button; -moz-appearance: button; appearance: button; text-decoration: none;\r\n" " color: initial; padding: 0 5px; border: 1px solid #894C84; }\r\n" " .header { font-size: 2.5em; text-align: center; margin: 1em 0; color: #894C84; }\r\n" - " .wrapper { margin: 0 auto; padding: 1em; max-width: 56em; }\r\n" + " .wrapper { margin: 0 auto; padding: 1em; max-width: 58em; }\r\n" " .menu { float: left; } .menu a { display: block; padding: 2px; }\r\n" " .content { float: left; font-size: 1em; margin-left: 4em; max-width: 46em; overflow: auto; }\r\n" " .tunnel.established { color: #56B734; }\r\n" @@ -77,8 +77,8 @@ namespace http { " table { display: table; border-collapse: collapse; text-align: center; }\r\n" " table.extaddr { text-align: left; } table.services { width: 100%; }\r\n" " .streamdest { width: 120px; max-width: 240px; overflow: hidden; text-overflow: ellipsis;}\r\n" - " .slide div.content, .slide [type='checkbox'] { display: none; }\r\n" - " .slide [type='checkbox']:checked ~ div.content { display: block; margin-top: 0; padding: 0; }\r\n" + " .slide div.slidecontent, .slide [type=\"checkbox\"] { display: none; }\r\n" + " .slide [type=\"checkbox\"]:checked ~ div.slidecontent { display: block; margin-top: 0; padding: 0; }\r\n" " .disabled:after { color: #D33F3F; content: \"Disabled\" }\r\n" " .enabled:after { color: #56B734; content: \"Enabled\" }\r\n" " @media screen and (max-width: 980px) {\r\n" /* adaptive style */ @@ -284,7 +284,7 @@ namespace http { s << "Data path: " << i2p::fs::GetDataDir() << "
\r\n"; s << "
"; if((outputFormat==OutputFormatEnum::forWebConsole)||!includeHiddenContent) { - s << "\r\n\r\n
\r\n"; + s << "\r\n\r\n
\r\n"; } if(includeHiddenContent) { s << "Router Ident: " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "
\r\n"; @@ -391,7 +391,7 @@ namespace http { if (dest->IsEncryptedLeaseSet ()) { i2p::data::BlindedPublicKey blinded (dest->GetIdentity (), dest->IsPerClientAuth ()); - s << "
\r\n\r\n
\r\n"; + s << "
\r\n\r\n
\r\n"; s << blinded.ToB33 () << ".b32.i2p
\r\n"; s << "
\r\n
\r\n"; } @@ -399,7 +399,7 @@ namespace http { if(dest->GetNumRemoteLeaseSets()) { s << "
\r\n\r\n
\r\n"; + << "\r\n\r\n
\r\n
AddressTypeEncType
"; for(auto& it: dest->GetLeaseSets ()) s << "\r\n"; s << "
AddressTypeEncType
" << it.first.ToBase32 () << "" << (int)it.second->GetStoreType () << "" << (int)it.second->GetEncryptionType () <<"
\r\n
\r\n
\r\n
\r\n"; @@ -433,8 +433,8 @@ namespace http { tmp_s << "" << i2p::client::context.GetAddressBook ().ToAddress(it.first) << "" << it.second->GetNumOutgoingTags () << "\r\n"; out_tags += it.second->GetNumOutgoingTags (); } - s << "
\r\n\r\n" - << "
\r\n\r\n\r\n\r\n" << tmp_s.str () << "
DestinationAmount
\r\n
\r\n
\r\n"; + s << "
\r\n\r\n" + << "
\r\n\r\n\r\n\r\n" << tmp_s.str () << "
DestinationAmount
\r\n
\r\n
\r\n"; } else s << "Outgoing: 0
\r\n"; s << "
\r\n"; @@ -449,8 +449,8 @@ namespace http { tmp_s << "" << i2p::client::context.GetAddressBook ().ToAddress(it.second->GetDestination ()) << "" << it.second->GetState () << "\r\n"; ecies_sessions++; } - s << "
\r\n\r\n" - << "
\r\n\r\n\r\n\r\n" << tmp_s.str () << "
DestinationStatus
\r\n
\r\n
\r\n"; + s << "
\r\n\r\n" + << "
\r\n\r\n\r\n\r\n" << tmp_s.str () << "
DestinationStatus
\r\n
\r\n
\r\n"; } else s << "Tags sessions: 0
\r\n"; s << "
\r\n"; @@ -549,7 +549,7 @@ namespace http { if (!ls->IsValid()) s << "
!! Invalid !!
\r\n"; s << "
\r\n"; - s << "\r\n
\r\n"; + s << "\r\n
\r\n"; s << "Store type: " << (int)storeType << "
\r\n"; s << "Expires: " << ConvertTime(ls->GetExpirationTime()) << "
\r\n"; if (storeType == i2p::data::NETDB_STORE_TYPE_LEASESET || storeType == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2) @@ -700,13 +700,13 @@ namespace http { if (!tmp_s.str ().empty ()) { s << "
\r\n\r\n
" + << " ( " << cnt << " )\r\n\r\n
" << tmp_s.str () << "
\r\n
\r\n"; } if (!tmp_s6.str ().empty ()) { s << "
\r\n\r\n
" + << "v6 ( " << cnt6 << " )\r\n\r\n
" << tmp_s6.str () << "
\r\n
\r\n"; } } @@ -734,7 +734,7 @@ namespace http { auto sessions = ssuServer->GetSessions (); if (!sessions.empty ()) { - s << "
\r\n\r\n
"; + s << "
\r\n\r\n
"; for (const auto& it: sessions) { auto endpoint = it.second->GetRemoteEndpoint (); @@ -751,7 +751,7 @@ namespace http { auto sessions6 = ssuServer->GetSessionsV6 (); if (!sessions6.empty ()) { - s << "
\r\n\r\n
"; + s << "
\r\n\r\n
"; for (const auto& it: sessions6) { auto endpoint = it.second->GetRemoteEndpoint (); From 1a39f7e5c608c6dd2443aef27534f05d9e56f4f9 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 13 Jun 2020 16:18:12 -0400 Subject: [PATCH 19/49] GarlicRoutingPath per session --- libi2pd/Datagram.cpp | 118 +++++++++++++++++++------------------------ libi2pd/Datagram.h | 2 - 2 files changed, 53 insertions(+), 67 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 5a196c3a..ad679cc0 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -281,94 +281,82 @@ namespace datagram std::shared_ptr DatagramSession::GetSharedRoutingPath () { - if (!m_RoutingSession || !m_RoutingSession->GetOwner ()) + if (!m_RemoteLeaseSet || m_RemoteLeaseSet->IsExpired ()) { - if(!m_RemoteLeaseSet) { - m_RemoteLeaseSet = m_LocalDestination->FindLeaseSet(m_RemoteIdent); - } - if(!m_RemoteLeaseSet) { - // no remote lease set - if(!m_RequestingLS) { + m_RemoteLeaseSet = m_LocalDestination->FindLeaseSet(m_RemoteIdent); + if (!m_RemoteLeaseSet) + { + if(!m_RequestingLS) + { m_RequestingLS = true; m_LocalDestination->RequestDestination(m_RemoteIdent, std::bind(&DatagramSession::HandleLeaseSetUpdated, this, std::placeholders::_1)); } return nullptr; - } + } + } + + if (!m_RoutingSession || !m_RoutingSession->GetOwner ()) m_RoutingSession = m_LocalDestination->GetRoutingSession(m_RemoteLeaseSet, true); - } + auto path = m_RoutingSession->GetSharedRoutingPath(); - if(path) { - if (m_CurrentOutboundTunnel && !m_CurrentOutboundTunnel->IsEstablished()) { + if (path) + { + if (path->outboundTunnel && !path->outboundTunnel->IsEstablished ()) // bad outbound tunnel, switch outbound tunnel - m_CurrentOutboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(m_CurrentOutboundTunnel); - path->outboundTunnel = m_CurrentOutboundTunnel; - } - if(m_CurrentRemoteLease && m_CurrentRemoteLease->ExpiresWithin(DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW)) { + path->outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(path->outboundTunnel); + + if (path->remoteLease && path->remoteLease->ExpiresWithin(DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW)) + { // bad lease, switch to next one - if(m_RemoteLeaseSet && m_RemoteLeaseSet->IsExpired()) - m_RemoteLeaseSet = m_LocalDestination->FindLeaseSet(m_RemoteIdent); - if(m_RemoteLeaseSet) { - auto ls = m_RemoteLeaseSet->GetNonExpiredLeasesExcluding([&](const i2p::data::Lease& l) -> bool { - return l.tunnelID == m_CurrentRemoteLease->tunnelID; - }); + if (m_RemoteLeaseSet) + { + auto ls = m_RemoteLeaseSet->GetNonExpiredLeasesExcluding( + [&](const i2p::data::Lease& l) -> bool + { + return l.tunnelID == path->remoteLease->tunnelID; + }); auto sz = ls.size(); - if (sz) { + if (sz) + { auto idx = rand() % sz; - m_CurrentRemoteLease = ls[idx]; + path->remoteLease = ls[idx]; } - } else { + else + path->remoteLease = nullptr; + } + else // no remote lease set? LogPrint(eLogWarning, "DatagramSession: no cached remote lease set for ", m_RemoteIdent.ToBase32()); - } - path->remoteLease = m_CurrentRemoteLease; } - } else { + } + else + { // no current path, make one path = std::make_shared(); - // switch outbound tunnel if bad - if(m_CurrentOutboundTunnel == nullptr || ! m_CurrentOutboundTunnel->IsEstablished()) { - m_CurrentOutboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(m_CurrentOutboundTunnel); - } - // switch lease if bad - if(m_CurrentRemoteLease && m_CurrentRemoteLease->ExpiresWithin(DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW)) { - if(!m_RemoteLeaseSet) { - m_RemoteLeaseSet = m_LocalDestination->FindLeaseSet(m_RemoteIdent); - } - if(m_RemoteLeaseSet) { - // pick random next good lease - auto ls = m_RemoteLeaseSet->GetNonExpiredLeasesExcluding([&] (const i2p::data::Lease & l) -> bool { - if(m_CurrentRemoteLease) - return l.tunnelGateway == m_CurrentRemoteLease->tunnelGateway; - return false; - }); - auto sz = ls.size(); - if(sz) { - auto idx = rand() % sz; - m_CurrentRemoteLease = ls[idx]; - } - } else { - // no remote lease set currently, bail - LogPrint(eLogWarning, "DatagramSession: no remote lease set found for ", m_RemoteIdent.ToBase32()); - return nullptr; - } - } else if (!m_CurrentRemoteLease) { - if(!m_RemoteLeaseSet) m_RemoteLeaseSet = m_LocalDestination->FindLeaseSet(m_RemoteIdent); - if (m_RemoteLeaseSet) + path->outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(); + + if (m_RemoteLeaseSet) + { + // pick random next good lease + auto ls = m_RemoteLeaseSet->GetNonExpiredLeases(); + auto sz = ls.size(); + if (sz) { - auto ls = m_RemoteLeaseSet->GetNonExpiredLeases(); - auto sz = ls.size(); - if (sz) { - auto idx = rand() % sz; - m_CurrentRemoteLease = ls[idx]; - } + auto idx = rand() % sz; + path->remoteLease = ls[idx]; } + + + } + else + { + // no remote lease set currently, bail + LogPrint(eLogWarning, "DatagramSession: no remote lease set found for ", m_RemoteIdent.ToBase32()); + return nullptr; } - path->outboundTunnel = m_CurrentOutboundTunnel; - path->remoteLease = m_CurrentRemoteLease; m_RoutingSession->SetSharedRoutingPath(path); } return path; - } void DatagramSession::HandleLeaseSetUpdated(std::shared_ptr ls) diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index 94fe422c..66e9e909 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -95,8 +95,6 @@ namespace datagram i2p::data::IdentHash m_RemoteIdent; std::shared_ptr m_RemoteLeaseSet; std::shared_ptr m_RoutingSession; - std::shared_ptr m_CurrentRemoteLease; - std::shared_ptr m_CurrentOutboundTunnel; std::vector > m_SendQueue; uint64_t m_LastUse; bool m_RequestingLS; From 0f309377ecf57c9edc23324da8368c22624fa5b1 Mon Sep 17 00:00:00 2001 From: Anton Nesterov Date: Sat, 13 Jun 2020 20:46:17 +0000 Subject: [PATCH 20/49] Improve AppArmor profile - give it a name - import needed abstractions - allow local additions - cleanup --- contrib/apparmor/usr.sbin.i2pd | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/contrib/apparmor/usr.sbin.i2pd b/contrib/apparmor/usr.sbin.i2pd index 6cc80609..1e47cd74 100644 --- a/contrib/apparmor/usr.sbin.i2pd +++ b/contrib/apparmor/usr.sbin.i2pd @@ -4,34 +4,22 @@ # #include -/usr/sbin/i2pd { +profile i2pd /{usr/,}sbin/i2pd { #include - - network inet dgram, - network inet stream, - network inet6 dgram, - network inet6 stream, - network netlink raw, - - /etc/gai.conf r, - /etc/host.conf r, - /etc/hosts r, - /etc/nsswitch.conf r, - /etc/resolv.conf r, - /run/resolvconf/resolv.conf r, - /run/systemd/resolve/resolv.conf r, - /run/systemd/resolve/stub-resolv.conf r, + #include + #include # path specific (feel free to modify if you have another paths) /etc/i2pd/** r, - /run/i2pd/i2pd.pid rwk, /var/lib/i2pd/** rw, /var/log/i2pd/i2pd.log w, - /var/run/i2pd/i2pd.pid rwk, - /usr/sbin/i2pd mr, - /usr/share/i2pd/** r, + /{var/,}run/i2pd/i2pd.pid rwk, + /{usr/,}sbin/i2pd mr, + @{system_share_dirs}/i2pd/** r, # user homedir (if started not by init.d or systemd) owner @{HOME}/.i2pd/ rw, owner @{HOME}/.i2pd/** rwk, + + #include if exists } From 69194118dfe3c6e0201efc3db6671bbf1d81e32e Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 13 Jun 2020 21:24:16 -0400 Subject: [PATCH 21/49] generate random padding length in bulk --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 9 +++++++-- libi2pd/ECIESX25519AEADRatchetSession.h | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index ad91382f..87fd13ed 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -96,6 +96,7 @@ namespace garlic ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet): GarlicRoutingSession (owner, attachLeaseSet) { + RAND_bytes (m_PaddingSizes, 32); m_NextPaddingSize = 0; ResetKeys (); } @@ -745,8 +746,12 @@ namespace garlic int delta = (int)ECIESX25519_OPTIMAL_PAYLOAD_SIZE - (int)payloadLen; if (delta < 0 || delta > 3) // don't create padding if we are close to optimal size { - RAND_bytes (&paddingSize, 1); - paddingSize &= 0x0F; // 0 - 15 + paddingSize = m_PaddingSizes[m_NextPaddingSize++] & 0x0F; // 0 - 15 + if (m_NextPaddingSize >= 32) + { + RAND_bytes (m_PaddingSizes, 32); + m_NextPaddingSize = 0; + } if (delta > 3) { delta -= 3; diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index d121842d..727c48ac 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -188,7 +188,8 @@ namespace garlic std::list > m_AckRequests; // (tagsetid, index) bool m_SendReverseKey = false, m_SendForwardKey = false; std::unique_ptr m_NextReceiveRatchet, m_NextSendRatchet; - + uint8_t m_PaddingSizes[32], m_NextPaddingSize; + public: // for HTTP only From 1e609acb035dba27116d3f3b4f3a63740aa52e3d Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 14 Jun 2020 11:16:08 -0400 Subject: [PATCH 22/49] keep sending through first successive routing path --- libi2pd/Datagram.cpp | 20 +++++++++++++++++--- libi2pd/Datagram.h | 1 + 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index ad679cc0..844611d3 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -296,7 +296,23 @@ namespace datagram } if (!m_RoutingSession || !m_RoutingSession->GetOwner ()) - m_RoutingSession = m_LocalDestination->GetRoutingSession(m_RemoteLeaseSet, true); + { + bool found = false; + for (auto& it: m_PendingRoutingSessions) + if (it->GetOwner ()) // found established session + { + m_RoutingSession = it; + m_PendingRoutingSessions.clear (); + found = true; + break; + } + if (!found) + { + m_RoutingSession = m_LocalDestination->GetRoutingSession(m_RemoteLeaseSet, true); + if (!m_RoutingSession->GetOwner ()) + m_PendingRoutingSessions.push_back (m_RoutingSession); + } + } auto path = m_RoutingSession->GetSharedRoutingPath(); if (path) @@ -345,8 +361,6 @@ namespace datagram auto idx = rand() % sz; path->remoteLease = ls[idx]; } - - } else { diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index 66e9e909..5dd6c8b6 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -95,6 +95,7 @@ namespace datagram i2p::data::IdentHash m_RemoteIdent; std::shared_ptr m_RemoteLeaseSet; std::shared_ptr m_RoutingSession; + std::vector > m_PendingRoutingSessions; std::vector > m_SendQueue; uint64_t m_LastUse; bool m_RequestingLS; From 8d903a09e2a20d790fe287ca66eb4b4c458c8efa Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sun, 14 Jun 2020 22:18:41 +0300 Subject: [PATCH 23/49] [Docker] drop boost-python2 --- contrib/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index 6b6250d0..be3feea7 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -36,7 +36,7 @@ RUN apk --no-cache --virtual build-dependendencies add make gcc g++ libtool zlib && cd /usr/local/bin \ && strip i2pd \ && rm -fr /tmp/build && apk --no-cache --purge del build-dependendencies build-base fortify-headers boost-dev zlib-dev openssl-dev \ - boost-python3 python3 gdbm boost-unit_test_framework boost-python2 linux-headers boost-prg_exec_monitor \ + boost-python3 python3 gdbm boost-unit_test_framework linux-headers boost-prg_exec_monitor \ boost-serialization boost-wave boost-wserialization boost-math boost-graph boost-regex git pcre2 \ libtool g++ gcc From 70e4cbc0236d253b68d6747c0a3c046f9c095384 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 15 Jun 2020 20:10:47 -0400 Subject: [PATCH 24/49] differentiate UDP server sessions by port --- libi2pd_client/I2PTunnel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index d05a97b7..95f56873 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -611,7 +611,7 @@ namespace client void I2PUDPServerTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) { - if (!m_LastSession || m_LastSession->Identity.GetLL()[0] != from.GetIdentHash ().GetLL()[0]) + if (!m_LastSession || m_LastSession->Identity.GetLL()[0] != from.GetIdentHash ().GetLL()[0] || fromPort != m_LastSession->RemotePort) { std::lock_guard lock(m_SessionsMutex); m_LastSession = ObtainUDPSession(from, toPort, fromPort); @@ -659,7 +659,7 @@ namespace client auto ih = from.GetIdentHash(); for (auto & s : m_Sessions ) { - if (s->Identity.GetLL()[0] == ih.GetLL()[0]) + if (s->Identity.GetLL()[0] == ih.GetLL()[0] && remotePort == s->RemotePort) { /** found existing session */ LogPrint(eLogDebug, "UDPServer: found session ", s->IPSocket.local_endpoint(), " ", ih.ToBase32()); From 31494267e5856b0f685f323e6cfcbbd66dde16dd Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 17 Jun 2020 14:24:25 -0400 Subject: [PATCH 25/49] fixed datagram idle crash --- libi2pd/Datagram.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 844611d3..b9938043 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -318,8 +318,12 @@ namespace datagram if (path) { if (path->outboundTunnel && !path->outboundTunnel->IsEstablished ()) + { // bad outbound tunnel, switch outbound tunnel path->outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(path->outboundTunnel); + if (!path->outboundTunnel) + m_RoutingSession->SetSharedRoutingPath (nullptr); + } if (path->remoteLease && path->remoteLease->ExpiresWithin(DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW)) { @@ -338,11 +342,14 @@ namespace datagram path->remoteLease = ls[idx]; } else - path->remoteLease = nullptr; + m_RoutingSession->SetSharedRoutingPath (nullptr); } else + { // no remote lease set? LogPrint(eLogWarning, "DatagramSession: no cached remote lease set for ", m_RemoteIdent.ToBase32()); + m_RoutingSession->SetSharedRoutingPath (nullptr); + } } } else @@ -350,7 +357,8 @@ namespace datagram // no current path, make one path = std::make_shared(); path->outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(); - + if (!path->outboundTunnel) return nullptr; + if (m_RemoteLeaseSet) { // pick random next good lease @@ -361,6 +369,8 @@ namespace datagram auto idx = rand() % sz; path->remoteLease = ls[idx]; } + else + return nullptr; } else { From 951ec567c7769e2f4b8adf1c5876052260821e89 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 17 Jun 2020 21:06:35 -0400 Subject: [PATCH 26/49] don't try to connect though teminated local destination --- libi2pd_client/SAM.cpp | 23 +++++++++++++++-------- libi2pd_client/SAM.h | 2 +- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 4723d168..63b9c7ed 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -494,7 +494,7 @@ namespace client context.GetAddressBook().InsertFullAddress(dest); auto leaseSet = session->localDestination->FindLeaseSet(dest->GetIdentHash()); if (leaseSet) - Connect(leaseSet); + Connect(leaseSet, session); else { session->localDestination->RequestDestination(dest->GetIdentHash(), @@ -509,18 +509,25 @@ namespace client SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); } - void SAMSocket::Connect (std::shared_ptr remote) + void SAMSocket::Connect (std::shared_ptr remote, std::shared_ptr session) { - auto session = m_Owner.FindSession(m_ID); - if(session) + if (!session) session = m_Owner.FindSession(m_ID); + if (session) { m_SocketType = eSAMSocketTypeStream; m_Stream = session->localDestination->CreateStream (remote); - m_Stream->Send ((uint8_t *)m_Buffer, m_BufferOffset); // connect and send - m_BufferOffset = 0; - I2PReceive (); - SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + if (m_Stream) + { + m_Stream->Send ((uint8_t *)m_Buffer, m_BufferOffset); // connect and send + m_BufferOffset = 0; + I2PReceive (); + SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + } + else + SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); } + else + SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); } void SAMSocket::HandleConnectLeaseSetRequestComplete (std::shared_ptr leaseSet) diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index ceda5253..7b1702f5 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -134,7 +134,7 @@ namespace client size_t ProcessDatagramSend (char * buf, size_t len, const char * data); // from SAM 1.0 void ExtractParams (char * buf, std::map& params); - void Connect (std::shared_ptr remote); + void Connect (std::shared_ptr remote, std::shared_ptr session = nullptr); void HandleConnectLeaseSetRequestComplete (std::shared_ptr leaseSet); void SendNamingLookupReply (std::shared_ptr identity); void HandleNamingLookupLeaseSetRequestComplete (std::shared_ptr leaseSet, std::string name); From a0b35ebd3ef68dd4d4ccacf6cef218000e618c2f Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 22 Jun 2020 22:32:18 -0400 Subject: [PATCH 27/49] mark NTCP2 unreachable routers --- libi2pd/NTCP2.cpp | 3 ++- libi2pd/Transports.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 8b44a795..60eab17c 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1305,7 +1305,8 @@ namespace transport if (ecode != boost::asio::error::operation_aborted) { LogPrint (eLogInfo, "NTCP2: Not connected in ", timeout, " seconds"); - //i2p::data::netdb.SetUnreachable (conn->GetRemoteIdentity ()->GetIdentHash (), true); + if (conn->GetRemoteIdentity ()) + i2p::data::netdb.SetUnreachable (conn->GetRemoteIdentity ()->GetIdentHash (), true); conn->Terminate (); } }); diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 7157306d..6f163e5f 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -440,7 +440,7 @@ namespace transport { // NTCP2 have priority over NTCP auto address = peer.router->GetNTCP2Address (true, !context.SupportsV6 ()); // published only - if (address) + if (address && !peer.router->IsUnreachable ()) { auto s = std::make_shared (*m_NTCP2Server, peer.router); From 61e9c31f0dc3a3bda295fd4fdb0f80a3ac099ca9 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 24 Jun 2020 11:29:54 -0400 Subject: [PATCH 28/49] don't hold RouterInfo after successive connect --- libi2pd/Transports.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 6f163e5f..7da0f63b 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -431,6 +431,8 @@ namespace transport bool Transports::ConnectToPeer (const i2p::data::IdentHash& ident, Peer& peer) { + if (!peer.router) // reconnect + peer.router = netdb.FindRouter (ident); // try to get new one from netdb if (peer.router) // we have RI already { if (!peer.numAttempts) // NTCP2 @@ -638,6 +640,7 @@ namespace transport auto it = m_Peers.find (ident); if (it != m_Peers.end ()) { + it->second.router = nullptr; // we don't need RouterInfo after successive connect bool sendDatabaseStore = true; if (it->second.delayedMessages.size () > 0) { From df9965e1295de377516cb3a15aa68ef1a86c71f6 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 29 Jun 2020 18:19:31 -0400 Subject: [PATCH 29/49] use unordered_map for peers --- libi2pd/Transports.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index cdfbfccf..95c7aedb 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -157,7 +157,7 @@ namespace transport SSUServer * m_SSUServer; NTCP2Server * m_NTCP2Server; mutable std::mutex m_PeersMutex; - std::map m_Peers; + std::unordered_map m_Peers; DHKeysPairSupplier m_DHKeysPairSupplier; From 1f31fdc257ec0a0f44fd263d0fb0ed9fa14464a8 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 29 Jun 2020 20:02:09 -0400 Subject: [PATCH 30/49] pre-calculate ephemeral keys for x25519 --- libi2pd/NTCP2.cpp | 8 +++---- libi2pd/NTCP2.h | 4 ++-- libi2pd/Transports.cpp | 52 +++++++++++++++++++++++++++++------------- libi2pd/Transports.h | 23 ++++++++++++------- 4 files changed, 57 insertions(+), 30 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 60eab17c..f1f7e59f 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -83,7 +83,7 @@ namespace transport void NTCP2Establisher::KDF1Alice () { - KeyDerivationFunction1 (m_RemoteStaticKey, m_EphemeralKeys, m_RemoteStaticKey, GetPub ()); + KeyDerivationFunction1 (m_RemoteStaticKey, *m_EphemeralKeys, m_RemoteStaticKey, GetPub ()); } void NTCP2Establisher::KDF1Bob () @@ -102,7 +102,7 @@ namespace transport // x25519 between remote pub and ephemaral priv uint8_t inputKeyMaterial[32]; - m_EphemeralKeys.Agree (GetRemotePub (), inputKeyMaterial); + m_EphemeralKeys->Agree (GetRemotePub (), inputKeyMaterial); MixKey (inputKeyMaterial); } @@ -127,13 +127,13 @@ namespace transport void NTCP2Establisher::KDF3Bob () { uint8_t inputKeyMaterial[32]; - m_EphemeralKeys.Agree (m_RemoteStaticKey, inputKeyMaterial); + m_EphemeralKeys->Agree (m_RemoteStaticKey, inputKeyMaterial); MixKey (inputKeyMaterial); } void NTCP2Establisher::CreateEphemeralKey () { - m_EphemeralKeys.GenerateKeys (); + m_EphemeralKeys = i2p::transport::transports.GetNextX25519KeysPair (); } void NTCP2Establisher::CreateSessionRequestMessage () diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index 8b8c6acb..df72fed0 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -79,7 +79,7 @@ namespace transport NTCP2Establisher (); ~NTCP2Establisher (); - const uint8_t * GetPub () const { return m_EphemeralKeys.GetPublicKey (); }; + const uint8_t * GetPub () const { return m_EphemeralKeys->GetPublicKey (); }; const uint8_t * GetRemotePub () const { return m_RemoteEphemeralPublicKey; }; // Y for Alice and X for Bob uint8_t * GetRemotePub () { return m_RemoteEphemeralPublicKey; }; // to set @@ -110,7 +110,7 @@ namespace transport bool ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce); bool ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf); - i2p::crypto::X25519Keys m_EphemeralKeys; + std::shared_ptr m_EphemeralKeys; uint8_t m_RemoteEphemeralPublicKey[32]; // x25519 uint8_t m_RemoteStaticKey[32], m_IV[16], m_H[32] /*h*/, m_CK[64] /* [ck, k]*/; i2p::data::IdentHash m_RemoteIdentHash; diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 7da0f63b..edfe33fa 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -21,23 +21,27 @@ namespace i2p { namespace transport { - DHKeysPairSupplier::DHKeysPairSupplier (int size): + template + EphemeralKeysSupplier::EphemeralKeysSupplier (int size): m_QueueSize (size), m_IsRunning (false), m_Thread (nullptr) { } - DHKeysPairSupplier::~DHKeysPairSupplier () + template + EphemeralKeysSupplier::~EphemeralKeysSupplier () { Stop (); } - void DHKeysPairSupplier::Start () + template + void EphemeralKeysSupplier::Start () { m_IsRunning = true; - m_Thread = new std::thread (std::bind (&DHKeysPairSupplier::Run, this)); + m_Thread = new std::thread (std::bind (&EphemeralKeysSupplier::Run, this)); } - void DHKeysPairSupplier::Stop () + template + void EphemeralKeysSupplier::Stop () { { std::unique_lock l(m_AcquiredMutex); @@ -52,19 +56,20 @@ namespace transport } } - void DHKeysPairSupplier::Run () + template + void EphemeralKeysSupplier::Run () { while (m_IsRunning) { int num, total = 0; while ((num = m_QueueSize - (int)m_Queue.size ()) > 0 && total < 10) { - CreateDHKeysPairs (num); + CreateEphemeralKeys (num); total += num; } if (total >= 10) { - LogPrint (eLogWarning, "Transports: ", total, " DH keys generated at the time"); + LogPrint (eLogWarning, "Transports: ", total, " ephemeral keys generated at the time"); std::this_thread::sleep_for (std::chrono::seconds(1)); // take a break } else @@ -76,24 +81,26 @@ namespace transport } } - void DHKeysPairSupplier::CreateDHKeysPairs (int num) + template + void EphemeralKeysSupplier::CreateEphemeralKeys (int num) { if (num > 0) { for (int i = 0; i < num; i++) { - auto pair = std::make_shared (); + auto pair = std::make_shared (); pair->GenerateKeys (); - std::unique_lock l(m_AcquiredMutex); + std::unique_lock l(m_AcquiredMutex); m_Queue.push (pair); } } } - std::shared_ptr DHKeysPairSupplier::Acquire () + template + std::shared_ptr EphemeralKeysSupplier::Acquire () { { - std::unique_lock l(m_AcquiredMutex); + std::unique_lock l(m_AcquiredMutex); if (!m_Queue.empty ()) { auto pair = m_Queue.front (); @@ -103,12 +110,13 @@ namespace transport } } // queue is empty, create new - auto pair = std::make_shared (); + auto pair = std::make_shared (); pair->GenerateKeys (); return pair; } - void DHKeysPairSupplier::Return (std::shared_ptr pair) + template + void EphemeralKeysSupplier::Return (std::shared_ptr pair) { if (pair) { @@ -126,7 +134,7 @@ namespace transport m_IsOnline (true), m_IsRunning (false), m_IsNAT (true), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr), m_PeerCleanupTimer (nullptr), m_PeerTestTimer (nullptr), m_NTCPServer (nullptr), m_SSUServer (nullptr), m_NTCP2Server (nullptr), - m_DHKeysPairSupplier (5), // 5 pre-generated keys + m_DHKeysPairSupplier (5), m_X25519KeysPairSupplier (5), // 5 pre-generated keys m_TotalSentBytes(0), m_TotalReceivedBytes(0), m_TotalTransitTransmittedBytes (0), m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth(0), m_LastInBandwidthUpdateBytes (0), m_LastOutBandwidthUpdateBytes (0), @@ -158,6 +166,7 @@ namespace transport i2p::config::GetOption("nat", m_IsNAT); m_DHKeysPairSupplier.Start (); + m_X25519KeysPairSupplier.Start (); m_IsRunning = true; m_Thread = new std::thread (std::bind (&Transports::Run, this)); std::string ntcpproxy; i2p::config::GetOption("ntcpproxy", ntcpproxy); @@ -312,6 +321,7 @@ namespace transport } m_DHKeysPairSupplier.Stop (); + m_X25519KeysPairSupplier.Stop (); m_IsRunning = false; if (m_Service) m_Service->stop (); if (m_Thread) @@ -630,6 +640,16 @@ namespace transport m_DHKeysPairSupplier.Return (pair); } + std::shared_ptr Transports::GetNextX25519KeysPair () + { + return m_X25519KeysPairSupplier.Acquire (); + } + + void Transports::ReuseX25519KeysPair (std::shared_ptr pair) + { + m_X25519KeysPairSupplier.Return (pair); + } + void Transports::PeerConnected (std::shared_ptr session) { m_Service->post([session, this]() diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index 95c7aedb..48eee4b4 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -32,33 +32,37 @@ namespace i2p { namespace transport { - class DHKeysPairSupplier + template + class EphemeralKeysSupplier { + // called from this file only, so implementation is in Transports.cpp public: - DHKeysPairSupplier (int size); - ~DHKeysPairSupplier (); + EphemeralKeysSupplier (int size); + ~EphemeralKeysSupplier (); void Start (); void Stop (); - std::shared_ptr Acquire (); - void Return (std::shared_ptr pair); + std::shared_ptr Acquire (); + void Return (std::shared_ptr pair); private: void Run (); - void CreateDHKeysPairs (int num); + void CreateEphemeralKeys (int num); private: const int m_QueueSize; - std::queue > m_Queue; + std::queue > m_Queue; bool m_IsRunning; std::thread * m_Thread; std::condition_variable m_Acquired; std::mutex m_AcquiredMutex; }; - + typedef EphemeralKeysSupplier DHKeysPairSupplier; + typedef EphemeralKeysSupplier X25519KeysPairSupplier; + struct Peer { int numAttempts; @@ -97,6 +101,8 @@ namespace transport boost::asio::io_service& GetService () { return *m_Service; }; std::shared_ptr GetNextDHKeysPair (); void ReuseDHKeysPair (std::shared_ptr pair); + std::shared_ptr GetNextX25519KeysPair (); + void ReuseX25519KeysPair (std::shared_ptr pair); void SendMessage (const i2p::data::IdentHash& ident, std::shared_ptr msg); void SendMessages (const i2p::data::IdentHash& ident, const std::vector >& msgs); @@ -160,6 +166,7 @@ namespace transport std::unordered_map m_Peers; DHKeysPairSupplier m_DHKeysPairSupplier; + X25519KeysPairSupplier m_X25519KeysPairSupplier; std::atomic m_TotalSentBytes, m_TotalReceivedBytes, m_TotalTransitTransmittedBytes; uint32_t m_InBandwidth, m_OutBandwidth, m_TransitBandwidth; // bytes per second From 5f1e66d64b2c92af5082f9b29b5e6d52ad4130d4 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 30 Jun 2020 13:00:41 -0400 Subject: [PATCH 31/49] use pre-calculated x25519 ephemeral keys for ratchets --- libi2pd/Crypto.h | 4 ++ libi2pd/ECIESX25519AEADRatchetSession.cpp | 59 +++++++++++++++++------ libi2pd/ECIESX25519AEADRatchetSession.h | 4 +- 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 9ca3163f..ab84e56a 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -91,6 +91,9 @@ namespace crypto void SetPrivateKey (const uint8_t * priv, bool calculatePublic = false); void Agree (const uint8_t * pub, uint8_t * shared); + bool IsElligatorIneligible () const { return m_IsElligatorIneligible; } + void SetElligatorIneligible () { m_IsElligatorIneligible = true; } + private: uint8_t m_PublicKey[32]; @@ -101,6 +104,7 @@ namespace crypto BN_CTX * m_Ctx; uint8_t m_PrivateKey[32]; #endif + bool m_IsElligatorIneligible = false; // true if definitly ineligible }; // ElGamal diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 87fd13ed..8e0e743d 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -16,6 +16,7 @@ #include "Timestamp.h" #include "Tunnel.h" #include "TunnelPool.h" +#include "Transports.h" #include "ECIESX25519AEADRatchetSession.h" namespace i2p @@ -137,12 +138,38 @@ namespace garlic bool ECIESX25519AEADRatchetSession::GenerateEphemeralKeysAndEncode (uint8_t * buf) { + bool ineligible = false; + while (!ineligible) + { + m_EphemeralKeys = i2p::transport::transports.GetNextX25519KeysPair (); + ineligible = m_EphemeralKeys->IsElligatorIneligible (); + if (!ineligible) // we haven't tried it yet + { + if (i2p::crypto::GetElligator ()->Encode (m_EphemeralKeys->GetPublicKey (), buf)) + return true; // success + // otherwise return back + m_EphemeralKeys->SetElligatorIneligible (); + i2p::transport::transports.ReuseX25519KeysPair (m_EphemeralKeys); + } + else + i2p::transport::transports.ReuseX25519KeysPair (m_EphemeralKeys); + } + // we still didn't find elligator eligible pair for (int i = 0; i < 10; i++) { - m_EphemeralKeys.GenerateKeys (); - if (i2p::crypto::GetElligator ()->Encode (m_EphemeralKeys.GetPublicKey (), buf)) + // create new + m_EphemeralKeys = std::make_shared(); + m_EphemeralKeys->GenerateKeys (); + if (i2p::crypto::GetElligator ()->Encode (m_EphemeralKeys->GetPublicKey (), buf)) return true; // success + else + { + // let NTCP2 use it + m_EphemeralKeys->SetElligatorIneligible (); + i2p::transport::transports.ReuseX25519KeysPair (m_EphemeralKeys); + } } + LogPrint (eLogError, "Garlic: Can't generate elligator eligible x25519 keys"); return false; } @@ -294,7 +321,7 @@ namespace garlic if (flag & ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG) memcpy (m_NextSendRatchet->remote, buf, 32); uint8_t sharedSecret[32], tagsetKey[32]; - m_NextSendRatchet->key.Agree (m_NextSendRatchet->remote, sharedSecret); + m_NextSendRatchet->key->Agree (m_NextSendRatchet->remote, sharedSecret); i2p::crypto::HKDF (sharedSecret, nullptr, 0, "XDHRatchetTagSet", tagsetKey, 32); // tagsetKey = HKDF(sharedSecret, ZEROLEN, "XDHRatchetTagSet", 32) auto newTagset = std::make_shared (shared_from_this ()); newTagset->SetTagSetID (1 + m_NextSendRatchet->keyID + keyID); @@ -326,7 +353,7 @@ namespace garlic int tagsetID = 2*keyID; if (newKey) { - m_NextReceiveRatchet->key.GenerateKeys (); + m_NextReceiveRatchet->key = i2p::transport::transports.GetNextX25519KeysPair (); m_NextReceiveRatchet->newKey = true; tagsetID++; } @@ -336,7 +363,7 @@ namespace garlic memcpy (m_NextReceiveRatchet->remote, buf, 32); uint8_t sharedSecret[32], tagsetKey[32]; - m_NextReceiveRatchet->key.Agree (m_NextReceiveRatchet->remote, sharedSecret); + m_NextReceiveRatchet->key->Agree (m_NextReceiveRatchet->remote, sharedSecret); i2p::crypto::HKDF (sharedSecret, nullptr, 0, "XDHRatchetTagSet", tagsetKey, 32); // tagsetKey = HKDF(sharedSecret, ZEROLEN, "XDHRatchetTagSet", 32) auto newTagset = std::make_shared(shared_from_this ()); newTagset->SetTagSetID (tagsetID); @@ -364,7 +391,7 @@ namespace garlic else m_NextSendRatchet.reset (new DHRatchet ()); if (m_NextSendRatchet->newKey) - m_NextSendRatchet->key.GenerateKeys (); + m_NextSendRatchet->key->GenerateKeys (); m_SendForwardKey = true; LogPrint (eLogDebug, "Garlic: new send ratchet ", m_NextSendRatchet->newKey ? "new" : "old", " key ", m_NextSendRatchet->keyID, " created"); @@ -384,9 +411,9 @@ namespace garlic // KDF1 MixHash (m_RemoteStaticKey, 32); // h = SHA256(h || bpk) - MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || aepk) + MixHash (m_EphemeralKeys->GetPublicKey (), 32); // h = SHA256(h || aepk) uint8_t sharedSecret[32]; - m_EphemeralKeys.Agree (m_RemoteStaticKey, sharedSecret); // x25519(aesk, bpk) + m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret); // x25519(aesk, bpk) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) // encrypt static key section uint8_t nonce[12]; @@ -435,11 +462,11 @@ namespace garlic offset += 32; // KDF for Reply Key Section MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag) - MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || bepk) + MixHash (m_EphemeralKeys->GetPublicKey (), 32); // h = SHA256(h || bepk) uint8_t sharedSecret[32]; - m_EphemeralKeys.Agree (m_Aepk, sharedSecret); // sharedSecret = x25519(besk, aepk) + m_EphemeralKeys->Agree (m_Aepk, sharedSecret); // sharedSecret = x25519(besk, aepk) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32) - m_EphemeralKeys.Agree (m_RemoteStaticKey, sharedSecret); // sharedSecret = x25519(besk, apk) + m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret); // sharedSecret = x25519(besk, apk) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) uint8_t nonce[12]; CreateNonce (0, nonce); @@ -485,7 +512,7 @@ namespace garlic // recalculate h with new tag memcpy (m_H, m_NSRH, 32); MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag) - MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || bepk) + MixHash (m_EphemeralKeys->GetPublicKey (), 32); // h = SHA256(h || bepk) uint8_t nonce[12]; CreateNonce (0, nonce); if (!i2p::crypto::AEADChaCha20Poly1305 (nonce /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + 40, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad) @@ -524,7 +551,7 @@ namespace garlic if (m_State == eSessionStateNewSessionSent) { // only fist time, we assume ephemeral keys the same - m_EphemeralKeys.Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk) + m_EphemeralKeys->Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32) GetOwner ()->Decrypt (bepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519 (ask, bepk) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) @@ -565,6 +592,7 @@ namespace garlic if (m_State == eSessionStateNewSessionSent) { m_State = eSessionStateEstablished; + m_EphemeralKeys = nullptr; m_SessionCreatedTimestamp = i2p::util::GetSecondsSinceEpoch (); GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ()); } @@ -643,6 +671,7 @@ namespace garlic case eSessionStateNewSessionReplySent: m_State = eSessionStateEstablished; m_NSRSendTagset = nullptr; + m_EphemeralKeys = nullptr; #if (__cplusplus >= 201703L) // C++ 17 or higher [[fallthrough]]; #endif @@ -813,7 +842,7 @@ namespace garlic htobe16buf (v.data () + offset, keyID); offset += 2; // keyid if (m_NextReceiveRatchet->newKey) { - memcpy (v.data () + offset, m_NextReceiveRatchet->key.GetPublicKey (), 32); + memcpy (v.data () + offset, m_NextReceiveRatchet->key->GetPublicKey (), 32); offset += 32; // public key } m_SendReverseKey = false; @@ -828,7 +857,7 @@ namespace garlic htobe16buf (v.data () + offset, m_NextSendRatchet->keyID); offset += 2; // keyid if (m_NextSendRatchet->newKey) { - memcpy (v.data () + offset, m_NextSendRatchet->key.GetPublicKey (), 32); + memcpy (v.data () + offset, m_NextSendRatchet->key->GetPublicKey (), 32); offset += 32; // public key } } diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index 727c48ac..2dccd865 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -122,7 +122,7 @@ namespace garlic struct DHRatchet { int keyID = 0; - i2p::crypto::X25519Keys key; + std::shared_ptr key; uint8_t remote[32]; // last remote public key bool newKey = true; }; @@ -180,7 +180,7 @@ namespace garlic uint8_t m_H[32], m_CK[64] /* [chainkey, key] */, m_RemoteStaticKey[32]; uint8_t m_Aepk[32]; // Alice's ephemeral keys, for incoming only uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only - i2p::crypto::X25519Keys m_EphemeralKeys; + std::shared_ptr m_EphemeralKeys; SessionState m_State = eSessionStateNew; uint64_t m_SessionCreatedTimestamp = 0, m_LastActivityTimestamp = 0; // incoming std::shared_ptr m_SendTagset, m_NSRSendTagset; From 6f2e6ed8873d68f8bdd9e626ed7ac5912beeffd0 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 30 Jun 2020 15:05:17 -0400 Subject: [PATCH 32/49] key for next send ratchet --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 8e0e743d..d403c9bd 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -391,7 +391,7 @@ namespace garlic else m_NextSendRatchet.reset (new DHRatchet ()); if (m_NextSendRatchet->newKey) - m_NextSendRatchet->key->GenerateKeys (); + m_NextSendRatchet->key = i2p::transport::transports.GetNextX25519KeysPair (); m_SendForwardKey = true; LogPrint (eLogDebug, "Garlic: new send ratchet ", m_NextSendRatchet->newKey ? "new" : "old", " key ", m_NextSendRatchet->keyID, " created"); From 6f17624742b4af654b1c4c604172beb7b2c48787 Mon Sep 17 00:00:00 2001 From: user Date: Sun, 5 Jul 2020 12:53:15 +0800 Subject: [PATCH 33/49] Android.mk : openssl-1.1.1d-clang instead of openssl-1.1.1a-clang --- android/jni/Android.mk | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 2376509e..07dc7080 100755 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -53,15 +53,15 @@ include $(PREBUILT_STATIC_LIBRARY) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := crypto -LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/$(TARGET_ARCH_ABI)/lib/libcrypto.a -LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/include +LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1d-clang/$(TARGET_ARCH_ABI)/lib/libcrypto.a +LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1d-clang/include include $(PREBUILT_STATIC_LIBRARY) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := ssl -LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/$(TARGET_ARCH_ABI)/lib/libssl.a -LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/include +LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1d-clang/$(TARGET_ARCH_ABI)/lib/libssl.a +LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1d-clang/include LOCAL_STATIC_LIBRARIES := crypto include $(PREBUILT_STATIC_LIBRARY) From e15b2cc5d6531037850b855b36b025ad371b962b Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 15 Jun 2020 09:01:17 +0300 Subject: [PATCH 34/49] [webconsole] rework lists with tunnels, transit, etc Signed-off-by: R4SAS --- daemon/HTTPServer.cpp | 166 ++++++++++++++++++++++++------------------ 1 file changed, 95 insertions(+), 71 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 41f198c8..c387a402 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -67,35 +67,36 @@ namespace http { " color: initial; padding: 0 5px; border: 1px solid #894C84; }\r\n" " .header { font-size: 2.5em; text-align: center; margin: 1em 0; color: #894C84; }\r\n" " .wrapper { margin: 0 auto; padding: 1em; max-width: 58em; }\r\n" - " .menu { float: left; } .menu a { display: block; padding: 2px; }\r\n" + " .menu { float: left; } .menu a, .commands a { display: block; }\r\n" + " .listitem { display: block; font-family: monospace; font-size: 1.2em; white-space: nowrap; }\r\n" " .content { float: left; font-size: 1em; margin-left: 4em; max-width: 46em; overflow: auto; }\r\n" - " .tunnel.established { color: #56B734; }\r\n" - " .tunnel.expiring { color: #D3AE3F; }\r\n" - " .tunnel.failed { color: #D33F3F; }\r\n" - " .tunnel.building { color: #434343; }\r\n" + " .tunnel.established { color: #56B734; } .tunnel.expiring { color: #D3AE3F; }\r\n" + " .tunnel.failed { color: #D33F3F; } .tunnel.building { color: #434343; }\r\n" " caption { font-size: 1.5em; text-align: center; color: #894C84; }\r\n" " table { display: table; border-collapse: collapse; text-align: center; }\r\n" " table.extaddr { text-align: left; } table.services { width: 100%; }\r\n" + " textarea { word-break: break-all; }\r\n" " .streamdest { width: 120px; max-width: 240px; overflow: hidden; text-overflow: ellipsis;}\r\n" " .slide div.slidecontent, .slide [type=\"checkbox\"] { display: none; }\r\n" " .slide [type=\"checkbox\"]:checked ~ div.slidecontent { display: block; margin-top: 0; padding: 0; }\r\n" " .disabled:after { color: #D33F3F; content: \"Disabled\" }\r\n" " .enabled:after { color: #56B734; content: \"Enabled\" }\r\n" " @media screen and (max-width: 980px) {\r\n" /* adaptive style */ - " .menu { width: 100%; display: block; float: none; position: unset; font-size: 24px;\r\n" + " .menu { width: 100%; display: block; float: none; position: unset; font-size: 16px;\r\n" + " text-align: center; }\r\n" + " .menu a, .commands a { padding: 2px; }\r\n" + " .content { float: none; margin: 0; margin-top: 16px; max-width: 100%; width: 100%;\r\n" " text-align: center; }\r\n" - " .content { float: none; margin: 0; margin-top: 16px; max-width: 100%; width: 100%; font-size: 1.2em;\r\n" - " text-align: center; line-height: 28px; }\r\n" " a, .slide label { /* margin-right: 10px; */ display: block; /* font-size: 18px; */ }\r\n" - " .header { margin: 0.5em 0; } small {display: block}\r\n" + " .header { margin: unset; font-size: 1.5em; } small {display: block}\r\n" " a.button { -webkit-appearance: button; -moz-appearance: button; appearance: button; text-decoration: none;\r\n" " color: initial; margin-top: 10px; padding: 6px; border: 1px solid #894c84; width: -webkit-fill-available; }\r\n" - " input { width: 35%; height: 50px; text-align: center; /* margin-top: 15px; */ padding: 5px;\r\n" - " border: 2px solid #ccc; -webkit-border-radius: 5px; border-radius: 5px; font-size: 35px; }\r\n" + " input { width: 35%; text-align: center; padding: 5px;\r\n" + " border: 2px solid #ccc; -webkit-border-radius: 5px; border-radius: 5px; font-size: 24px; }\r\n" " textarea { width: -webkit-fill-available; height: auto; padding:5px; border:2px solid #ccc;\r\n" - " -webkit-border-radius: 5px; border-radius: 5px; font-size: 22px; }\r\n" + " -webkit-border-radius: 5px; border-radius: 5px; font-size: 12px; }\r\n" " button[type=submit] { padding: 5px 15px; background: #ccc; border: 0 none; cursor: pointer;\r\n" - " -webkit-border-radius: 5px; border-radius: 5px; position: relative; height: 50px; display: -webkit-inline-box; margin-top: 25px; }\r\n" + " -webkit-border-radius: 5px; border-radius: 5px; position: relative; height: 36px; display: -webkit-inline-box; margin-top: 10px; }\r\n" " }\r\n" /* adaptive style */ "\r\n"; @@ -228,7 +229,7 @@ namespace http { static void ShowPageTail (std::stringstream& s) { s << - "
\r\n" + "
\r\n
\r\n" "\r\n" "\r\n"; } @@ -358,18 +359,19 @@ namespace http { void ShowLocalDestinations (std::stringstream& s) { std::string webroot; i2p::config::GetOption("http.webroot", webroot); - s << "Local Destinations:
\r\n
\r\n"; + s << "Local Destinations:
\r\n
\r\n"; for (auto& it: i2p::client::context.GetDestinations ()) { auto ident = it.second->GetIdentHash (); - s << ""; - s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "
\r\n" << std::endl; + s << "\r\n" << std::endl; } + s << "
\r\n"; auto i2cpServer = i2p::client::context.GetI2CPServer (); if (i2cpServer && !(i2cpServer->GetSessions ().empty ())) { - s << "
I2CP Local Destinations:
\r\n
\r\n"; + s << "
I2CP Local Destinations:
\r\n
\r\n"; for (auto& it: i2cpServer->GetSessions ()) { auto dest = it.second->GetDestination (); @@ -377,10 +379,11 @@ namespace http { { auto ident = dest->GetIdentHash (); auto& name = dest->GetNickname (); - s << "[ "; - s << name << " ] ⇔ " << i2p::client::context.GetAddressBook ().ToAddress(ident) <<"
\r\n" << std::endl; + s << "
[ "; + s << name << " ] ⇔ " << i2p::client::context.GetAddressBook ().ToAddress(ident) <<"
\r\n" << std::endl; } } + s << "
\r\n"; } } @@ -581,54 +584,59 @@ namespace http { void ShowTunnels (std::stringstream& s) { - s << "Tunnels:
\r\n
\r\n"; - s << "Queue size: " << i2p::tunnel::tunnels.GetQueueSize () << "
\r\n"; + s << "Tunnels:
\r\n"; + s << "Queue size: " << i2p::tunnel::tunnels.GetQueueSize () << "
\r\n
\r\n"; auto ExplPool = i2p::tunnel::tunnels.GetExploratoryPool (); - s << "Inbound tunnels:
\r\n"; + s << "Inbound tunnels:
\r\n
\r\n"; for (auto & it : i2p::tunnel::tunnels.GetInboundTunnels ()) { + s << "
"; it->Print(s); if(it->LatencyIsKnown()) s << " ( " << it->GetMeanLatency() << "ms )"; ShowTunnelDetails(s, it->GetState (), (it->GetTunnelPool () == ExplPool), it->GetNumReceivedBytes ()); + s << "
\r\n"; } - s << "
\r\n"; - s << "Outbound tunnels:
\r\n"; + s << "
\r\n
\r\n"; + s << "Outbound tunnels:
\r\n
\r\n"; for (auto & it : i2p::tunnel::tunnels.GetOutboundTunnels ()) { + s << "
"; it->Print(s); if(it->LatencyIsKnown()) s << " ( " << it->GetMeanLatency() << "ms )"; ShowTunnelDetails(s, it->GetState (), (it->GetTunnelPool () == ExplPool), it->GetNumSentBytes ()); + s << "
\r\n"; } - s << "
\r\n"; + s << "
\r\n"; } static void ShowCommands (std::stringstream& s, uint32_t token) { std::string webroot; i2p::config::GetOption("http.webroot", webroot); /* commands */ - s << "Router Commands
\r\n
\r\n"; - s << " Run peer test
\r\n"; + s << "Router Commands
\r\n
\r\n
\r\n"; + s << " Run peer test\r\n"; //s << " Reload config
\r\n"; if (i2p::context.AcceptsTunnels ()) - s << " Decline transit tunnels
\r\n"; + s << " Decline transit tunnels\r\n"; else - s << " Accept transit tunnels
\r\n"; + s << " Accept transit tunnels\r\n"; #if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY)) if (Daemon.gracefulShutdownInterval) - s << " Cancel graceful shutdown
"; + s << " Cancel graceful shutdown\r\n"; else s << " Start graceful shutdown
\r\n"; #elif defined(WIN32_APP) if (i2p::util::DaemonWin32::Instance().isGraceful) - s << " Cancel graceful shutdown
"; + s << " Cancel graceful shutdown\r\n"; else - s << " Graceful shutdown
\r\n"; + s << " Graceful shutdown\r\n"; #endif - s << " Force shutdown
\r\n
\r\n"; + s << " Force shutdown\r\n"; + s << "
"; - s << "Note: any action done here are not persistent and not changes your config files.\r\n
\r\n"; + s << "
\r\nNote: any action done here are not persistent and not changes your config files.\r\n
\r\n"; s << "Logging level
\r\n"; s << " none \r\n"; @@ -651,17 +659,19 @@ namespace http { { if(i2p::tunnel::tunnels.CountTransitTunnels()) { - s << "Transit tunnels:
\r\n
\r\n"; + s << "Transit tunnels:
\r\n
\r\n"; for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ()) { + s << "
\r\n"; if (std::dynamic_pointer_cast(it)) s << it->GetTunnelID () << " ⇒ "; else if (std::dynamic_pointer_cast(it)) s << " ⇒ " << it->GetTunnelID (); else s << " ⇒ " << it->GetTunnelID () << " ⇒ "; - s << " " << it->GetNumTransmittedBytes () << "
\r\n"; + s << " " << it->GetNumTransmittedBytes () << "
\r\n"; } + s << "
\r\n"; } else { @@ -677,43 +687,44 @@ namespace http { { if (it.second && it.second->IsEstablished () && !it.second->GetSocket ().remote_endpoint ().address ().is_v6 ()) { - // incoming connection doesn't have remote RI + tmp_s << "
\r\n"; if (it.second->IsOutgoing ()) tmp_s << " ⇒ "; tmp_s << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": " << it.second->GetSocket ().remote_endpoint().address ().to_string (); if (!it.second->IsOutgoing ()) tmp_s << " ⇒ "; tmp_s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; - tmp_s << "
\r\n" << std::endl; + tmp_s << "
\r\n" << std::endl; cnt++; } if (it.second && it.second->IsEstablished () && it.second->GetSocket ().remote_endpoint ().address ().is_v6 ()) { + tmp_s6 << "
\r\n"; if (it.second->IsOutgoing ()) tmp_s6 << " ⇒ "; tmp_s6 << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": " << "[" << it.second->GetSocket ().remote_endpoint().address ().to_string () << "]"; if (!it.second->IsOutgoing ()) tmp_s6 << " ⇒ "; tmp_s6 << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; - tmp_s6 << "
\r\n" << std::endl; + tmp_s6 << "
\r\n" << std::endl; cnt6++; } } if (!tmp_s.str ().empty ()) { s << "
\r\n\r\n
" + << " ( " << cnt << " )\r\n\r\n
" << tmp_s.str () << "
\r\n
\r\n"; } if (!tmp_s6.str ().empty ()) { s << "
\r\n\r\n
" + << "v6 ( " << cnt6 << " )\r\n\r\n
" << tmp_s6.str () << "
\r\n
\r\n"; } } void ShowTransports (std::stringstream& s) { - s << "Transports:
\r\n
\r\n"; + s << "Transports:
\r\n"; auto ntcpServer = i2p::transport::transports.GetNTCPServer (); if (ntcpServer) { @@ -734,9 +745,10 @@ namespace http { auto sessions = ssuServer->GetSessions (); if (!sessions.empty ()) { - s << "
\r\n\r\n
"; + s << "
\r\n\r\n
"; for (const auto& it: sessions) { + s << "
\r\n"; auto endpoint = it.second->GetRemoteEndpoint (); if (it.second->IsOutgoing ()) s << " ⇒ "; s << endpoint.address ().to_string () << ":" << endpoint.port (); @@ -744,16 +756,17 @@ namespace http { s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; if (it.second->GetRelayTag ()) s << " [itag:" << it.second->GetRelayTag () << "]"; - s << "
\r\n" << std::endl; + s << "
\r\n" << std::endl; } s << "
\r\n
\r\n"; } auto sessions6 = ssuServer->GetSessionsV6 (); if (!sessions6.empty ()) { - s << "
\r\n\r\n
"; + s << "
\r\n\r\n
"; for (const auto& it: sessions6) { + s << "
\r\n"; auto endpoint = it.second->GetRemoteEndpoint (); if (it.second->IsOutgoing ()) s << " ⇒ "; s << "[" << endpoint.address ().to_string () << "]:" << endpoint.port (); @@ -761,7 +774,7 @@ namespace http { s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; if (it.second->GetRelayTag ()) s << " [itag:" << it.second->GetRelayTag () << "]"; - s << "
\r\n" << std::endl; + s << "
\r\n" << std::endl; } s << "
\r\n
\r\n"; } @@ -780,13 +793,14 @@ namespace http { if(sam->GetSessions ().size ()) { - s << "SAM Sessions:
\r\n
\r\n"; + s << "SAM Sessions:
\r\n
\r\n"; for (auto& it: sam->GetSessions ()) { auto& name = it.second->localDestination->GetNickname (); - s << ""; - s << name << " (" << it.first << ")
\r\n" << std::endl; + s << "\r\n" << std::endl; } + s << "
\r\n"; } else s << "SAM Sessions: no sessions currently running.
\r\n"; @@ -794,25 +808,28 @@ namespace http { static void ShowSAMSession (std::stringstream& s, const std::string& id) { - std::string webroot; i2p::config::GetOption("http.webroot", webroot); - s << "SAM Session:
\r\n
\r\n"; auto sam = i2p::client::context.GetSAMBridge (); if (!sam) { ShowError(s, "SAM disabled"); return; } + auto session = sam->FindSession (id); if (!session) { ShowError(s, "SAM session not found"); return; } + + std::string webroot; i2p::config::GetOption("http.webroot", webroot); + s << "SAM Session:
\r\n
\r\n"; auto& ident = session->localDestination->GetIdentHash(); - s << ""; - s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "
\r\n"; + s << "\r\n"; s << "
\r\n"; - s << "Streams:
\r\n"; + s << "Streams:
\r\n
\r\n"; for (const auto& it: sam->ListSockets(id)) { + s << "
"; switch (it->GetSocketType ()) { case i2p::client::eSAMSocketTypeSession : s << "session"; break; @@ -821,78 +838,85 @@ namespace http { default: s << "unknown"; break; } s << " [" << it->GetSocket ().remote_endpoint() << "]"; - s << "
\r\n"; + s << "
\r\n"; } + s << "
\r\n"; } void ShowI2PTunnels (std::stringstream& s) { std::string webroot; i2p::config::GetOption("http.webroot", webroot); - s << "Client Tunnels:
\r\n
\r\n"; + s << "Client Tunnels:
\r\n
\r\n"; for (auto& it: i2p::client::context.GetClientTunnels ()) { auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); - s << ""; + s << "
"; s << it.second->GetName () << " ⇐ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); - s << "
\r\n"<< std::endl; + s << "
\r\n"<< std::endl; } auto httpProxy = i2p::client::context.GetHttpProxy (); if (httpProxy) { auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash(); - s << ""; + s << "
"; s << "HTTP Proxy" << " ⇐ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); - s << "
\r\n"<< std::endl; + s << "
\r\n"<< std::endl; } auto socksProxy = i2p::client::context.GetSocksProxy (); if (socksProxy) { auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash(); - s << ""; + s << "
"; s << "SOCKS Proxy" << " ⇐ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); - s << "
\r\n"<< std::endl; + s << "
\r\n"<< std::endl; } + s << "
\r\n"; + auto& serverTunnels = i2p::client::context.GetServerTunnels (); if (!serverTunnels.empty ()) { - s << "
\r\nServer Tunnels:
\r\n
\r\n"; + s << "
\r\nServer Tunnels:
\r\n
\r\n"; for (auto& it: serverTunnels) { auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); - s << ""; + s << "
"; s << it.second->GetName () << " ⇒ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << ":" << it.second->GetLocalPort (); - s << "
\r\n"<< std::endl; + s << "
\r\n"<< std::endl; } + s << "
\r\n"; } + auto& clientForwards = i2p::client::context.GetClientForwards (); if (!clientForwards.empty ()) { - s << "
\r\nClient Forwards:
\r\n
\r\n"; + s << "
\r\nClient Forwards:
\r\n
\r\n"; for (auto& it: clientForwards) { auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); - s << ""; + s << "
"; s << it.second->GetName () << " ⇐ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); - s << "
\r\n"<< std::endl; + s << "
\r\n"<< std::endl; } + s << "
\r\n"; } auto& serverForwards = i2p::client::context.GetServerForwards (); if (!serverForwards.empty ()) { - s << "
\r\nServer Forwards:
\r\n
\r\n"; + s << "
\r\nServer Forwards:
\r\n
\r\n"; for (auto& it: serverForwards) { auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); s << ""; s << it.second->GetName () << " ⇐ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); - s << "
\r\n"<< std::endl; + s << "
\r\n"<< std::endl; } + s << "
\r\n"; } } From 2d65402cedf9d788609b47bbeac7faaab88c8591 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 15 Jun 2020 13:05:01 +0300 Subject: [PATCH 35/49] [webconsole] update styles Signed-off-by: R4SAS --- daemon/HTTPServer.cpp | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index c387a402..416cf1e4 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -69,6 +69,7 @@ namespace http { " .wrapper { margin: 0 auto; padding: 1em; max-width: 58em; }\r\n" " .menu { float: left; } .menu a, .commands a { display: block; }\r\n" " .listitem { display: block; font-family: monospace; font-size: 1.2em; white-space: nowrap; }\r\n" + " .tableitem { font-family: monospace; font-size: 1.2em; white-space: nowrap; }\r\n" " .content { float: left; font-size: 1em; margin-left: 4em; max-width: 46em; overflow: auto; }\r\n" " .tunnel.established { color: #56B734; } .tunnel.expiring { color: #D3AE3F; }\r\n" " .tunnel.failed { color: #D33F3F; } .tunnel.building { color: #434343; }\r\n" @@ -172,7 +173,7 @@ namespace http { default: state = "unknown"; break; } s << " " << state << ((explr) ? " (exploratory)" : "") << ", "; - s << " " << (int) (bytes / 1024) << " KiB
\r\n"; + s << " " << (int) (bytes / 1024) << " KiB\r\n"; } static void SetLogLevel (const std::string& level) @@ -389,7 +390,7 @@ namespace http { static void ShowLeaseSetDestination (std::stringstream& s, std::shared_ptr dest) { - s << "Base64:
\r\n
\r\n
\r\n"; if (dest->IsEncryptedLeaseSet ()) { @@ -402,29 +403,34 @@ namespace http { if(dest->GetNumRemoteLeaseSets()) { s << "
\r\n\r\n
\r\n"; + << "\r\n\r\n
\r\n
AddressTypeEncType
"; for(auto& it: dest->GetLeaseSets ()) s << "\r\n"; s << "
AddressTypeEncType
" << it.first.ToBase32 () << "" << (int)it.second->GetStoreType () << "" << (int)it.second->GetEncryptionType () <<"
\r\n
\r\n
\r\n
\r\n"; } else s << "LeaseSets: 0
\r\n
\r\n"; + auto pool = dest->GetTunnelPool (); if (pool) { - s << "Inbound tunnels:
\r\n"; + s << "Inbound tunnels:
\r\n
\r\n"; for (auto & it : pool->GetInboundTunnels ()) { + s << "
"; it->Print(s); if(it->LatencyIsKnown()) s << " ( " << it->GetMeanLatency() << "ms )"; ShowTunnelDetails(s, it->GetState (), false, it->GetNumReceivedBytes ()); + s << "
\r\n"; } s << "
\r\n"; - s << "Outbound tunnels:
\r\n"; + s << "Outbound tunnels:
\r\n
\r\n"; for (auto & it : pool->GetOutboundTunnels ()) { + s << "
"; it->Print(s); if(it->LatencyIsKnown()) s << " ( " << it->GetMeanLatency() << "ms )"; ShowTunnelDetails(s, it->GetState (), false, it->GetNumSentBytes ()); + s << "
\r\n"; } } s << "
\r\n"; @@ -437,7 +443,7 @@ namespace http { out_tags += it.second->GetNumOutgoingTags (); } s << "
\r\n\r\n" - << "
\r\n\r\n\r\n\r\n" << tmp_s.str () << "
DestinationAmount
\r\n
\r\n
\r\n"; + << "
\r\n\r\n\r\n\r\n" << tmp_s.str () << "
DestinationAmount
\r\n
\r\n
\r\n"; } else s << "Outgoing: 0
\r\n"; s << "
\r\n"; @@ -453,7 +459,7 @@ namespace http { ecies_sessions++; } s << "
\r\n\r\n" - << "
\r\n\r\n\r\n\r\n" << tmp_s.str () << "
DestinationStatus
\r\n
\r\n
\r\n"; + << "
\r\n\r\n\r\n\r\n" << tmp_s.str () << "
DestinationStatus
\r\n
\r\n
\r\n"; } else s << "Tags sessions: 0
\r\n"; s << "
\r\n"; @@ -483,11 +489,12 @@ namespace http { s << "RTT"; s << "Window"; s << "Status"; - s << "\r\n\r\n\r\n"; + s << "\r\n\r\n\r\n"; for (const auto& it: dest->GetAllStreams ()) { auto streamDest = i2p::client::context.GetAddressBook ().ToAddress(it->GetRemoteIdentity ()); + std::string streamDestShort = streamDest.substr(0,12) + "….b32.i2p"; s << ""; s << "" << it->GetRecvStreamID () << ""; if (it->GetRecvStreamID ()) { @@ -496,7 +503,7 @@ namespace http { } else { s << ""; } - s << "" << streamDest << ""; + s << "" << streamDestShort << ""; s << "" << it->GetNumSentBytes () << ""; s << "" << it->GetNumReceivedBytes () << ""; s << "" << it->GetSendQueueSize () << ""; @@ -531,7 +538,7 @@ namespace http { { if (i2p::data::netdb.GetNumLeaseSets ()) { - s << "LeaseSets:
\r\n
\r\n"; + s << "LeaseSets:
\r\n
\r\n"; int counter = 1; // for each lease set i2p::data::netdb.VisitLeaseSets( @@ -545,13 +552,13 @@ namespace http { else ls.reset (new i2p::data::LeaseSet2 (storeType, leaseSet->GetBuffer(), leaseSet->GetBufferLen())); if (!ls) return; - s << "
\r\n"; + s << "\">\r\n"; if (!ls->IsValid()) - s << "
!! Invalid !!
\r\n"; - s << "
\r\n"; + s << "
!! Invalid !!
\r\n"; + s << "
\r\n"; s << "\r\n
\r\n"; s << "Store type: " << (int)storeType << "
\r\n"; s << "Expires: " << ConvertTime(ls->GetExpirationTime()) << "
\r\n"; @@ -922,7 +929,7 @@ namespace http { std::string ConvertTime (uint64_t time) { - ldiv_t divTime = ldiv(time,1000); + lldiv_t divTime = lldiv(time, 1000); time_t t = divTime.quot; struct tm *tm = localtime(&t); char date[128]; From 4e4c11702371bbbcc9ee87a02448bb36f8815fb4 Mon Sep 17 00:00:00 2001 From: potatowipedlifereverse Date: Tue, 7 Jul 2020 02:01:56 +0300 Subject: [PATCH 36/49] whitelist synonim for accesslist --- libi2pd_client/ClientContext.cpp | 2 ++ libi2pd_client/ClientContext.h | 1 + 2 files changed, 3 insertions(+) diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 0348aeeb..e8e8eb2d 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -663,6 +663,8 @@ namespace client // optional params int inPort = section.second.get (I2P_SERVER_TUNNEL_INPORT, 0); std::string accessList = section.second.get (I2P_SERVER_TUNNEL_ACCESS_LIST, ""); + if(accessList == "") + accessList=section.second.get (I2P_SERVER_TUNNEL_WHITE_LIST, ""); std::string hostOverride = section.second.get (I2P_SERVER_TUNNEL_HOST_OVERRIDE, ""); std::string webircpass = section.second.get (I2P_SERVER_TUNNEL_WEBIRC_PASSWORD, ""); bool gzip = section.second.get (I2P_SERVER_TUNNEL_GZIP, true); diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index 8a4835c8..05b754fe 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -54,6 +54,7 @@ namespace client const char I2P_SERVER_TUNNEL_SIGNATURE_TYPE[] = "signaturetype"; const char I2P_SERVER_TUNNEL_INPORT[] = "inport"; const char I2P_SERVER_TUNNEL_ACCESS_LIST[] = "accesslist"; + const char I2P_SERVER_TUNNEL_WHITE_LIST[] = "whitelist"; const char I2P_SERVER_TUNNEL_GZIP[] = "gzip"; const char I2P_SERVER_TUNNEL_WEBIRC_PASSWORD[] = "webircpassword"; const char I2P_SERVER_TUNNEL_ADDRESS[] = "address"; From 67b94d3533f8e0f0eca2443344c012d06acc5ab5 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 7 Jul 2020 15:38:20 -0400 Subject: [PATCH 37/49] unordered_map for RouterInfos and LeaseSets --- libi2pd/NetDb.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 1c65969a..d4501ab9 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -11,7 +11,7 @@ // this file is called NetDb.hpp to resolve conflict with libc's netdb.h on case insensitive fs #include #include -#include +#include #include #include #include @@ -138,9 +138,9 @@ namespace data private: mutable std::mutex m_LeaseSetsMutex; - std::map > m_LeaseSets; + std::unordered_map > m_LeaseSets; mutable std::mutex m_RouterInfosMutex; - std::map > m_RouterInfos; + std::unordered_map > m_RouterInfos; mutable std::mutex m_FloodfillsMutex; std::list > m_Floodfills; From c41554109b76ad3ff4e9b621c86e0f91a533dc54 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 15 Jul 2020 16:20:35 -0400 Subject: [PATCH 38/49] change datagram routing path if nothing comes back in 10 seconds --- libi2pd/Datagram.cpp | 7 ++ libi2pd/ECIESX25519AEADRatchetSession.cpp | 140 +++++++++++----------- libi2pd/ECIESX25519AEADRatchetSession.h | 7 +- libi2pd/Garlic.h | 1 + 4 files changed, 85 insertions(+), 70 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index b9938043..559b0a8b 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -315,6 +315,13 @@ namespace datagram } auto path = m_RoutingSession->GetSharedRoutingPath(); + if (path && m_RoutingSession->IsRatchets () && + m_LastUse > m_RoutingSession->GetLastActivityTimestamp ()*1000 + DATAGRAM_SESSION_PATH_TIMEOUT) + { + m_RoutingSession->SetSharedRoutingPath (nullptr); + path = nullptr; + } + if (path) { if (path->outboundTunnel && !path->outboundTunnel->IsEstablished ()) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index d403c9bd..dac5dbe0 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -770,7 +770,7 @@ namespace garlic if (m_NextSendRatchet->newKey) payloadLen += 32; } uint8_t paddingSize = 0; - if (payloadLen) + if (payloadLen || ts > m_LastSentTimestamp + ECIESX25519_SEND_INACTIVITY_TIMEOUT) { int delta = (int)ECIESX25519_OPTIMAL_PAYLOAD_SIZE - (int)payloadLen; if (delta < 0 || delta > 3) // don't create padding if we are close to optimal size @@ -791,83 +791,87 @@ namespace garlic } } std::vector v(payloadLen); - size_t offset = 0; - // DateTime - if (first) - { - v[offset] = eECIESx25519BlkDateTime; offset++; - htobe16buf (v.data () + offset, 4); offset += 2; - htobe32buf (v.data () + offset, ts/1000); offset += 4; // in seconds - } - // LeaseSet - if (leaseSet) - { - offset += CreateLeaseSetClove (leaseSet, ts, v.data () + offset, payloadLen - offset); - if (!first) + if (payloadLen) + { + m_LastSentTimestamp = ts; + size_t offset = 0; + // DateTime + if (first) { - // ack request - v[offset] = eECIESx25519BlkAckRequest; offset++; - htobe16buf (v.data () + offset, 1); offset += 2; - v[offset] = 0; offset++; // flags + v[offset] = eECIESx25519BlkDateTime; offset++; + htobe16buf (v.data () + offset, 4); offset += 2; + htobe32buf (v.data () + offset, ts/1000); offset += 4; // in seconds } - } - // msg - if (msg && m_Destination) - offset += CreateGarlicClove (msg, v.data () + offset, payloadLen - offset, true); - // ack - if (m_AckRequests.size () > 0) - { - v[offset] = eECIESx25519BlkAck; offset++; - htobe16buf (v.data () + offset, m_AckRequests.size () * 4); offset += 2; - for (auto& it: m_AckRequests) + // LeaseSet + if (leaseSet) { - htobe16buf (v.data () + offset, it.first); offset += 2; - htobe16buf (v.data () + offset, it.second); offset += 2; + offset += CreateLeaseSetClove (leaseSet, ts, v.data () + offset, payloadLen - offset); + if (!first) + { + // ack request + v[offset] = eECIESx25519BlkAckRequest; offset++; + htobe16buf (v.data () + offset, 1); offset += 2; + v[offset] = 0; offset++; // flags + } } - m_AckRequests.clear (); - } - // next keys - if (m_SendReverseKey) - { - v[offset] = eECIESx25519BlkNextKey; offset++; - htobe16buf (v.data () + offset, m_NextReceiveRatchet->newKey ? 35 : 3); offset += 2; - v[offset] = ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG; - int keyID = m_NextReceiveRatchet->keyID - 1; - if (m_NextReceiveRatchet->newKey) + // msg + if (msg && m_Destination) + offset += CreateGarlicClove (msg, v.data () + offset, payloadLen - offset, true); + // ack + if (m_AckRequests.size () > 0) { - v[offset] |= ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG; - keyID++; + v[offset] = eECIESx25519BlkAck; offset++; + htobe16buf (v.data () + offset, m_AckRequests.size () * 4); offset += 2; + for (auto& it: m_AckRequests) + { + htobe16buf (v.data () + offset, it.first); offset += 2; + htobe16buf (v.data () + offset, it.second); offset += 2; + } + m_AckRequests.clear (); } - offset++; // flag - htobe16buf (v.data () + offset, keyID); offset += 2; // keyid - if (m_NextReceiveRatchet->newKey) + // next keys + if (m_SendReverseKey) { - memcpy (v.data () + offset, m_NextReceiveRatchet->key->GetPublicKey (), 32); - offset += 32; // public key + v[offset] = eECIESx25519BlkNextKey; offset++; + htobe16buf (v.data () + offset, m_NextReceiveRatchet->newKey ? 35 : 3); offset += 2; + v[offset] = ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG; + int keyID = m_NextReceiveRatchet->keyID - 1; + if (m_NextReceiveRatchet->newKey) + { + v[offset] |= ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG; + keyID++; + } + offset++; // flag + htobe16buf (v.data () + offset, keyID); offset += 2; // keyid + if (m_NextReceiveRatchet->newKey) + { + memcpy (v.data () + offset, m_NextReceiveRatchet->key->GetPublicKey (), 32); + offset += 32; // public key + } + m_SendReverseKey = false; } - m_SendReverseKey = false; - } - if (m_SendForwardKey) - { - v[offset] = eECIESx25519BlkNextKey; offset++; - htobe16buf (v.data () + offset, m_NextSendRatchet->newKey ? 35 : 3); offset += 2; - v[offset] = m_NextSendRatchet->newKey ? ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG : ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG; - if (!m_NextSendRatchet->keyID) v[offset] |= ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG; // for first key only - offset++; // flag - htobe16buf (v.data () + offset, m_NextSendRatchet->keyID); offset += 2; // keyid - if (m_NextSendRatchet->newKey) + if (m_SendForwardKey) { - memcpy (v.data () + offset, m_NextSendRatchet->key->GetPublicKey (), 32); - offset += 32; // public key + v[offset] = eECIESx25519BlkNextKey; offset++; + htobe16buf (v.data () + offset, m_NextSendRatchet->newKey ? 35 : 3); offset += 2; + v[offset] = m_NextSendRatchet->newKey ? ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG : ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG; + if (!m_NextSendRatchet->keyID) v[offset] |= ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG; // for first key only + offset++; // flag + htobe16buf (v.data () + offset, m_NextSendRatchet->keyID); offset += 2; // keyid + if (m_NextSendRatchet->newKey) + { + memcpy (v.data () + offset, m_NextSendRatchet->key->GetPublicKey (), 32); + offset += 32; // public key + } } - } - // padding - if (paddingSize) - { - v[offset] = eECIESx25519BlkPadding; offset++; - htobe16buf (v.data () + offset, paddingSize); offset += 2; - memset (v.data () + offset, 0, paddingSize); offset += paddingSize; - } + // padding + if (paddingSize) + { + v[offset] = eECIESx25519BlkPadding; offset++; + htobe16buf (v.data () + offset, paddingSize); offset += 2; + memset (v.data () + offset, 0, paddingSize); offset += paddingSize; + } + } return v; } diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index 2dccd865..cccb4092 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -27,7 +27,8 @@ namespace garlic { const int ECIESX25519_RESTART_TIMEOUT = 120; // number of second since session creation we can restart session after const int ECIESX25519_EXPIRATION_TIMEOUT = 480; // in seconds - const int ECIESX25519_INACTIVITY_TIMEOUT = 90; // number of second we receive nothing and should restart if we can + const int ECIESX25519_INACTIVITY_TIMEOUT = 90; // number of seconds we receive nothing and should restart if we can + const int ECIESX25519_SEND_INACTIVITY_TIMEOUT = 5000; // number of milliseconds we can send empty(pyaload only) packet after const int ECIESX25519_INCOMING_TAGS_EXPIRATION_TIMEOUT = 600; // in seconds const int ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT = 180; // 180 const int ECIESX25519_TAGSET_MAX_NUM_TAGS = 4096; // number of tags we request new tagset after @@ -148,6 +149,7 @@ namespace garlic bool IsInactive (uint64_t ts) const { return ts > m_LastActivityTimestamp + ECIESX25519_INACTIVITY_TIMEOUT && CanBeRestarted (ts); } bool IsRatchets () const { return true; }; + uint64_t GetLastActivityTimestamp () const { return m_LastActivityTimestamp; }; private: @@ -182,7 +184,8 @@ namespace garlic uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only std::shared_ptr m_EphemeralKeys; SessionState m_State = eSessionStateNew; - uint64_t m_SessionCreatedTimestamp = 0, m_LastActivityTimestamp = 0; // incoming + uint64_t m_SessionCreatedTimestamp = 0, m_LastActivityTimestamp = 0, // incoming + m_LastSentTimestamp = 0; // in milliseconds std::shared_ptr m_SendTagset, m_NSRSendTagset; std::unique_ptr m_Destination;// TODO: might not need it std::list > m_AckRequests; // (tagsetid, index) diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index 70893bec..2168ee81 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -114,6 +114,7 @@ namespace garlic virtual bool CleanupUnconfirmedTags () { return false; }; // for I2CP, override in ElGamalAESSession virtual bool MessageConfirmed (uint32_t msgID); virtual bool IsRatchets () const { return false; }; + virtual uint64_t GetLastActivityTimestamp () const { return 0; }; // non-zero for rathets only void SetLeaseSetUpdated () { From 3ef8b3dcbb55a3b1714eb46f3cd86bec2d53000a Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 24 Jul 2020 20:44:01 -0400 Subject: [PATCH 39/49] don't send repliable datagram after less then 100 milliseconds --- libi2pd_client/I2PTunnel.cpp | 16 ++++++++++++---- libi2pd_client/I2PTunnel.h | 3 ++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 95f56873..3575e062 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -708,9 +708,12 @@ namespace client if(!ecode) { LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint); - LastActivity = i2p::util::GetMillisecondsSinceEpoch(); + auto ts = i2p::util::GetMillisecondsSinceEpoch(); auto session = m_Destination->GetSession (Identity); - m_Destination->SendDatagram(session, m_Buffer, len, LocalPort, RemotePort); + if (ts > LastActivity + I2P_UDP_REPLIABLE_DATAGRAM_INTERVAL) + m_Destination->SendDatagram(session, m_Buffer, len, LocalPort, RemotePort); + else + m_Destination->SendRawDatagram(session, m_Buffer, len, LocalPort, RemotePort); size_t numPackets = 0; while (numPackets < i2p::datagram::DATAGRAM_SEND_QUEUE_MAX_SIZE) { @@ -724,6 +727,7 @@ namespace client if (numPackets > 0) LogPrint(eLogDebug, "UDPSession: forward more ", numPackets, "packets B from ", FromEndpoint); m_Destination->FlushSendQueue (session); + LastActivity = ts; Receive(); } else @@ -841,9 +845,13 @@ namespace client m_LastPort = remotePort; } // send off to remote i2p destination + auto ts = i2p::util::GetMillisecondsSinceEpoch(); LogPrint(eLogDebug, "UDP Client: send ", transferred, " to ", m_RemoteIdent->ToBase32(), ":", RemotePort); auto session = m_LocalDest->GetDatagramDestination()->GetSession (*m_RemoteIdent); - m_LocalDest->GetDatagramDestination()->SendDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort); + if (ts > m_LastSession->second + I2P_UDP_REPLIABLE_DATAGRAM_INTERVAL) + m_LocalDest->GetDatagramDestination()->SendDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort); + else + m_LocalDest->GetDatagramDestination()->SendRawDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort); size_t numPackets = 0; while (numPackets < i2p::datagram::DATAGRAM_SEND_QUEUE_MAX_SIZE) { @@ -862,7 +870,7 @@ namespace client // mark convo as active if (m_LastSession) - m_LastSession->second = i2p::util::GetMillisecondsSinceEpoch(); + m_LastSession->second = ts; RecvFromLocal(); } diff --git a/libi2pd_client/I2PTunnel.h b/libi2pd_client/I2PTunnel.h index eb1d8ed9..b76a1027 100644 --- a/libi2pd_client/I2PTunnel.h +++ b/libi2pd_client/I2PTunnel.h @@ -165,7 +165,8 @@ namespace client /** 2 minute timeout for udp sessions */ const uint64_t I2P_UDP_SESSION_TIMEOUT = 1000 * 60 * 2; - + const uint64_t I2P_UDP_REPLIABLE_DATAGRAM_INTERVAL = 100; // in milliseconds + /** max size for i2p udp */ const size_t I2P_UDP_MAX_MTU = 64*1024; From c3aa6b9cda922a4c76221c3383287ae60a20a038 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 29 Jul 2020 17:47:46 -0400 Subject: [PATCH 40/49] use delivery type local if destination is not secified --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 15 +++++++++------ libi2pd/ECIESX25519AEADRatchetSession.h | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index dac5dbe0..51ca9242 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -739,8 +739,11 @@ namespace garlic uint64_t ts = i2p::util::GetMillisecondsSinceEpoch (); size_t payloadLen = 0; if (first) payloadLen += 7;// datatime - if (msg && m_Destination) - payloadLen += msg->GetPayloadLength () + 13 + 32; + if (msg) + { + payloadLen += msg->GetPayloadLength () + 13; + if (m_Destination) payloadLen += 32; + } auto leaseSet = (GetLeaseSetUpdateStatus () == eLeaseSetUpdated || (GetLeaseSetUpdateStatus () == eLeaseSetSubmitted && ts > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT)) ? @@ -816,7 +819,7 @@ namespace garlic } // msg if (msg && m_Destination) - offset += CreateGarlicClove (msg, v.data () + offset, payloadLen - offset, true); + offset += CreateGarlicClove (msg, v.data () + offset, payloadLen - offset); // ack if (m_AckRequests.size () > 0) { @@ -875,16 +878,16 @@ namespace garlic return v; } - size_t ECIESX25519AEADRatchetSession::CreateGarlicClove (std::shared_ptr msg, uint8_t * buf, size_t len, bool isDestination) + size_t ECIESX25519AEADRatchetSession::CreateGarlicClove (std::shared_ptr msg, uint8_t * buf, size_t len) { if (!msg) return 0; uint16_t cloveSize = msg->GetPayloadLength () + 9 + 1; - if (isDestination) cloveSize += 32; + if (m_Destination) cloveSize += 32; if ((int)len < cloveSize + 3) return 0; buf[0] = eECIESx25519BlkGalicClove; // clove type htobe16buf (buf + 1, cloveSize); // size buf += 3; - if (isDestination) + if (m_Destination) { *buf = (eGarlicDeliveryTypeDestination << 5); memcpy (buf + 1, *m_Destination, 32); buf += 32; diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index cccb4092..73e129d7 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -171,7 +171,7 @@ namespace garlic bool NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen); std::vector CreatePayload (std::shared_ptr msg, bool first); - size_t CreateGarlicClove (std::shared_ptr msg, uint8_t * buf, size_t len, bool isDestination = false); + size_t CreateGarlicClove (std::shared_ptr msg, uint8_t * buf, size_t len); size_t CreateLeaseSetClove (std::shared_ptr ls, uint64_t ts, uint8_t * buf, size_t len); void GenerateMoreReceiveTags (std::shared_ptr receiveTagset, int numTags); From 9636d82b37ff021cd7ee7a7a0d55e89624e4a183 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 3 Aug 2020 18:31:03 -0400 Subject: [PATCH 41/49] MixHash for SessionConfirmed processing --- libi2pd/NTCP2.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index f1f7e59f..4e3b219c 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -338,11 +338,8 @@ namespace transport KDF3Bob (); if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer + 48, m3p2Len - 16, GetH (), 32, GetK (), nonce, m3p2Buf, m3p2Len - 16, false)) // decrypt - { // caclulate new h again for KDF data - memcpy (m_SessionConfirmedBuffer + 16, m_H, 32); // h || ciphertext - SHA256 (m_SessionConfirmedBuffer + 16, m3p2Len + 32, m_H); //h = SHA256(h || ciphertext); - } + MixHash (m_SessionConfirmedBuffer + 48, m3p2Len); // h = SHA256(h || ciphertext) else { LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part2 AEAD verification failed "); From 8e252265744cc8fdb942b90c2b27b8968d45698c Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 8 Aug 2020 13:34:27 -0400 Subject: [PATCH 42/49] use unordered_map for incomplete and sent messages --- libi2pd/SSUData.cpp | 2 +- libi2pd/SSUData.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libi2pd/SSUData.cpp b/libi2pd/SSUData.cpp index 5068f006..fde684d0 100644 --- a/libi2pd/SSUData.cpp +++ b/libi2pd/SSUData.cpp @@ -301,7 +301,7 @@ namespace transport void SSUData::Send (std::shared_ptr msg) { uint32_t msgID = msg->ToSSU (); - if (m_SentMessages.count (msgID) > 0) + if (m_SentMessages.find (msgID) != m_SentMessages.end()) { LogPrint (eLogWarning, "SSU: message ", msgID, " already sent"); return; diff --git a/libi2pd/SSUData.h b/libi2pd/SSUData.h index f4a5ba4f..2e606053 100644 --- a/libi2pd/SSUData.h +++ b/libi2pd/SSUData.h @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include #include @@ -124,8 +124,8 @@ namespace transport private: SSUSession& m_Session; - std::map > m_IncompleteMessages; - std::map > m_SentMessages; + std::unordered_map > m_IncompleteMessages; + std::unordered_map > m_SentMessages; std::unordered_set m_ReceivedMessages; boost::asio::deadline_timer m_ResendTimer, m_IncompleteMessagesCleanupTimer; int m_MaxPacketSize, m_PacketSize; From e50abbb250da622191cebcb2c9d9f989087bfd8b Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 8 Aug 2020 19:01:55 -0400 Subject: [PATCH 43/49] avoid replay upon SSU packet resend --- libi2pd/SSUData.cpp | 23 +++++++++++++++-------- libi2pd/SSUSession.cpp | 26 ++++++++++++++++---------- libi2pd/SSUSession.h | 1 + 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/libi2pd/SSUData.cpp b/libi2pd/SSUData.cpp index fde684d0..bd188ab7 100644 --- a/libi2pd/SSUData.cpp +++ b/libi2pd/SSUData.cpp @@ -326,8 +326,7 @@ namespace transport { Fragment * fragment = new Fragment; fragment->fragmentNum = fragmentNum; - uint8_t * buf = fragment->buf; - uint8_t * payload = buf + sizeof (SSUHeader); + uint8_t * payload = fragment->buf + sizeof (SSUHeader); *payload = DATA_FLAG_WANT_REPLY; // for compatibility payload++; *payload = 1; // always 1 message fragment per message @@ -346,14 +345,20 @@ namespace transport payload += 3; memcpy (payload, msgBuf, size); - size += payload - buf; - if (size & 0x0F) // make sure 16 bytes boundary - size = ((size >> 4) + 1) << 4; // (/16 + 1)*16 + size += payload - fragment->buf; + uint8_t rem = size & 0x0F; + if (rem) // make sure 16 bytes boundary + { + auto padding = 16 - rem; + memset (fragment->buf + size, 0, padding); + size += padding; + } fragment->len = size; fragments.push_back (std::unique_ptr (fragment)); // encrypt message with session key - m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, size); + uint8_t buf[SSU_V4_MAX_PACKET_SIZE + 18]; + m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, fragment->buf, size, buf); try { m_Session.Send (buf, size); @@ -432,6 +437,7 @@ namespace transport { if (ecode != boost::asio::error::operation_aborted) { + uint8_t buf[SSU_V4_MAX_PACKET_SIZE + 18]; uint32_t ts = i2p::util::GetSecondsSinceEpoch (); int numResent = 0; for (auto it = m_SentMessages.begin (); it != m_SentMessages.end ();) @@ -444,8 +450,9 @@ namespace transport if (f) { try - { - m_Session.Send (f->buf, f->len); // resend + { + m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, f->buf, f->len, buf); + m_Session.Send (buf, f->len); // resend numResent++; } catch (boost::system::system_error& ec) diff --git a/libi2pd/SSUSession.cpp b/libi2pd/SSUSession.cpp index 73699d6a..fca074b3 100644 --- a/libi2pd/SSUSession.cpp +++ b/libi2pd/SSUSession.cpp @@ -744,27 +744,33 @@ namespace transport } void SSUSession::FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len) + { + FillHeaderAndEncrypt (payloadType, buf, len, buf); + } + + void SSUSession::FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * in, size_t len, uint8_t * out) { if (len < sizeof (SSUHeader)) { LogPrint (eLogError, "SSU: Unexpected packet length ", len); return; } - SSUHeader * header = (SSUHeader *)buf; + SSUHeader * header = (SSUHeader *)out; RAND_bytes (header->iv, 16); // random iv m_SessionKeyEncryption.SetIV (header->iv); - header->flag = payloadType << 4; // MSB is 0 - htobe32buf (header->time, i2p::util::GetSecondsSinceEpoch ()); - uint8_t * encrypted = &header->flag; - uint16_t encryptedLen = len - (encrypted - buf); - m_SessionKeyEncryption.Encrypt (encrypted, encryptedLen, encrypted); - // assume actual buffer size is 18 (16 + 2) bytes more - memcpy (buf + len, header->iv, 16); + SSUHeader * inHeader = (SSUHeader *)in; + inHeader->flag = payloadType << 4; // MSB is 0 + htobe32buf (inHeader->time, i2p::util::GetSecondsSinceEpoch ()); + uint8_t * encrypted = &header->flag, * clear = &inHeader->flag; + uint16_t encryptedLen = len - (encrypted - out); + m_SessionKeyEncryption.Encrypt (clear, encryptedLen, encrypted); + // assume actual out buffer size is 18 (16 + 2) bytes more + memcpy (out + len, header->iv, 16); uint16_t netid = i2p::context.GetNetID (); - htobe16buf (buf + len + 16, (netid == I2PD_NET_ID) ? encryptedLen : encryptedLen ^ ((netid - 2) << 8)); + htobe16buf (out + len + 16, (netid == I2PD_NET_ID) ? encryptedLen : encryptedLen ^ ((netid - 2) << 8)); i2p::crypto::HMACMD5Digest (encrypted, encryptedLen + 18, m_MacKey, header->mac); } - + void SSUSession::Decrypt (uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey) { if (len < sizeof (SSUHeader)) diff --git a/libi2pd/SSUSession.h b/libi2pd/SSUSession.h index 066e01eb..ea820517 100644 --- a/libi2pd/SSUSession.h +++ b/libi2pd/SSUSession.h @@ -138,6 +138,7 @@ namespace transport void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey, const uint8_t * iv, const i2p::crypto::MACKey& macKey, uint8_t flag = 0); void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len); // with session key + void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * in, size_t len, uint8_t * out); // with session key void Decrypt (uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey); void DecryptSessionKey (uint8_t * buf, size_t len); bool Validate (uint8_t * buf, size_t len, const i2p::crypto::MACKey& macKey); From 6fec92c012b8fa067284f26355c427610f8624fb Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 10 Aug 2020 17:49:46 -0400 Subject: [PATCH 44/49] shared transient addresses --- libi2pd_client/ClientContext.cpp | 52 +++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index e8e8eb2d..fc48ddbb 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -253,7 +253,8 @@ namespace client bool ClientContext::LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, i2p::data::SigningKeyType sigType, i2p::data::CryptoKeyType cryptoType) { - if (filename == "transient") + static const std::string transient("transient"); + if (!filename.compare (0, transient.length (), transient)) // starts with transient { keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType, cryptoType); LogPrint (eLogInfo, "Clients: New transient keys address ", m_AddressBook.ToAddress(keys.GetPublic ()->GetIdentHash ()), " created"); @@ -533,6 +534,7 @@ namespace client return; } + std::map > destinations; // keys -> destination for (auto& section: pt) { std::string name = section.first; @@ -564,18 +566,25 @@ namespace client std::shared_ptr localDestination = nullptr; if (keys.length () > 0) { - i2p::data::PrivateKeys k; - if(LoadPrivateKeys (k, keys, sigType, cryptoType)) - { - localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ()); - if (!localDestination) + auto it = destinations.find (keys); + if (it != destinations.end ()) + localDestination = it->second; + else + { + i2p::data::PrivateKeys k; + if(LoadPrivateKeys (k, keys, sigType, cryptoType)) { - if(matchTunnels) - localDestination = CreateNewMatchedTunnelDestination(k, dest, &options); - else - localDestination = CreateNewLocalDestination (k, type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT, &options); + localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ()); + if (!localDestination) + { + if(matchTunnels) + localDestination = CreateNewMatchedTunnelDestination(k, dest, &options); + else + localDestination = CreateNewLocalDestination (k, type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT, &options); + destinations[keys] = localDestination; + } } - } + } } if (type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) { @@ -679,12 +688,21 @@ namespace client ReadI2CPOptions (section, options); std::shared_ptr localDestination = nullptr; - i2p::data::PrivateKeys k; - if(!LoadPrivateKeys (k, keys, sigType, cryptoType)) - continue; - localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ()); - if (!localDestination) - localDestination = CreateNewLocalDestination (k, true, &options); + auto it = destinations.find (keys); + if (it != destinations.end ()) + localDestination = it->second; + else + { + i2p::data::PrivateKeys k; + if(!LoadPrivateKeys (k, keys, sigType, cryptoType)) + continue; + localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ()); + if (!localDestination) + { + localDestination = CreateNewLocalDestination (k, true, &options); + destinations[keys] = localDestination; + } + } if (type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER) { // udp server tunnel From e7ff6fbffc437adef64e198eed8ae34085741cc9 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 14 Aug 2020 09:54:31 -0400 Subject: [PATCH 45/49] don't save invalid addreses --- libi2pd_client/AddressBook.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index 8b8e781d..7af1272d 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.cpp @@ -198,13 +198,18 @@ namespace client for (const auto& it: addresses) { - f << it.first << ","; - if (it.second->IsIdentHash ()) - f << it.second->identHash.ToBase32 (); + if (it.second->IsValid ()) + { + f << it.first << ","; + if (it.second->IsIdentHash ()) + f << it.second->identHash.ToBase32 (); + else + f << it.second->blindedPublicKey->ToB33 (); + f << std::endl; + num++; + } else - f << it.second->blindedPublicKey->ToB33 (); - f << std::endl; - num++; + LogPrint (eLogWarning, "Addressbook: invalid address ", it.first); } LogPrint (eLogInfo, "Addressbook: ", num, " addresses saved"); return num; From 3159b06988a215a745eba48c1e1c8c41fcf231c3 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 15 Aug 2020 13:53:49 -0400 Subject: [PATCH 46/49] reseeds update --- .../certificates/reseed/bugme_at_mail.i2p.crt | 32 ----------------- .../reseed/reseed_at_diva.exchange.crt | 34 +++++++++++++++++++ libi2pd/Config.cpp | 2 +- 3 files changed, 35 insertions(+), 33 deletions(-) delete mode 100644 contrib/certificates/reseed/bugme_at_mail.i2p.crt create mode 100644 contrib/certificates/reseed/reseed_at_diva.exchange.crt diff --git a/contrib/certificates/reseed/bugme_at_mail.i2p.crt b/contrib/certificates/reseed/bugme_at_mail.i2p.crt deleted file mode 100644 index 2b6acac0..00000000 --- a/contrib/certificates/reseed/bugme_at_mail.i2p.crt +++ /dev/null @@ -1,32 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFezCCA2OgAwIBAgIEUQYyQjANBgkqhkiG9w0BAQ0FADBuMQswCQYDVQQGEwJY -WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt -b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEXMBUGA1UEAwwOYnVnbWVAbWFpbC5p -MnAwHhcNMTQxMTA2MDkxMTE0WhcNMjQxMTA1MDkxMTE0WjBuMQswCQYDVQQGEwJY -WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt -b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEXMBUGA1UEAwwOYnVnbWVAbWFpbC5p -MnAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCrThOH0eSDT0VnCSBC -sqYmAydWH+O8eNttDXr2mSvZLhvAW+6/xHTkKhaWvkIvvS0Vh8hujMnD90Cgp4Fk -TKCxMj9K527o5xIZwWW05OevbjlBwIpVLO1PjmsfsoD1nIX14eEzJSEoAulKsv7V -jGUC/6hC11mmVvH9buQLSRv6sCjuAcMszmw3TAD+XYBIs+z57KuwYXtX3+OA543c -l1/ZKLYkkwY8cwzZqWDVWqTKP5TfVae58t40HhJk3bOsr21FZsaOjlmao3GO+d/3 -exKuUGJRcolSqskL3sZ1ovFqko81obvvx0upI0YA0iMr/NRGl3VPuf/LJvRppYGc -LsJHgy9TIgtHvaXRi5Nt4CbKl9sZh/7WkkTTI5YGvevu00btlabAN+DSAZZqdsB3 -wY8HhM1MHiA9SWsqwU65TwErcRrjNna2FiDHEu0xk5+/iAGl6CSKHZBmNcYKXSv8 -cwShB0jjmciK0a05nC638RPgj0fng7KRrSglyzfjXRrljmZ40LSBL/GGMZMWpOM7 -mEsBH5UZJ/2BEmjc9X9257zBdx8BK8y1TXpAligpNBsERcTw1WP1PJ35einZvlXW -qI3GwMf0sl26sn+evcK0gDl27jVDZ45MtNQEq64M4NV3Tn9zq0eg/39YvjVeqrI5 -l7sxmYqYGR6BuSncwdc4x+t6swIDAQABoyEwHzAdBgNVHQ4EFgQU/REZ7NMbVZHr -Xkao6Q8Ccqv2kAMwDQYJKoZIhvcNAQENBQADggIBACc2YjLVNbl1kJUdg2klCLJt -5LjNTiIZa2Cha5GStlC/lyoRRge6+q/y9TN3tTptlzLPS9pI9EE1GfIQaE+HAk+e -/bC3KUOAHgVuETvsNAbfpaVsPCdWpFuXmp/4b9iDN7qZy4afTKUPA/Ir/cLfNp14 -JULfP4z2yFOsCQZ5viNFAs1u99FrwobV2LBzUSIJQewsksuOwj96zIyau0Y629oJ -k+og88Tifd9EH3MVZNGhdpojQDDdwHQSITnCDgfRP5yER1WIA4jg6l+mM90QkvLY -5NjWTna5kJ3X6UizvgCk365yzT2sbN3R9UGXfCJa9GBcnnviJtJF3+/gC0abwY2f -NtVYp32Xky45NY/NdRhDg0bjHP3psxmX+Sc0M9NuQcDQ+fUR+CzM0IGeiszkzXOs -RG+bOou2cZ81G4oxWdAALHIRrn7VvLGlkFMxiIZyhYcTGQZzsTPT6n18dY99+DAV -yQWZfIRdm8DOnt0G+cwfeohc/9ZwDmj4jJAAi0aeTXdY6NEGIVydk6MAycEhg2Hx -9EV96kRwZNIW0AGY8CozECFL3Eyo2ClQVV4Q35SsBibsitDjM03usc2DJ/qjynXA -C8HoOSWgbddiBvqZueqK8GdhykOy3J3ysr+MNN/lbG48LqkQr1OWxev9rGGQ6RJT -wpBgPyAFAwouPy1whmnx ------END CERTIFICATE----- diff --git a/contrib/certificates/reseed/reseed_at_diva.exchange.crt b/contrib/certificates/reseed/reseed_at_diva.exchange.crt new file mode 100644 index 00000000..04b1524b --- /dev/null +++ b/contrib/certificates/reseed/reseed_at_diva.exchange.crt @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIIF0zCCA7ugAwIBAgIQWjHyC+NRh3emuuAwcEnKSjANBgkqhkiG9w0BAQsFADB0 +MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK +ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEdMBsGA1UEAwwU +cmVzZWVkQGRpdmEuZXhjaGFuZ2UwHhcNMjAwNjA5MDUzNjQ1WhcNMzAwNjA5MDUz +NjQ1WjB0MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4w +HAYDVQQKExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEdMBsG +A1UEAwwUcmVzZWVkQGRpdmEuZXhjaGFuZ2UwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQC6BJGeMEgoXk9dlzKVfmwHrT2VpwTT+wRJvh3eAM746u4uDT2y +NPHXhdGcQ9dRRZ63T98IshWCwOmWSlm1kdWkmKkVVb93GUoMQ3gziCi0apLJMAau +gEu/sPCbORS2dPsQeAPW2eIsJO7dSjTRiQAuquW//NcIXG4gnxDA52lgke1BvpKr +83SJlCrqECAy6OKtZ49yn75CqmPPWFn0b/E8bxruN5ffeipTTospvdEtT41gXUqk +hOz3k8ang+QTWiP//jOjk31KXZ2dbh0LOlNJOvRxCqQmBZafNxxCR4DH8RewfPlL +qOiOJVzbLSP9RjqPLwnny5BOjbLWXcaybN5Qv2Pyd4mKtN3EpqBwRu7VnzXpsuuG +gRbxNmfKJ/vBEGrZAHAxi0NkHHEEne3B7pPDc2dVZHOfTfCu31m9uDHZ4eHEsNOJ +SJRiGjq74l0chCSlBGLrD1Y9LPyqadjdwuB9bzM0tMFC1wPflanQCflhhnEzAfbN +BaU2GRXo/I1UCDW/dH1FIkqEe61eMW1Lwqr5tdlrUpdr5VIddTyNJRBJogbZ+HZE +8mcoJW2lXRAkYi7KEm4b4EQNe7sbRNTF0j+fAJ+3ZOZ3O3SMHss6ignlSa+giVim +VvL+Joc6wpSzxpeNPf6m82cEO/UvifFYeOC9TpiRriSt+vvgQVzQtfQ+fQIDAQAB +o2EwXzAOBgNVHQ8BAf8EBAMCAoQwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUF +BwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHJlc2VlZEBkaXZhLmV4Y2hh +bmdlMA0GCSqGSIb3DQEBCwUAA4ICAQCFGOb1dHlwjmgFHEER6oMiGWl1mI3Hb7GX +NNI6QUhZQ+iEWGYtsOTk3Q8xejL8t6AG/ZLXfZviLIJXZc5XZfPXk0ezDSC2cYxQ +ZAyYPw2dRP14brI86sCSqNAFIax/U5SM3zXhCbBiTfaEoBPfDpvKjx+VliaITUnc +sHTRn+C5ID5M8cZIqUSGECPEMU/bDtuRNJLTKYaJ98yXtYuS2CWsMEM4o0GGcnYQ +5HOZT/lbbwfq1Ks7IyJpeIpRaS5qckGcfgkxFY4eGujDuaFeWC+HCIh9RzBJrqZR +73Aly4Pyu7Jjg8xCCf9MswDjtqAjEHgWCmRLWL7p3H6cPipFKNMY6yomYZl5urE7 +q6DUAZFKwPqlZpyeaY4/SVvaHTxuPp7484s3db4kPhdmuQS/DOB/7d+cn/S580Vy +ALqlFQjtjLEaT16upceAV0gYktDInE6Rtym/OsqilrtYks/Sc0GROSz8lJhDDWbr +W3t92muSXDh0rYrEUYWl+xl1gSTpbIP75zzU+cUr1E/qlRY9qZn66FsJpOuN0I0q +UXsQS/bPDcA+IW48Hd9LfO9gtTWZslwFTimjEvQ2nJAnUlUQP6OfuPUKHoYX/CwY +2LCN8+pv2bKPDVHvp0lf6xrbbZNvFtzfR0G3AprZjYpuu2XgjVB5nJnwmbH74b9w +LD8d2z2Lgg== +-----END CERTIFICATE----- diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index d11152dd..6ce3a714 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -195,7 +195,7 @@ namespace config { ("reseed.proxy", value()->default_value(""), "url for reseed proxy, supports http/socks") ("reseed.urls", value()->default_value( "https://reseed.i2p-projekt.de/," - "https://i2p.mooo.com/netDb/," + "https://reseed.diva.exchange/," "https://reseed.i2p2.no/," "https://reseed-fr.i2pd.xyz/," "https://reseed.memcpy.io/," From 0777bad2c3b92607825c25898383346ae877a236 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sun, 23 Aug 2020 22:25:54 +0300 Subject: [PATCH 47/49] [webconsole] fix warning, mobile page width Signed-off-by: R4SAS --- daemon/HTTPServer.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 416cf1e4..d6b7a2ef 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -83,17 +83,18 @@ namespace http { " .disabled:after { color: #D33F3F; content: \"Disabled\" }\r\n" " .enabled:after { color: #56B734; content: \"Enabled\" }\r\n" " @media screen and (max-width: 980px) {\r\n" /* adaptive style */ + " body { padding: 1.5em 0 0 0; }\r\n" " .menu { width: 100%; display: block; float: none; position: unset; font-size: 16px;\r\n" " text-align: center; }\r\n" " .menu a, .commands a { padding: 2px; }\r\n" - " .content { float: none; margin: 0; margin-top: 16px; max-width: 100%; width: 100%;\r\n" + " .content { float: none; margin-left: unset; margin-top: 16px; max-width: 100%; width: 100%;\r\n" " text-align: center; }\r\n" " a, .slide label { /* margin-right: 10px; */ display: block; /* font-size: 18px; */ }\r\n" " .header { margin: unset; font-size: 1.5em; } small {display: block}\r\n" " a.button { -webkit-appearance: button; -moz-appearance: button; appearance: button; text-decoration: none;\r\n" " color: initial; margin-top: 10px; padding: 6px; border: 1px solid #894c84; width: -webkit-fill-available; }\r\n" " input { width: 35%; text-align: center; padding: 5px;\r\n" - " border: 2px solid #ccc; -webkit-border-radius: 5px; border-radius: 5px; font-size: 24px; }\r\n" + " border: 2px solid #ccc; -webkit-border-radius: 5px; border-radius: 5px; font-size: 18px; }\r\n" " textarea { width: -webkit-fill-available; height: auto; padding:5px; border:2px solid #ccc;\r\n" " -webkit-border-radius: 5px; border-radius: 5px; font-size: 12px; }\r\n" " button[type=submit] { padding: 5px 15px; background: #ccc; border: 0 none; cursor: pointer;\r\n" @@ -933,7 +934,7 @@ namespace http { time_t t = divTime.quot; struct tm *tm = localtime(&t); char date[128]; - snprintf(date, sizeof(date), "%02d/%02d/%d %02d:%02d:%02d.%03ld", tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec, divTime.rem); + snprintf(date, sizeof(date), "%02d/%02d/%d %02d:%02d:%02d.%03lld", tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec, divTime.rem); return date; } From 954781262c1be24673c9c7d57527eefe921aa065 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 24 Aug 2020 12:27:39 -0400 Subject: [PATCH 48/49] 2.33.0 --- ChangeLog | 23 +++++++++++++++++++ Win32/installer.iss | 2 +- android/build.gradle | 4 ++-- contrib/rpm/i2pd-git.spec | 5 +++- contrib/rpm/i2pd.spec | 5 +++- debian/changelog | 6 +++++ libi2pd/version.h | 6 ++--- qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml | 1 + 8 files changed, 44 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 33792a97..362b28bf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,29 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.33.0] - 2020-08-24 +### Added +- Shared transient addresses +- crypto.ratchet.inboundTags paramater +- Multiple encryption keys through I2CP +- Pre-calculated x25519 ephemeral keys +- Change datagram routing path if nothing comes back in 10 seconds +- Shared routing path for datagram session +### Changed +- UDP tunnels send mix of repliable and raw datagrams in bulk +- Encrypt SSU packet again upon resend +- Start new tunnel message if remaining buffer is too small +- Use LeaseSet2 for ECIES-X25519-AEAD-Ratchet automatically +- Save new ECIES-X25519-AEAD-Ratchet session with NSR tagset +- Generate random padding lengths for ECIES-X25519-AEAD-Ratchet in bulk +- Webconsole layout +- Reseed servers list +### Fixed +- Don't connect through terminated SAM destination +- Differentiate UDP server sessions by port +- ECIES-X25519-AEAD-Ratchet through I2CP +- Don't save invalid address to AddressBook + ## [2.32.1] - 2020-06-02 ### Added - Read explicit peers in tunnels config diff --git a/Win32/installer.iss b/Win32/installer.iss index 40724d7a..fbbeba53 100644 --- a/Win32/installer.iss +++ b/Win32/installer.iss @@ -1,5 +1,5 @@ #define I2Pd_AppName "i2pd" -#define I2Pd_ver "2.32.1" +#define I2Pd_ver "2.33.0" #define I2Pd_Publisher "PurpleI2P" [Setup] diff --git a/android/build.gradle b/android/build.gradle index c9e8429c..ace2047a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -30,8 +30,8 @@ android { applicationId "org.purplei2p.i2pd" targetSdkVersion 29 minSdkVersion 14 - versionCode 2321 - versionName "2.32.1" + versionCode 2330 + versionName "2.33.0" setProperty("archivesBaseName", archivesBaseName + "-" + versionName) ndk { abiFilters 'armeabi-v7a' diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index 7079ec23..00bea0b0 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -1,7 +1,7 @@ %define git_hash %(git rev-parse HEAD | cut -c -7) Name: i2pd-git -Version: 2.32.1 +Version: 2.33.0 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -124,6 +124,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Aug 24 2020 orignal - 2.33.0 +- update to 2.33.0 + * Tue Jun 02 2020 r4sas - 2.32.1 - update to 2.32.1 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 5c0b8fbd..22287f24 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.32.1 +Version: 2.33.0 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -122,6 +122,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Aug 24 2020 orignal - 2.33.0 +- update to 2.33.0 + * Tue Jun 02 2020 r4sas - 2.32.1 - update to 2.32.1 diff --git a/debian/changelog b/debian/changelog index b01f9519..bac3f3b3 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.33.0-1) unstable; urgency=medium + + * updated to version 2.33.0/0.9.47 + + -- orignal Mon, 24 Aug 2020 16:00:00 +0000 + i2pd (2.32.1-1) unstable; urgency=high * updated to version 2.32.1 diff --git a/libi2pd/version.h b/libi2pd/version.h index c234516f..db30eee8 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -16,8 +16,8 @@ #define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 32 -#define I2PD_VERSION_MICRO 1 +#define I2PD_VERSION_MINOR 33 +#define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO) #define VERSION I2PD_VERSION @@ -30,7 +30,7 @@ #define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MINOR 9 -#define I2P_VERSION_MICRO 46 +#define I2P_VERSION_MICRO 47 #define I2P_VERSION_PATCH 0 #define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) #define I2P_VERSION_NUMBER MAKE_VERSION_NUMBER(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) diff --git a/qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml b/qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml index 75c57fb7..d3fa2e9e 100644 --- a/qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml +++ b/qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml @@ -35,6 +35,7 @@ + From a0685d804d158796adbdc96deb30fdadc65aa4e5 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 24 Aug 2020 12:48:09 -0400 Subject: [PATCH 49/49] 2.33.0 --- ChangeLog | 2 ++ appveyor.yml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 362b28bf..beef7a5a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -23,6 +23,8 @@ - Differentiate UDP server sessions by port - ECIES-X25519-AEAD-Ratchet through I2CP - Don't save invalid address to AddressBook +- ECDSA signatures names in SAM +- AppArmor profile ## [2.32.1] - 2020-06-02 ### Added diff --git a/appveyor.yml b/appveyor.yml index 0567127c..a6278d2d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.32.1.{build} +version: 2.33.0.{build} pull_requests: do_not_increment_build_number: true branches: