From 6f54ae24cdeacd14519eac8b127e0e1fea03d66a Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Mon, 11 May 2020 17:11:17 +0200 Subject: [PATCH] p2p: add 0 port check in dialer (#21008) * p2p: add low port check in dialer We already have a check like this for UDP ports, add a similar one in the dialer. This prevents dials to port zero and it's also an extra layer of protection against spamming HTTP servers. * p2p/discover: use errLowPort in v4 code * p2p: change port check * p2p: add comment * p2p/simulations/adapters: ensure assigned port is in all node records --- p2p/dial.go | 19 ++++++++++++++----- p2p/discover/v4_udp.go | 2 +- p2p/simulations/adapters/types.go | 2 +- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/p2p/dial.go b/p2p/dial.go index d190e866a..d36d66550 100644 --- a/p2p/dial.go +++ b/p2p/dial.go @@ -78,6 +78,7 @@ var ( errAlreadyConnected = errors.New("already connected") errRecentlyDialed = errors.New("recently dialed") errNotWhitelisted = errors.New("not contained in netrestrict whitelist") + errNoPort = errors.New("node does not provide TCP port") ) // dialer creates outbound connections and submits them into Server. @@ -388,6 +389,12 @@ func (d *dialScheduler) checkDial(n *enode.Node) error { if n.ID() == d.self { return errSelf } + if n.IP() != nil && n.TCP() == 0 { + // This check can trigger if a non-TCP node is found + // by discovery. If there is no IP, the node is a static + // node and the actual endpoint will be resolved later in dialTask. + return errNoPort + } if _, ok := d.dialing[n.ID()]; ok { return errAlreadyDialing } @@ -474,15 +481,13 @@ type dialError struct { } func (t *dialTask) run(d *dialScheduler) { - if t.dest.Incomplete() { - if !t.resolve(d) { - return - } + if t.needResolve() && !t.resolve(d) { + return } err := t.dial(d, t.dest) if err != nil { - // Try resolving the ID of static nodes if dialing failed. + // For static nodes, resolve one more time if dialing fails. if _, ok := err.(*dialError); ok && t.flags&staticDialedConn != 0 { if t.resolve(d) { t.dial(d, t.dest) @@ -491,6 +496,10 @@ func (t *dialTask) run(d *dialScheduler) { } } +func (t *dialTask) needResolve() bool { + return t.flags&staticDialedConn != 0 && t.dest.IP() == nil +} + // resolve attempts to find the current endpoint for the destination // using discovery. // diff --git a/p2p/discover/v4_udp.go b/p2p/discover/v4_udp.go index 6af05f93d..cc395d8f0 100644 --- a/p2p/discover/v4_udp.go +++ b/p2p/discover/v4_udp.go @@ -169,7 +169,7 @@ func makeEndpoint(addr *net.UDPAddr, tcpPort uint16) rpcEndpoint { func (t *UDPv4) nodeFromRPC(sender *net.UDPAddr, rn rpcNode) (*node, error) { if rn.UDP <= 1024 { - return nil, errors.New("low port") + return nil, errLowPort } if err := netutil.CheckRelayIP(sender.IP, rn.IP); err != nil { return nil, err diff --git a/p2p/simulations/adapters/types.go b/p2p/simulations/adapters/types.go index ec22b712c..498723d1a 100644 --- a/p2p/simulations/adapters/types.go +++ b/p2p/simulations/adapters/types.go @@ -300,5 +300,5 @@ func (n *NodeConfig) initEnode(ip net.IP, tcpport int, udpport int) error { } func (n *NodeConfig) initDummyEnode() error { - return n.initEnode(net.IPv4(127, 0, 0, 1), 0, 0) + return n.initEnode(net.IPv4(127, 0, 0, 1), int(n.Port), 0) }