fix(cmd/devp2p): track challenge sources

Signed-off-by: Delweng <delweng@gmail.com>
This commit is contained in:
Delweng 2026-03-03 23:20:17 +08:00
parent e5c6d3a7e5
commit b636489898

View file

@ -22,7 +22,6 @@ import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"net" "net"
"slices"
"time" "time"
"github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/common/mclock"
@ -66,8 +65,7 @@ type conn struct {
log logger log logger
codec *v5wire.Codec codec *v5wire.Codec
idCounter uint32 idCounter uint32
lastFrom string sources map[v5wire.Nonce]string // source addr of WHOAREYOU challenges
lastLocal net.IP
} }
type logger interface { type logger interface {
@ -93,6 +91,7 @@ func newConn(dest *enode.Node, log logger) *conn {
remoteAddr: &net.UDPAddr{IP: dest.IP(), Port: dest.UDP()}, remoteAddr: &net.UDPAddr{IP: dest.IP(), Port: dest.UDP()},
codec: v5wire.NewCodec(ln, key, mclock.System{}, nil), codec: v5wire.NewCodec(ln, key, mclock.System{}, nil),
log: log, log: log,
sources: make(map[v5wire.Nonce]string),
} }
} }
@ -203,16 +202,12 @@ func (tc *conn) findnode(c net.PacketConn, dists []uint) ([]*enode.Node, error)
// write sends a packet on the given connection. // write sends a packet on the given connection.
func (tc *conn) write(c net.PacketConn, p v5wire.Packet, challenge *v5wire.Whoareyou) v5wire.Nonce { func (tc *conn) write(c net.PacketConn, p v5wire.Packet, challenge *v5wire.Whoareyou) v5wire.Nonce {
lip := laddr(c).IP
if tc.lastLocal != nil && !tc.lastLocal.Equal(lip) && challenge == nil {
// New local endpoint: drop old sessions to avoid reusing them across IPs.
tc.codec = v5wire.NewCodec(tc.localNode, tc.localKey, mclock.System{}, nil)
}
tc.lastLocal = slices.Clone(lip)
addr := tc.remoteAddr.String() addr := tc.remoteAddr.String()
if challenge != nil && tc.lastFrom != "" { if challenge != nil {
addr = tc.lastFrom if from, ok := tc.sources[challenge.Nonce]; ok {
addr = from
delete(tc.sources, challenge.Nonce)
}
} }
packet, nonce, err := tc.codec.Encode(tc.remote.ID(), addr, p, challenge) packet, nonce, err := tc.codec.Encode(tc.remote.ID(), addr, p, challenge)
if err != nil { if err != nil {
@ -236,11 +231,13 @@ func (tc *conn) read(c net.PacketConn) v5wire.Packet {
if err != nil { if err != nil {
return &readError{err} return &readError{err}
} }
tc.lastFrom = fromAddr.String()
_, _, p, err := tc.codec.Decode(buf[:n], fromAddr.String()) _, _, p, err := tc.codec.Decode(buf[:n], fromAddr.String())
if err != nil { if err != nil {
return &readError{err} return &readError{err}
} }
if w, ok := p.(*v5wire.Whoareyou); ok {
tc.sources[w.Nonce] = fromAddr.String()
}
tc.logf("<< %s", p.Name()) tc.logf("<< %s", p.Name())
return p return p
} }