Reduce fingerprinting.
This change reduces fingerprinting via timestamps in addr messages. Previously, the last seen time for an address was updated when certain protocol commands were received. Now, the last seen time is set when the peer disconnects if the peer had sent a verack message and was connected for more than 20 minutes. This mimics Bitcoin Core commit: 9c2737901b5203f267d21d728019d64b46f1d9f3 Also, add additional sanity checking before updating the peer's timestamp. These include: - Do not mark a peer as connected if we never received a version message. - Disconnect a peer for sending a verack before btcd sent a version - Disconnect a peer for sending multiple verack's
This commit is contained in:
parent
0eef96e1c8
commit
2cc85ef428
2 changed files with 34 additions and 21 deletions
|
@ -862,12 +862,12 @@ func (a *AddrManager) Good(addr *wire.NetAddress) {
|
|||
if ka == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// ka.Timestamp is not updated here to avoid leaking information
|
||||
// about currently connected peers.
|
||||
now := time.Now()
|
||||
ka.lastsuccess = now
|
||||
ka.lastattempt = now
|
||||
naCopy := *ka.na
|
||||
naCopy.Timestamp = time.Now()
|
||||
ka.na = &naCopy
|
||||
ka.attempts = 0
|
||||
|
||||
// move to tried set, optionally evicting other addresses if neeed.
|
||||
|
|
49
peer.go
49
peer.go
|
@ -183,6 +183,8 @@ type peer struct {
|
|||
StatsMtx sync.Mutex // protects all statistics below here.
|
||||
versionKnown bool
|
||||
protocolVersion uint32
|
||||
versionSent bool
|
||||
verAckReceived bool
|
||||
services wire.ServiceFlag
|
||||
timeOffset int64
|
||||
timeConnected time.Time
|
||||
|
@ -1480,25 +1482,36 @@ out:
|
|||
}
|
||||
|
||||
// Handle each supported message type.
|
||||
markConnected := false
|
||||
switch msg := rmsg.(type) {
|
||||
case *wire.MsgVersion:
|
||||
p.handleVersionMsg(msg)
|
||||
markConnected = true
|
||||
|
||||
case *wire.MsgVerAck:
|
||||
// Do nothing.
|
||||
p.StatsMtx.Lock()
|
||||
versionSent := p.versionSent
|
||||
verAckReceived := p.verAckReceived
|
||||
p.StatsMtx.Unlock()
|
||||
|
||||
if !versionSent {
|
||||
peerLog.Infof("Received 'verack' from peer %v "+
|
||||
"before version was sent -- disconnecting", p)
|
||||
break out
|
||||
}
|
||||
if verAckReceived {
|
||||
peerLog.Infof("Already received 'verack' from "+
|
||||
"peer %v -- disconnecting", p)
|
||||
break out
|
||||
}
|
||||
p.verAckReceived = true
|
||||
|
||||
case *wire.MsgGetAddr:
|
||||
p.handleGetAddrMsg(msg)
|
||||
|
||||
case *wire.MsgAddr:
|
||||
p.handleAddrMsg(msg)
|
||||
markConnected = true
|
||||
|
||||
case *wire.MsgPing:
|
||||
p.handlePingMsg(msg)
|
||||
markConnected = true
|
||||
|
||||
case *wire.MsgPong:
|
||||
p.handlePongMsg(msg)
|
||||
|
@ -1524,7 +1537,6 @@ out:
|
|||
|
||||
case *wire.MsgInv:
|
||||
p.handleInvMsg(msg)
|
||||
markConnected = true
|
||||
|
||||
case *wire.MsgHeaders:
|
||||
p.handleHeadersMsg(msg)
|
||||
|
@ -1537,7 +1549,6 @@ out:
|
|||
|
||||
case *wire.MsgGetData:
|
||||
p.handleGetDataMsg(msg)
|
||||
markConnected = true
|
||||
|
||||
case *wire.MsgGetBlocks:
|
||||
p.handleGetBlocksMsg(msg)
|
||||
|
@ -1563,16 +1574,6 @@ out:
|
|||
rmsg.Command())
|
||||
}
|
||||
|
||||
// Mark the address as currently connected and working as of
|
||||
// now if one of the messages that trigger it was processed.
|
||||
if markConnected && atomic.LoadInt32(&p.disconnect) == 0 {
|
||||
if p.na == nil {
|
||||
peerLog.Warnf("we're getting stuff before we " +
|
||||
"got a version message. that's bad")
|
||||
continue
|
||||
}
|
||||
p.server.addrManager.Connected(p.na)
|
||||
}
|
||||
// ok we got a message, reset the timer.
|
||||
// timer just calls p.Disconnect() after logging.
|
||||
idleTimer.Reset(idleTimeoutMinutes * time.Minute)
|
||||
|
@ -1756,7 +1757,10 @@ out:
|
|||
reset := true
|
||||
switch m := msg.msg.(type) {
|
||||
case *wire.MsgVersion:
|
||||
// should get an ack
|
||||
// should get a verack
|
||||
p.StatsMtx.Lock()
|
||||
p.versionSent = true
|
||||
p.StatsMtx.Unlock()
|
||||
case *wire.MsgGetAddr:
|
||||
// should get addresses
|
||||
case *wire.MsgPing:
|
||||
|
@ -1875,6 +1879,15 @@ func (p *peer) Disconnect() {
|
|||
if atomic.AddInt32(&p.disconnect, 1) != 1 {
|
||||
return
|
||||
}
|
||||
|
||||
// Update the address' last seen time if the peer has acknowledged
|
||||
// our version and has sent us its version as well.
|
||||
p.StatsMtx.Lock()
|
||||
if p.verAckReceived && p.versionKnown && p.na != nil {
|
||||
p.server.addrManager.Connected(p.na)
|
||||
}
|
||||
p.StatsMtx.Unlock()
|
||||
|
||||
peerLog.Tracef("disconnecting %s", p)
|
||||
close(p.quit)
|
||||
if atomic.LoadInt32(&p.connected) != 0 {
|
||||
|
|
Loading…
Reference in a new issue