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 {
|
if ka == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ka.Timestamp is not updated here to avoid leaking information
|
||||||
|
// about currently connected peers.
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
ka.lastsuccess = now
|
ka.lastsuccess = now
|
||||||
ka.lastattempt = now
|
ka.lastattempt = now
|
||||||
naCopy := *ka.na
|
|
||||||
naCopy.Timestamp = time.Now()
|
|
||||||
ka.na = &naCopy
|
|
||||||
ka.attempts = 0
|
ka.attempts = 0
|
||||||
|
|
||||||
// move to tried set, optionally evicting other addresses if neeed.
|
// 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.
|
StatsMtx sync.Mutex // protects all statistics below here.
|
||||||
versionKnown bool
|
versionKnown bool
|
||||||
protocolVersion uint32
|
protocolVersion uint32
|
||||||
|
versionSent bool
|
||||||
|
verAckReceived bool
|
||||||
services wire.ServiceFlag
|
services wire.ServiceFlag
|
||||||
timeOffset int64
|
timeOffset int64
|
||||||
timeConnected time.Time
|
timeConnected time.Time
|
||||||
|
@ -1480,25 +1482,36 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle each supported message type.
|
// Handle each supported message type.
|
||||||
markConnected := false
|
|
||||||
switch msg := rmsg.(type) {
|
switch msg := rmsg.(type) {
|
||||||
case *wire.MsgVersion:
|
case *wire.MsgVersion:
|
||||||
p.handleVersionMsg(msg)
|
p.handleVersionMsg(msg)
|
||||||
markConnected = true
|
|
||||||
|
|
||||||
case *wire.MsgVerAck:
|
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:
|
case *wire.MsgGetAddr:
|
||||||
p.handleGetAddrMsg(msg)
|
p.handleGetAddrMsg(msg)
|
||||||
|
|
||||||
case *wire.MsgAddr:
|
case *wire.MsgAddr:
|
||||||
p.handleAddrMsg(msg)
|
p.handleAddrMsg(msg)
|
||||||
markConnected = true
|
|
||||||
|
|
||||||
case *wire.MsgPing:
|
case *wire.MsgPing:
|
||||||
p.handlePingMsg(msg)
|
p.handlePingMsg(msg)
|
||||||
markConnected = true
|
|
||||||
|
|
||||||
case *wire.MsgPong:
|
case *wire.MsgPong:
|
||||||
p.handlePongMsg(msg)
|
p.handlePongMsg(msg)
|
||||||
|
@ -1524,7 +1537,6 @@ out:
|
||||||
|
|
||||||
case *wire.MsgInv:
|
case *wire.MsgInv:
|
||||||
p.handleInvMsg(msg)
|
p.handleInvMsg(msg)
|
||||||
markConnected = true
|
|
||||||
|
|
||||||
case *wire.MsgHeaders:
|
case *wire.MsgHeaders:
|
||||||
p.handleHeadersMsg(msg)
|
p.handleHeadersMsg(msg)
|
||||||
|
@ -1537,7 +1549,6 @@ out:
|
||||||
|
|
||||||
case *wire.MsgGetData:
|
case *wire.MsgGetData:
|
||||||
p.handleGetDataMsg(msg)
|
p.handleGetDataMsg(msg)
|
||||||
markConnected = true
|
|
||||||
|
|
||||||
case *wire.MsgGetBlocks:
|
case *wire.MsgGetBlocks:
|
||||||
p.handleGetBlocksMsg(msg)
|
p.handleGetBlocksMsg(msg)
|
||||||
|
@ -1563,16 +1574,6 @@ out:
|
||||||
rmsg.Command())
|
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.
|
// ok we got a message, reset the timer.
|
||||||
// timer just calls p.Disconnect() after logging.
|
// timer just calls p.Disconnect() after logging.
|
||||||
idleTimer.Reset(idleTimeoutMinutes * time.Minute)
|
idleTimer.Reset(idleTimeoutMinutes * time.Minute)
|
||||||
|
@ -1756,7 +1757,10 @@ out:
|
||||||
reset := true
|
reset := true
|
||||||
switch m := msg.msg.(type) {
|
switch m := msg.msg.(type) {
|
||||||
case *wire.MsgVersion:
|
case *wire.MsgVersion:
|
||||||
// should get an ack
|
// should get a verack
|
||||||
|
p.StatsMtx.Lock()
|
||||||
|
p.versionSent = true
|
||||||
|
p.StatsMtx.Unlock()
|
||||||
case *wire.MsgGetAddr:
|
case *wire.MsgGetAddr:
|
||||||
// should get addresses
|
// should get addresses
|
||||||
case *wire.MsgPing:
|
case *wire.MsgPing:
|
||||||
|
@ -1875,6 +1879,15 @@ func (p *peer) Disconnect() {
|
||||||
if atomic.AddInt32(&p.disconnect, 1) != 1 {
|
if atomic.AddInt32(&p.disconnect, 1) != 1 {
|
||||||
return
|
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)
|
peerLog.Tracef("disconnecting %s", p)
|
||||||
close(p.quit)
|
close(p.quit)
|
||||||
if atomic.LoadInt32(&p.connected) != 0 {
|
if atomic.LoadInt32(&p.connected) != 0 {
|
||||||
|
|
Loading…
Add table
Reference in a new issue