fix: IP, Addr, AddrPort changes

This commit is contained in:
Igor Sirotin 2025-09-30 23:06:40 +01:00
parent 68b48e88df
commit 7daed85191
No known key found for this signature in database
GPG Key ID: 0EABBCB40CB9AD4A
5 changed files with 31 additions and 23 deletions

View File

@ -140,7 +140,7 @@ func (it *lookup) slowdown() {
}
func (it *lookup) query(n *node, reply chan<- []*node) {
fails := it.tab.db.FindFails(n.ID(), n.IP())
fails := it.tab.db.FindFails(n.ID(), n.IPAddr())
r, err := it.queryfunc(n)
if errors.Is(err, errClosed) {
// Avoid recording failures on shutdown.
@ -148,7 +148,7 @@ func (it *lookup) query(n *node, reply chan<- []*node) {
return
} else if len(r) == 0 {
fails++
it.tab.db.UpdateFindFails(n.ID(), n.IP(), fails)
it.tab.db.UpdateFindFails(n.ID(), n.IPAddr(), fails)
// Remove the node from the local table if it fails to return anything useful too
// many times, but only if there are enough other nodes in the bucket.
if fails >= maxFindnodeFailures && it.tab.bucketLen(n.ID()) >= bucketSize/2 {
@ -156,7 +156,7 @@ func (it *lookup) query(n *node, reply chan<- []*node) {
}
} else if fails > 0 {
// Reset failure counter because it counts _consecutive_ failures.
it.tab.db.UpdateFindFails(n.ID(), n.IP(), 0)
it.tab.db.UpdateFindFails(n.ID(), n.IPAddr(), 0)
}
// Grab as many nodes as possible. Some of them might not be alive anymore, but we'll

View File

@ -44,7 +44,7 @@ type meteredUdpConn struct {
func newMeteredConn(conn UDPConn) UDPConn {
// Short circuit if metrics are disabled
if !metrics.Enabled {
if !metrics.Enabled() {
return conn
}
return &meteredUdpConn{UDPConn: conn}

View File

@ -26,6 +26,7 @@ import (
"fmt"
"io"
"net"
"net/netip"
"sync"
"time"
@ -34,6 +35,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/netutil"
"github.com/waku-org/go-discover/discover/v4wire"
)
@ -242,7 +244,7 @@ func (t *UDPv4) sendPing(toid enode.ID, toaddr *net.UDPAddr, callback func()) *r
return matched, matched
})
// Send the packet.
t.localNode.UDPContact(toaddr)
t.localNode.UDPContact(toaddr.AddrPort())
t.write(toaddr, toid, req.Name(), packet)
return rm
}
@ -560,15 +562,15 @@ func (t *UDPv4) handlePacket(from *net.UDPAddr, buf []byte) error {
}
// checkBond checks if the given node has a recent enough endpoint proof.
func (t *UDPv4) checkBond(id enode.ID, ip net.IP) bool {
return time.Since(t.db.LastPongReceived(id, ip)) < bondExpiration
func (t *UDPv4) checkBond(id enode.ID, addr netip.Addr) bool {
return time.Since(t.db.LastPongReceived(id, addr)) < bondExpiration
}
// ensureBond solicits a ping from a node if we haven't seen a ping from it for a while.
// This ensures there is a valid endpoint proof on the remote end.
func (t *UDPv4) ensureBond(toid enode.ID, toaddr *net.UDPAddr) {
tooOld := time.Since(t.db.LastPingReceived(toid, toaddr.IP)) > bondExpiration
if tooOld || t.db.FindFails(toid, toaddr.IP) > maxFindnodeFailures {
tooOld := time.Since(t.db.LastPingReceived(toid, toaddr.AddrPort().Addr())) > bondExpiration
if tooOld || t.db.FindFails(toid, toaddr.AddrPort().Addr()) > maxFindnodeFailures {
rm := t.sendPing(toid, toaddr, nil)
<-rm.errc
// Wait for them to ping back and process our pong.
@ -668,7 +670,7 @@ func (t *UDPv4) handlePing(h *packetHandlerV4, from *net.UDPAddr, fromID enode.I
// Ping back if our last pong on file is too far in the past.
n := wrapNode(enode.NewV4(h.senderKey, from.IP, int(req.From.TCP), from.Port))
if time.Since(t.db.LastPongReceived(n.ID(), from.IP)) > bondExpiration {
if time.Since(t.db.LastPongReceived(n.ID(), from.AddrPort().Addr())) > bondExpiration {
t.sendPing(fromID, from, func() {
t.tab.addVerifiedNode(n)
})
@ -677,8 +679,8 @@ func (t *UDPv4) handlePing(h *packetHandlerV4, from *net.UDPAddr, fromID enode.I
}
// Update node database and endpoint predictor.
t.db.UpdateLastPingReceived(n.ID(), from.IP, time.Now())
t.localNode.UDPEndpointStatement(from, &net.UDPAddr{IP: req.To.IP, Port: int(req.To.UDP)})
t.db.UpdateLastPingReceived(n.ID(), from.AddrPort().Addr(), time.Now())
t.localNode.UDPEndpointStatement(from.AddrPort(), req.To.UDPAddrPort())
}
// PONG/v4
@ -692,8 +694,8 @@ func (t *UDPv4) verifyPong(h *packetHandlerV4, from *net.UDPAddr, fromID enode.I
if !t.handleReply(fromID, from.IP, req) {
return errUnsolicitedReply
}
t.localNode.UDPEndpointStatement(from, &net.UDPAddr{IP: req.To.IP, Port: int(req.To.UDP)})
t.db.UpdateLastPongReceived(fromID, from.IP, time.Now())
t.localNode.UDPEndpointStatement(from.AddrPort(), req.To.UDPAddrPort())
t.db.UpdateLastPongReceived(fromID, from.AddrPort().Addr(), time.Now())
return nil
}
@ -705,7 +707,7 @@ func (t *UDPv4) verifyFindnode(h *packetHandlerV4, from *net.UDPAddr, fromID eno
if v4wire.Expired(req.Expiration) {
return errExpired
}
if !t.checkBond(fromID, from.IP) {
if !t.checkBond(fromID, from.AddrPort().Addr()) {
// No endpoint proof pong exists, we don't process the packet. This prevents an
// attack vector where the discovery protocol could be used to amplify traffic in a
// DDOS attack. A malicious actor would send a findnode request with the IP address
@ -765,7 +767,7 @@ func (t *UDPv4) verifyENRRequest(h *packetHandlerV4, from *net.UDPAddr, fromID e
if v4wire.Expired(req.Expiration) {
return errExpired
}
if !t.checkBond(fromID, from.IP) {
if !t.checkBond(fromID, from.AddrPort().Addr()) {
return errUnknownNode
}
return nil

View File

@ -25,6 +25,7 @@ import (
"fmt"
"math/big"
"net"
"net/netip"
"time"
"github.com/ethereum/go-ethereum/common/math"
@ -151,13 +152,16 @@ type Endpoint struct {
// NewEndpoint creates an endpoint.
func NewEndpoint(addr *net.UDPAddr, tcpPort uint16) Endpoint {
ip := net.IP{}
if ip4 := addr.IP.To4(); ip4 != nil {
ip = ip4
} else if ip6 := addr.IP.To16(); ip6 != nil {
ip = ip6
return Endpoint{
IP: addr.IP,
UDP: uint16(addr.Port),
TCP: tcpPort,
}
return Endpoint{IP: ip, UDP: uint16(addr.Port), TCP: tcpPort}
}
func (ep *Endpoint) UDPAddrPort() netip.AddrPort {
addr, _ := netip.AddrFromSlice(ep.IP)
return netip.AddrPortFrom(addr, ep.UDP)
}
type Packet interface {

View File

@ -25,6 +25,7 @@ import (
"fmt"
"io"
"net"
"net/netip"
"sync"
"time"
@ -761,7 +762,8 @@ func (t *UDPv5) handle(p v5wire.Packet, fromID enode.ID, fromAddr *net.UDPAddr)
t.handlePing(p, fromID, fromAddr)
case *v5wire.Pong:
if t.handleCallResponse(fromID, fromAddr, p) {
t.localNode.UDPEndpointStatement(fromAddr, &net.UDPAddr{IP: p.ToIP, Port: int(p.ToPort)})
toAddr, _ := netip.AddrFromSlice(p.ToIP)
t.localNode.UDPEndpointStatement(fromAddr.AddrPort(), netip.AddrPortFrom(toAddr, p.ToPort))
}
case *v5wire.Findnode:
t.handleFindnode(p, fromID, fromAddr)