p2p/discover: improve ping-back check and comments

This commit is contained in:
Felix Lange 2018-07-03 13:57:02 +02:00
parent 1b77946ef5
commit b7172ee02f

View file

@ -306,7 +306,8 @@ func (t *udp) waitping(from NodeID) error {
// findnode sends a findnode request to the given node and waits until // findnode sends a findnode request to the given node and waits until
// the node has sent up to k neighbors. // the node has sent up to k neighbors.
func (t *udp) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node, error) { func (t *udp) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node, error) {
// Ensure bond exists before attempting findnode. // If we haven't seen a ping from the destination node for a while, it won't remember
// our endpoint proof and reject findnode. Solicit a ping first.
if time.Since(t.db.lastPingReceived(toid)) > nodeDBNodeExpiration { if time.Since(t.db.lastPingReceived(toid)) > nodeDBNodeExpiration {
t.ping(toid, toaddr) t.ping(toid, toaddr)
t.waitping(toid) t.waitping(toid)
@ -604,14 +605,12 @@ func (req *ping) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) er
}) })
t.handleReply(fromID, pingPacket, req) t.handleReply(fromID, pingPacket, req)
// Add the node to the table. Before doing so, ensure that we have a recent enough pong
// recorded in the database so their findnode requests will be accepted later.
n := NewNode(fromID, from.IP, uint16(from.Port), req.From.TCP) n := NewNode(fromID, from.IP, uint16(from.Port), req.From.TCP)
if time.Since(t.db.lastPingReceived(fromID)) > nodeDBNodeExpiration { if time.Since(t.db.lastPongReceived(fromID)) > nodeDBNodeExpiration {
// We haven't answered the senders ping since a long time.
// Verify their endpoint by pinging back. If they manage to reply
// their endpoint is legit and can be added to the table.
t.sendPing(fromID, from, func() { t.addThroughPing(n) }) t.sendPing(fromID, from, func() { t.addThroughPing(n) })
} else { } else {
// Add immediately because bond exists.
t.addThroughPing(n) t.addThroughPing(n)
} }
t.db.updateLastPingReceived(fromID, time.Now()) t.db.updateLastPingReceived(fromID, time.Now())
@ -638,13 +637,12 @@ func (req *findnode) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte
return errExpired return errExpired
} }
if !t.db.hasBond(fromID) { if !t.db.hasBond(fromID) {
// No bond exists, we don't process the packet. This prevents // No endpoint proof pong exists, we don't process the packet. This prevents an
// an attack vector where the discovery protocol could be used // attack vector where the discovery protocol could be used to amplify traffic in a
// to amplify traffic in a DDOS attack. A malicious actor // DDOS attack. A malicious actor would send a findnode request with the IP address
// would send a findnode request with the IP address and UDP // and UDP port of the target as the source address. The recipient of the findnode
// port of the target as the source address. The recipient of // packet would then send a neighbors packet (which is a much bigger packet than
// the findnode packet would then send a neighbors packet // findnode) to the victim.
// (which is a much bigger packet than findnode) to the victim.
return errUnknownNode return errUnknownNode
} }
target := crypto.Keccak256Hash(req.Target[:]) target := crypto.Keccak256Hash(req.Target[:])