mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-22 06:26:43 +02:00
Cache responses to addr requests
Prevents a spy from scraping victim's AddrMan by reconnecting and re-requesting addrs.
This commit is contained in:
parent
7cc0e8101f
commit
acd6135b43
11
src/net.cpp
11
src/net.cpp
@ -2539,6 +2539,17 @@ std::vector<CAddress> CConnman::GetAddresses()
|
||||
return addresses;
|
||||
}
|
||||
|
||||
std::vector<CAddress> CConnman::GetAddresses(Network requestor_network)
|
||||
{
|
||||
const auto current_time = GetTime<std::chrono::microseconds>();
|
||||
if (m_addr_response_caches.find(requestor_network) == m_addr_response_caches.end() ||
|
||||
m_addr_response_caches[requestor_network].m_update_addr_response < current_time) {
|
||||
m_addr_response_caches[requestor_network].m_addrs_response_cache = GetAddresses();
|
||||
m_addr_response_caches[requestor_network].m_update_addr_response = current_time + std::chrono::hours(21) + GetRandMillis(std::chrono::hours(6));
|
||||
}
|
||||
return m_addr_response_caches[requestor_network].m_addrs_response_cache;
|
||||
}
|
||||
|
||||
bool CConnman::AddNode(const std::string& strNode)
|
||||
{
|
||||
LOCK(cs_vAddedNodes);
|
||||
|
31
src/net.h
31
src/net.h
@ -27,6 +27,7 @@
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <thread>
|
||||
#include <memory>
|
||||
#include <condition_variable>
|
||||
@ -254,6 +255,13 @@ public:
|
||||
void MarkAddressGood(const CAddress& addr);
|
||||
void AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty = 0);
|
||||
std::vector<CAddress> GetAddresses();
|
||||
/**
|
||||
* Cache is used to minimize topology leaks, so it should
|
||||
* be used for all non-trusted calls, for example, p2p.
|
||||
* A non-malicious call (from RPC) should
|
||||
* call the function without a parameter to avoid using the cache.
|
||||
*/
|
||||
std::vector<CAddress> GetAddresses(Network requestor_network);
|
||||
|
||||
// This allows temporarily exceeding m_max_outbound_full_relay, with the goal of finding
|
||||
// a peer that is better than all our current peers.
|
||||
@ -418,6 +426,29 @@ private:
|
||||
std::atomic<NodeId> nLastNodeId{0};
|
||||
unsigned int nPrevNodeCount{0};
|
||||
|
||||
/**
|
||||
* Cache responses to addr requests to minimize privacy leak.
|
||||
* Attack example: scraping addrs in real-time may allow an attacker
|
||||
* to infer new connections of the victim by detecting new records
|
||||
* with fresh timestamps (per self-announcement).
|
||||
*/
|
||||
struct CachedAddrResponse {
|
||||
std::vector<CAddress> m_addrs_response_cache;
|
||||
std::chrono::microseconds m_update_addr_response{0};
|
||||
};
|
||||
|
||||
/**
|
||||
* Addr responses stored in different caches
|
||||
* per network prevent cross-network node identification.
|
||||
* If a node for example is multi-homed under Tor and IPv6,
|
||||
* a single cache (or no cache at all) would let an attacker
|
||||
* to easily detect that it is the same node by comparing responses.
|
||||
* The used memory equals to 1000 CAddress records (or around 32 bytes) per
|
||||
* distinct Network (up to 5) we have/had an inbound peer from,
|
||||
* resulting in at most ~160 KB.
|
||||
*/
|
||||
std::map<Network, CachedAddrResponse> m_addr_response_caches;
|
||||
|
||||
/**
|
||||
* Services this instance offers.
|
||||
*
|
||||
|
@ -3477,7 +3477,7 @@ void ProcessMessage(
|
||||
pfrom.fSentAddr = true;
|
||||
|
||||
pfrom.vAddrToSend.clear();
|
||||
std::vector<CAddress> vAddr = connman.GetAddresses();
|
||||
std::vector<CAddress> vAddr = connman.GetAddresses(pfrom.addr.GetNetwork());
|
||||
FastRandomContext insecure_rand;
|
||||
for (const CAddress &addr : vAddr) {
|
||||
pfrom.PushAddress(addr, insecure_rand);
|
||||
|
Loading…
x
Reference in New Issue
Block a user