The PR branch HEAD was 4e415067 at the time of this review club meeting.
Notes
Attackers may use
fingerprinting techniques
to recognize the same node across different connections. This makes it
possible to test if two addresses belong to the same node, which we generally
try to avoid especially for addresses belonging to privacy-centric networks
such as Tor. Some fingerprinting attacks work across restarts of the victim’s
node, making it possible to detect if a node changes addresses.
A variety of fingerprinting techniques have been patched or mitigated.
For example, attackers could have used requests for old non-main-chain
headers/blocks (#5820,
#8408,
#11113), addr message
timestamps and prune
depth to fingerprint nodes.
The fingerprintable behaviour that PR
#24571 addresses occurs when
a node receives headers from a peer (handled in
PeerManagerImpl::ProcessHeadersMessage).
If the received headers don’t connect to any header in the node’s block
index, then it will request additional headers via a getheaders message in
an attempt to connect the chain.
<b10c> I might have a branch in that tree that not many others have. If you can find out that I have this branch, this leaks information. Not sure if I can pinpoint you with that information, but can get harmful when combined with more information
<lightlike> dergoegge: I mean, if I do an IBD now, will I accept any historical non-best-chain headers in my blockchain index? Or would I only get those if I am online when there are conflicting blocks for my tip, and don't know which will stay in the main chain?
<dergoegge> b10c: exactly you might have seen a header/block that for example after a reorg is no longer part of the main chain and has thus become stale
<larryruane> If my node knows about a block that it thinks is stale, doesn't it forward to all its peers? If so, don't all knows end up knowing about all the same stale blocks?
<lightlike> so in order to accept a stale block header, we must have believed it was in our best chain at the time of acceptance (and then changed our opinion/reorged)?
<b10c> we extend a stale branch with header H+1, send H+1 to a node and see if it requests header H. If it does, it doesn't know about the stale branch. If it doesn't, it knows about the stale branch
<lightlike> Have a list of existing stale blocks that our peer might have or not, create bogus headers building on them, and send them to a peer to check and record for which of the headers we get a GETHEADERS in return.
<larryruane> but is the whole idea of this attack to do this procedure to two different peer network addresses, to try to link them to the same machine?
<dergoegge> larryruane: right, the attacker would know of two addresses say one IPv4 and one Tor and could then, using this technique, figure out if the addresses belong to the same node
<lightlike> if we accept any stale headers that extend the work of their predecessor to our index (as was discussed before) couldn't we just send our victim one of these headers, and then probe again, making the fingerprinting possible even if our victim doesn't have any stale headers at the beginning?
<dergoegge> yea if you have a good collection of past stale headers or are able to mine new ones then you might be able to mark nodes with specific headers you sent to them
<lightlike> Since it's almost time: I'd be interested in the answer to the last question, why the "allow_potentially_invalid_headers" parameter is necessary.
<lightlike> dergoegge: maybe also add the reason for this to the PR description or code, wherever it fits better (not that the test failed, but the root cause why it's necessary). It wasn't clear to me when reviewing.
<dergoegge> specifically "pindex->IsValid(BLOCK_VALID_SCRIPTS)" in PeerManagerImpl::BlockRequestAllowed always returns false for headers, so we need an exception for that if we are deciding if we should leak the info about a header