There was a report that by quickly asking a large number of nodes if
they have an ACK object (which the attacker knows but it is injected
into the network by the recipient of the message), it can estimate how
an object propagates through the network, and eventually pinpoint an
originating IP address of the injection, i.e. the IP address of the
message recipient.
This patch mitigates against it by stalling when asked for a nonexisting
object (so that the attacker can't spam requests), and also upon
connection before sending its own inventory list (so that reconnecting
won't help the attacker). It estimates how long a short message takes to
propagate through the network based on how many nodes are in a stream
and bases the stalling time on that. Currently that is about 15 seconds.
Initial connection delay takes into account the time that already passed
since the connection was established.
This basically gives the attacker one shot per a combination of his own
nodes and the nodes he can connect to, and thus makes the attack much
more difficult to succeed.
logger.debug('receiveDataThread starting. ID '+str(id(self))+'. The size of the shared.connectedHostsList is now '+str(len(shared.connectedHostsList)))
@ -125,6 +128,19 @@ class receiveDataThread(threading.Thread):
logger.info("Sleeping for %.2fs",delay-(now-self.startTime))
time.sleep(delay-(now-self.startTime))
elifnotinitial:
logger.info("Sleeping for %.2fs",delay)
time.sleep(delay)
defprocessData(self):
iflen(self.data)<shared.Header.size:# if so little of the data has arrived that we can't even read the checksum then wait for more data.
@ -318,6 +334,7 @@ class receiveDataThread(threading.Thread):
bigInvList[hash]=0
numberOfObjectsInInvMessage=0
payload=''
self.antiIntersectionDelay(True)
# Now let us start appending all of these hashes together. They will be
# sent out in a big inv message to our new peer.
forhash,storedValueinbigInvList.items():
@ -483,6 +500,7 @@ class receiveDataThread(threading.Thread):
payload,=row
self.sendObject(payload)
else:
self.antiIntersectionDelay()
logger.warning('%s asked for an object with a getdata which is not in either our memory inventory or our SQL inventory. We probably cleaned it out after advertising it but before they got around to asking for it.'%(self.peer,))
# Our peer has requested (in a getdata message) that we send an object.