mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-06-04 21:36:23 +02:00
fill phony record for inbound tunnel with x25519 public key
This commit is contained in:
parent
4c6be3b85a
commit
606881898b
4 changed files with 110 additions and 26 deletions
|
@ -29,7 +29,7 @@ namespace i2p
|
||||||
{
|
{
|
||||||
namespace tunnel
|
namespace tunnel
|
||||||
{
|
{
|
||||||
Tunnel::Tunnel (std::shared_ptr<const TunnelConfig> config):
|
Tunnel::Tunnel (std::shared_ptr<TunnelConfig> config):
|
||||||
TunnelBase (config->GetTunnelID (), config->GetNextTunnelID (), config->GetNextIdentHash ()),
|
TunnelBase (config->GetTunnelID (), config->GetNextTunnelID (), config->GetNextIdentHash ()),
|
||||||
m_Config (config), m_IsShortBuildMessage (false), m_Pool (nullptr),
|
m_Config (config), m_IsShortBuildMessage (false), m_Pool (nullptr),
|
||||||
m_State (eTunnelStatePending), m_FarEndTransports (i2p::data::RouterInfo::eAllTransports),
|
m_State (eTunnelStatePending), m_FarEndTransports (i2p::data::RouterInfo::eAllTransports),
|
||||||
|
@ -44,7 +44,13 @@ namespace tunnel
|
||||||
void Tunnel::Build (uint32_t replyMsgID, std::shared_ptr<OutboundTunnel> outboundTunnel)
|
void Tunnel::Build (uint32_t replyMsgID, std::shared_ptr<OutboundTunnel> outboundTunnel)
|
||||||
{
|
{
|
||||||
auto numHops = m_Config->GetNumHops ();
|
auto numHops = m_Config->GetNumHops ();
|
||||||
const int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : MAX_NUM_RECORDS;
|
bool insertPhonyRecord = m_Config->IsInbound() && numHops < MAX_NUM_RECORDS;
|
||||||
|
if (insertPhonyRecord)
|
||||||
|
{
|
||||||
|
m_Config->CreatePhonyHop ();
|
||||||
|
numHops++;
|
||||||
|
}
|
||||||
|
int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : MAX_NUM_RECORDS;
|
||||||
auto msg = numRecords <= STANDARD_NUM_RECORDS ? NewI2NPShortMessage () : NewI2NPMessage ();
|
auto msg = numRecords <= STANDARD_NUM_RECORDS ? NewI2NPShortMessage () : NewI2NPMessage ();
|
||||||
*msg->GetPayload () = numRecords;
|
*msg->GetPayload () = numRecords;
|
||||||
const size_t recordSize = m_Config->IsShort () ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE;
|
const size_t recordSize = m_Config->IsShort () ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE;
|
||||||
|
@ -52,8 +58,7 @@ namespace tunnel
|
||||||
// shuffle records
|
// shuffle records
|
||||||
std::vector<int> recordIndicies;
|
std::vector<int> recordIndicies;
|
||||||
for (int i = 0; i < numRecords; i++) recordIndicies.push_back(i);
|
for (int i = 0; i < numRecords; i++) recordIndicies.push_back(i);
|
||||||
std::shuffle (recordIndicies.begin(), recordIndicies.end(), m_Pool ? m_Pool->GetRng () : std::mt19937(std::random_device()()));
|
std::shuffle (recordIndicies.begin(), recordIndicies.end(), m_Pool ? m_Pool->GetRng () : std::mt19937(std::random_device()()));
|
||||||
|
|
||||||
// create real records
|
// create real records
|
||||||
uint8_t * records = msg->GetPayload () + 1;
|
uint8_t * records = msg->GetPayload () + 1;
|
||||||
TunnelHopConfig * hop = m_Config->GetFirstHop ();
|
TunnelHopConfig * hop = m_Config->GetFirstHop ();
|
||||||
|
@ -61,7 +66,7 @@ namespace tunnel
|
||||||
while (hop)
|
while (hop)
|
||||||
{
|
{
|
||||||
uint32_t msgID;
|
uint32_t msgID;
|
||||||
if (hop->next) // we set replyMsgID for last hop only
|
if (hop->next && hop->next->ident) // we set replyMsgID for last non-phony hop only
|
||||||
RAND_bytes ((uint8_t *)&msgID, 4);
|
RAND_bytes ((uint8_t *)&msgID, 4);
|
||||||
else
|
else
|
||||||
msgID = replyMsgID;
|
msgID = replyMsgID;
|
||||||
|
@ -89,6 +94,9 @@ namespace tunnel
|
||||||
}
|
}
|
||||||
hop = hop->prev;
|
hop = hop->prev;
|
||||||
}
|
}
|
||||||
|
// delete phony hop after encryption
|
||||||
|
if (insertPhonyRecord) m_Config->DeletePhonyHop ();
|
||||||
|
|
||||||
msg->FillI2NPMessageHeader (m_Config->IsShort () ? eI2NPShortTunnelBuild : eI2NPVariableTunnelBuild);
|
msg->FillI2NPMessageHeader (m_Config->IsShort () ? eI2NPShortTunnelBuild : eI2NPVariableTunnelBuild);
|
||||||
auto s = shared_from_this ();
|
auto s = shared_from_this ();
|
||||||
msg->onDrop = [s]()
|
msg->onDrop = [s]()
|
||||||
|
|
|
@ -81,12 +81,12 @@ namespace tunnel
|
||||||
/** function for visiting a hops stored in a tunnel */
|
/** function for visiting a hops stored in a tunnel */
|
||||||
typedef std::function<void(std::shared_ptr<const i2p::data::IdentityEx>)> TunnelHopVisitor;
|
typedef std::function<void(std::shared_ptr<const i2p::data::IdentityEx>)> TunnelHopVisitor;
|
||||||
|
|
||||||
Tunnel (std::shared_ptr<const TunnelConfig> config);
|
Tunnel (std::shared_ptr<TunnelConfig> config);
|
||||||
~Tunnel ();
|
~Tunnel ();
|
||||||
|
|
||||||
void Build (uint32_t replyMsgID, std::shared_ptr<OutboundTunnel> outboundTunnel = nullptr);
|
void Build (uint32_t replyMsgID, std::shared_ptr<OutboundTunnel> outboundTunnel = nullptr);
|
||||||
|
|
||||||
std::shared_ptr<const TunnelConfig> GetTunnelConfig () const { return m_Config; }
|
std::shared_ptr<TunnelConfig> GetTunnelConfig () const { return m_Config; }
|
||||||
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > GetPeers () const;
|
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > GetPeers () const;
|
||||||
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > GetInvertedPeers () const;
|
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > GetInvertedPeers () const;
|
||||||
bool IsShortBuildMessage () const { return m_IsShortBuildMessage; };
|
bool IsShortBuildMessage () const { return m_IsShortBuildMessage; };
|
||||||
|
@ -125,7 +125,7 @@ namespace tunnel
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::shared_ptr<const TunnelConfig> m_Config;
|
std::shared_ptr<TunnelConfig> m_Config;
|
||||||
std::vector<TunnelHop> m_Hops;
|
std::vector<TunnelHop> m_Hops;
|
||||||
bool m_IsShortBuildMessage;
|
bool m_IsShortBuildMessage;
|
||||||
std::shared_ptr<TunnelPool> m_Pool; // pool, tunnel belongs to, or null
|
std::shared_ptr<TunnelPool> m_Pool; // pool, tunnel belongs to, or null
|
||||||
|
@ -139,7 +139,7 @@ namespace tunnel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
OutboundTunnel (std::shared_ptr<const TunnelConfig> config):
|
OutboundTunnel (std::shared_ptr<TunnelConfig> config):
|
||||||
Tunnel (config), m_Gateway (*this), m_EndpointIdentHash (config->GetLastIdentHash ()) {};
|
Tunnel (config), m_Gateway (*this), m_EndpointIdentHash (config->GetLastIdentHash ()) {};
|
||||||
|
|
||||||
void SendTunnelDataMsgTo (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr<i2p::I2NPMessage> msg);
|
void SendTunnelDataMsgTo (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr<i2p::I2NPMessage> msg);
|
||||||
|
@ -164,7 +164,7 @@ namespace tunnel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
InboundTunnel (std::shared_ptr<const TunnelConfig> config): Tunnel (config), m_Endpoint (true) {};
|
InboundTunnel (std::shared_ptr<TunnelConfig> config): Tunnel (config), m_Endpoint (true) {};
|
||||||
void HandleTunnelDataMsg (std::shared_ptr<I2NPMessage>&& msg) override;
|
void HandleTunnelDataMsg (std::shared_ptr<I2NPMessage>&& msg) override;
|
||||||
virtual size_t GetNumReceivedBytes () const { return m_Endpoint.GetNumReceivedBytes (); };
|
virtual size_t GetNumReceivedBytes () const { return m_Endpoint.GetNumReceivedBytes (); };
|
||||||
bool IsInbound() const override { return true; }
|
bool IsInbound() const override { return true; }
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
* Copyright (c) 2013-2025, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -219,6 +219,42 @@ namespace tunnel
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LongPhonyTunnelHopConfig::CreateBuildRequestRecord (uint8_t * records, uint32_t replyMsgID)
|
||||||
|
{
|
||||||
|
uint8_t * record = records + recordIndex*TUNNEL_BUILD_RECORD_SIZE;
|
||||||
|
memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)i2p::context.GetIdentHash (), 16);
|
||||||
|
memcpy (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, i2p::transport::transports.GetNextX25519KeysPair ()->GetPublicKey (), 32);
|
||||||
|
RAND_bytes (record + 48, TUNNEL_BUILD_RECORD_SIZE - 48);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShortPhonyTunnelHopConfig::CreateBuildRequestRecord (uint8_t * records, uint32_t replyMsgID)
|
||||||
|
{
|
||||||
|
uint8_t * record = records + recordIndex*SHORT_TUNNEL_BUILD_RECORD_SIZE;
|
||||||
|
memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)i2p::context.GetIdentHash (), 16);
|
||||||
|
memcpy (record + SHORT_REQUEST_RECORD_ENCRYPTED_OFFSET, i2p::transport::transports.GetNextX25519KeysPair ()->GetPublicKey (), 32);
|
||||||
|
RAND_bytes (record + 48, SHORT_TUNNEL_BUILD_RECORD_SIZE - 48);
|
||||||
|
}
|
||||||
|
|
||||||
|
TunnelConfig::TunnelConfig (const std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers,
|
||||||
|
bool isShort, i2p::data::RouterInfo::CompatibleTransports farEndTransports):
|
||||||
|
m_IsShort (isShort), m_FarEndTransports (farEndTransports)
|
||||||
|
{
|
||||||
|
// inbound
|
||||||
|
CreatePeers (peers);
|
||||||
|
m_LastHop->SetNextIdent (i2p::context.GetIdentHash ());
|
||||||
|
}
|
||||||
|
|
||||||
|
TunnelConfig::TunnelConfig (const std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers,
|
||||||
|
uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent, bool isShort,
|
||||||
|
i2p::data::RouterInfo::CompatibleTransports farEndTransports):
|
||||||
|
m_IsShort (isShort), m_FarEndTransports (farEndTransports)
|
||||||
|
{
|
||||||
|
// outbound
|
||||||
|
CreatePeers (peers);
|
||||||
|
m_FirstHop->isGateway = false;
|
||||||
|
m_LastHop->SetReplyHop (replyTunnelID, replyIdent);
|
||||||
|
}
|
||||||
|
|
||||||
void TunnelConfig::CreatePeers (const std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers)
|
void TunnelConfig::CreatePeers (const std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers)
|
||||||
{
|
{
|
||||||
TunnelHopConfig * prev = nullptr;
|
TunnelHopConfig * prev = nullptr;
|
||||||
|
@ -245,5 +281,35 @@ namespace tunnel
|
||||||
}
|
}
|
||||||
m_LastHop = prev;
|
m_LastHop = prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TunnelConfig::CreatePhonyHop ()
|
||||||
|
{
|
||||||
|
if (m_LastHop && m_LastHop->ident)
|
||||||
|
{
|
||||||
|
TunnelHopConfig * hop = nullptr;
|
||||||
|
if (m_IsShort)
|
||||||
|
hop = new ShortPhonyTunnelHopConfig ();
|
||||||
|
else
|
||||||
|
hop = new LongPhonyTunnelHopConfig ();
|
||||||
|
if (hop)
|
||||||
|
{
|
||||||
|
hop->prev = m_LastHop;
|
||||||
|
m_LastHop->next = hop;
|
||||||
|
m_LastHop = hop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TunnelConfig::DeletePhonyHop ()
|
||||||
|
{
|
||||||
|
if (m_LastHop && !m_LastHop->ident)
|
||||||
|
{
|
||||||
|
if (m_LastHop->prev) m_LastHop->prev->next = nullptr;
|
||||||
|
else m_FirstHop = nullptr;
|
||||||
|
auto tmp = m_LastHop;
|
||||||
|
m_LastHop = m_LastHop->prev;
|
||||||
|
delete tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2024, The PurpleI2P Project
|
* Copyright (c) 2013-2025, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -77,28 +77,35 @@ namespace tunnel
|
||||||
uint64_t GetGarlicKey (uint8_t * key) const override;
|
uint64_t GetGarlicKey (uint8_t * key) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PhonyTunnelHopConfig: public ECIESTunnelHopConfig
|
||||||
|
{
|
||||||
|
PhonyTunnelHopConfig (): ECIESTunnelHopConfig (nullptr) {}
|
||||||
|
uint8_t GetRetCode (const uint8_t * records) const override { return 0; }
|
||||||
|
bool DecryptBuildResponseRecord (uint8_t * records) const override { return true; }
|
||||||
|
void DecryptRecord (uint8_t * records, int index) const override {} // do nothing
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LongPhonyTunnelHopConfig: public PhonyTunnelHopConfig
|
||||||
|
{
|
||||||
|
void CreateBuildRequestRecord (uint8_t * records, uint32_t replyMsgID) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ShortPhonyTunnelHopConfig: public PhonyTunnelHopConfig
|
||||||
|
{
|
||||||
|
void CreateBuildRequestRecord (uint8_t * records, uint32_t replyMsgID) override;
|
||||||
|
};
|
||||||
|
|
||||||
class TunnelConfig
|
class TunnelConfig
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TunnelConfig (const std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers,
|
TunnelConfig (const std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers,
|
||||||
bool isShort, i2p::data::RouterInfo::CompatibleTransports farEndTransports = i2p::data::RouterInfo::eAllTransports): // inbound
|
bool isShort, i2p::data::RouterInfo::CompatibleTransports farEndTransports = i2p::data::RouterInfo::eAllTransports); // inbound
|
||||||
m_IsShort (isShort), m_FarEndTransports (farEndTransports)
|
|
||||||
{
|
|
||||||
CreatePeers (peers);
|
|
||||||
m_LastHop->SetNextIdent (i2p::context.GetIdentHash ());
|
|
||||||
}
|
|
||||||
|
|
||||||
TunnelConfig (const std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers,
|
TunnelConfig (const std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers,
|
||||||
uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent, bool isShort,
|
uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent, bool isShort,
|
||||||
i2p::data::RouterInfo::CompatibleTransports farEndTransports = i2p::data::RouterInfo::eAllTransports): // outbound
|
i2p::data::RouterInfo::CompatibleTransports farEndTransports = i2p::data::RouterInfo::eAllTransports); // outbound
|
||||||
m_IsShort (isShort), m_FarEndTransports (farEndTransports)
|
|
||||||
{
|
|
||||||
CreatePeers (peers);
|
|
||||||
m_FirstHop->isGateway = false;
|
|
||||||
m_LastHop->SetReplyHop (replyTunnelID, replyIdent);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~TunnelConfig ()
|
virtual ~TunnelConfig ()
|
||||||
{
|
{
|
||||||
TunnelHopConfig * hop = m_FirstHop;
|
TunnelHopConfig * hop = m_FirstHop;
|
||||||
|
@ -182,6 +189,9 @@ namespace tunnel
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetRecordSize () const { return m_IsShort ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE; };
|
size_t GetRecordSize () const { return m_IsShort ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE; };
|
||||||
|
|
||||||
|
void CreatePhonyHop ();
|
||||||
|
void DeletePhonyHop ();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue