mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-06-25 08:21:24 +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;
|
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)
|
bool CConnman::AddNode(const std::string& strNode)
|
||||||
{
|
{
|
||||||
LOCK(cs_vAddedNodes);
|
LOCK(cs_vAddedNodes);
|
||||||
|
31
src/net.h
31
src/net.h
@ -27,6 +27,7 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <map>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
@ -254,6 +255,13 @@ public:
|
|||||||
void MarkAddressGood(const CAddress& addr);
|
void MarkAddressGood(const CAddress& addr);
|
||||||
void AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty = 0);
|
void AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty = 0);
|
||||||
std::vector<CAddress> GetAddresses();
|
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
|
// This allows temporarily exceeding m_max_outbound_full_relay, with the goal of finding
|
||||||
// a peer that is better than all our current peers.
|
// a peer that is better than all our current peers.
|
||||||
@ -418,6 +426,29 @@ private:
|
|||||||
std::atomic<NodeId> nLastNodeId{0};
|
std::atomic<NodeId> nLastNodeId{0};
|
||||||
unsigned int nPrevNodeCount{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.
|
* Services this instance offers.
|
||||||
*
|
*
|
||||||
|
@ -3477,7 +3477,7 @@ void ProcessMessage(
|
|||||||
pfrom.fSentAddr = true;
|
pfrom.fSentAddr = true;
|
||||||
|
|
||||||
pfrom.vAddrToSend.clear();
|
pfrom.vAddrToSend.clear();
|
||||||
std::vector<CAddress> vAddr = connman.GetAddresses();
|
std::vector<CAddress> vAddr = connman.GetAddresses(pfrom.addr.GetNetwork());
|
||||||
FastRandomContext insecure_rand;
|
FastRandomContext insecure_rand;
|
||||||
for (const CAddress &addr : vAddr) {
|
for (const CAddress &addr : vAddr) {
|
||||||
pfrom.PushAddress(addr, insecure_rand);
|
pfrom.PushAddress(addr, insecure_rand);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user