github.com/xinfinOrg/xdposchain@v1.1.0/p2p/discover/udp.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package discover 18 19 import ( 20 "bytes" 21 "container/list" 22 "crypto/ecdsa" 23 "errors" 24 "fmt" 25 "net" 26 "sync" 27 "time" 28 29 "github.com/ethereum/go-ethereum/crypto" 30 "github.com/ethereum/go-ethereum/log" 31 "github.com/ethereum/go-ethereum/p2p/enode" 32 "github.com/ethereum/go-ethereum/p2p/netutil" 33 "github.com/ethereum/go-ethereum/rlp" 34 ) 35 36 // Errors 37 var ( 38 errPacketTooSmall = errors.New("too small") 39 errBadHash = errors.New("bad hash") 40 errExpired = errors.New("expired") 41 errUnsolicitedReply = errors.New("unsolicited reply") 42 errUnknownNode = errors.New("unknown node") 43 errTimeout = errors.New("RPC timeout") 44 errClockWarp = errors.New("reply deadline too far in the future") 45 errClosed = errors.New("socket closed") 46 ) 47 48 // Timeouts 49 const ( 50 respTimeout = 500 * time.Millisecond 51 expiration = 20 * time.Second 52 bondExpiration = 24 * time.Hour 53 54 ntpFailureThreshold = 32 // Continuous timeouts after which to check NTP 55 ntpWarningCooldown = 10 * time.Minute // Minimum amount of time to pass before repeating NTP warning 56 driftThreshold = 10 * time.Second // Allowed clock drift before warning user 57 ) 58 59 // RPC packet types 60 const ( 61 pingPacket = iota + 1 // zero is 'reserved' 62 pongPacket 63 findnodePacket 64 neighborsPacket 65 pingXDC 66 ) 67 68 // RPC request structures 69 type ( 70 ping struct { 71 senderKey *ecdsa.PublicKey // filled in by preverify 72 73 Version uint 74 From, To rpcEndpoint 75 Expiration uint64 76 // Ignore additional fields (for forward compatibility). 77 Rest []rlp.RawValue `rlp:"tail"` 78 } 79 80 // pong is the reply to ping. 81 pong struct { 82 // This field should mirror the UDP envelope address 83 // of the ping packet, which provides a way to discover the 84 // the external address (after NAT). 85 To rpcEndpoint 86 87 ReplyTok []byte // This contains the hash of the ping packet. 88 Expiration uint64 // Absolute timestamp at which the packet becomes invalid. 89 // Ignore additional fields (for forward compatibility). 90 Rest []rlp.RawValue `rlp:"tail"` 91 } 92 93 // findnode is a query for nodes close to the given target. 94 findnode struct { 95 Target encPubkey 96 Expiration uint64 97 // Ignore additional fields (for forward compatibility). 98 Rest []rlp.RawValue `rlp:"tail"` 99 } 100 101 // reply to findnode 102 neighbors struct { 103 Nodes []rpcNode 104 Expiration uint64 105 // Ignore additional fields (for forward compatibility). 106 Rest []rlp.RawValue `rlp:"tail"` 107 } 108 109 rpcNode struct { 110 IP net.IP // len 4 for IPv4 or 16 for IPv6 111 UDP uint16 // for discovery protocol 112 TCP uint16 // for RLPx protocol 113 ID encPubkey 114 } 115 116 rpcEndpoint struct { 117 IP net.IP // len 4 for IPv4 or 16 for IPv6 118 UDP uint16 // for discovery protocol 119 TCP uint16 // for RLPx protocol 120 } 121 ) 122 123 func makeEndpoint(addr *net.UDPAddr, tcpPort uint16) rpcEndpoint { 124 ip := net.IP{} 125 if ip4 := addr.IP.To4(); ip4 != nil { 126 ip = ip4 127 } else if ip6 := addr.IP.To16(); ip6 != nil { 128 ip = ip6 129 } 130 return rpcEndpoint{IP: ip, UDP: uint16(addr.Port), TCP: tcpPort} 131 } 132 133 func (t *udp) nodeFromRPC(sender *net.UDPAddr, rn rpcNode) (*node, error) { 134 if rn.UDP <= 1024 { 135 return nil, errors.New("low port") 136 } 137 if err := netutil.CheckRelayIP(sender.IP, rn.IP); err != nil { 138 return nil, err 139 } 140 if t.netrestrict != nil && !t.netrestrict.Contains(rn.IP) { 141 return nil, errors.New("not contained in netrestrict whitelist") 142 } 143 key, err := decodePubkey(rn.ID) 144 if err != nil { 145 return nil, err 146 } 147 n := wrapNode(enode.NewV4(key, rn.IP, int(rn.TCP), int(rn.UDP))) 148 err = n.ValidateComplete() 149 return n, err 150 } 151 152 func nodeToRPC(n *node) rpcNode { 153 var key ecdsa.PublicKey 154 var ekey encPubkey 155 if err := n.Load((*enode.Secp256k1)(&key)); err == nil { 156 ekey = encodePubkey(&key) 157 } 158 return rpcNode{ID: ekey, IP: n.IP(), UDP: uint16(n.UDP()), TCP: uint16(n.TCP())} 159 } 160 161 // packet is implemented by all protocol messages. 162 type packet interface { 163 // preverify checks whether the packet is valid and should be handled at all. 164 preverify(t *udp, from *net.UDPAddr, fromID enode.ID, fromKey encPubkey) error 165 // handle handles the packet. 166 handle(t *udp, from *net.UDPAddr, fromID enode.ID, mac []byte) 167 // name returns the name of the packet for logging purposes. 168 name() string 169 } 170 171 type conn interface { 172 ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) 173 WriteToUDP(b []byte, addr *net.UDPAddr) (n int, err error) 174 Close() error 175 LocalAddr() net.Addr 176 } 177 178 // udp implements the discovery v4 UDP wire protocol. 179 type udp struct { 180 conn conn 181 netrestrict *netutil.Netlist 182 priv *ecdsa.PrivateKey 183 localNode *enode.LocalNode 184 db *enode.DB 185 tab *Table 186 wg sync.WaitGroup 187 188 addReplyMatcher chan *replyMatcher 189 gotreply chan reply 190 closing chan struct{} 191 } 192 193 // pending represents a pending reply. 194 // 195 // Some implementations of the protocol wish to send more than one 196 // reply packet to findnode. In general, any neighbors packet cannot 197 // be matched up with a specific findnode packet. 198 // 199 // Our implementation handles this by storing a callback function for 200 // each pending reply. Incoming packets from a node are dispatched 201 // to all callback functions for that node. 202 type replyMatcher struct { 203 // these fields must match in the reply. 204 from enode.ID 205 ip net.IP 206 ptype byte 207 208 // time when the request must complete 209 deadline time.Time 210 211 // callback is called when a matching reply arrives. If it returns matched == true, the 212 // reply was acceptable. The second return value indicates whether the callback should 213 // be removed from the pending reply queue. If it returns false, the reply is considered 214 // incomplete and the callback will be invoked again for the next matching reply. 215 callback replyMatchFunc 216 217 // errc receives nil when the callback indicates completion or an 218 // error if no further reply is received within the timeout. 219 errc chan<- error 220 } 221 222 type replyMatchFunc func(interface{}) (matched bool, requestDone bool) 223 224 type reply struct { 225 from enode.ID 226 ip net.IP 227 ptype byte 228 data packet 229 230 // loop indicates whether there was 231 // a matching request by sending on this channel. 232 matched chan<- bool 233 } 234 235 // ReadPacket is sent to the unhandled channel when it could not be processed 236 type ReadPacket struct { 237 Data []byte 238 Addr *net.UDPAddr 239 } 240 241 // Config holds Table-related settings. 242 type Config struct { 243 // These settings are required and configure the UDP listener: 244 PrivateKey *ecdsa.PrivateKey 245 246 // These settings are optional: 247 NetRestrict *netutil.Netlist // network whitelist 248 Bootnodes []*enode.Node // list of bootstrap nodes 249 Unhandled chan<- ReadPacket // unhandled packets are sent on this channel 250 } 251 252 // ListenUDP returns a new table that listens for UDP packets on laddr. 253 func ListenUDP(c conn, ln *enode.LocalNode, cfg Config) (*Table, error) { 254 tab, _, err := newUDP(c, ln, cfg) 255 if err != nil { 256 return nil, err 257 } 258 return tab, nil 259 } 260 261 func newUDP(c conn, ln *enode.LocalNode, cfg Config) (*Table, *udp, error) { 262 udp := &udp{ 263 conn: c, 264 priv: cfg.PrivateKey, 265 netrestrict: cfg.NetRestrict, 266 localNode: ln, 267 db: ln.Database(), 268 closing: make(chan struct{}), 269 gotreply: make(chan reply), 270 addReplyMatcher: make(chan *replyMatcher), 271 } 272 tab, err := newTable(udp, ln.Database(), cfg.Bootnodes) 273 if err != nil { 274 return nil, nil, err 275 } 276 udp.tab = tab 277 278 udp.wg.Add(2) 279 go udp.loop() 280 go udp.readLoop(cfg.Unhandled) 281 return udp.tab, udp, nil 282 } 283 284 func (t *udp) self() *enode.Node { 285 return t.localNode.Node() 286 } 287 288 func (t *udp) close() { 289 close(t.closing) 290 t.conn.Close() 291 t.wg.Wait() 292 } 293 294 func (t *udp) ourEndpoint() rpcEndpoint { 295 n := t.self() 296 a := &net.UDPAddr{IP: n.IP(), Port: n.UDP()} 297 return makeEndpoint(a, uint16(n.TCP())) 298 } 299 300 // ping sends a ping message to the given node and waits for a reply. 301 func (t *udp) ping(toid enode.ID, toaddr *net.UDPAddr) error { 302 return <-t.sendPing(toid, toaddr, nil) 303 } 304 305 // sendPing sends a ping message to the given node and invokes the callback 306 // when the reply arrives. 307 func (t *udp) sendPing(toid enode.ID, toaddr *net.UDPAddr, callback func()) <-chan error { 308 req := &ping{ 309 Version: 4, 310 From: t.ourEndpoint(), 311 To: makeEndpoint(toaddr, 0), // TODO: maybe use known TCP port from DB 312 Expiration: uint64(time.Now().Add(expiration).Unix()), 313 } 314 packet, hash, err := encodePacket(t.priv, pingXDC, req) 315 if err != nil { 316 errc := make(chan error, 1) 317 errc <- err 318 return errc 319 } 320 // Add a matcher for the reply to the pending reply queue. Pongs are matched if they 321 // reference the ping we're about to send. 322 errc := t.pending(toid, toaddr.IP, pongPacket, func(p interface{}) (matched bool, requestDone bool) { 323 matched = bytes.Equal(p.(*pong).ReplyTok, hash) 324 if matched && callback != nil { 325 callback() 326 } 327 return matched, matched 328 }) 329 // Send the packet. 330 t.localNode.UDPContact(toaddr) 331 t.write(toaddr, toid, req.name(), packet) 332 return errc 333 } 334 335 // findnode sends a findnode request to the given node and waits until 336 // the node has sent up to k neighbors. 337 func (t *udp) findnode(toid enode.ID, toaddr *net.UDPAddr, target encPubkey) ([]*node, error) { 338 // If we haven't seen a ping from the destination node for a while, it won't remember 339 // our endpoint proof and reject findnode. Solicit a ping first. 340 if time.Since(t.db.LastPingReceived(toid, toaddr.IP)) > bondExpiration { 341 t.ping(toid, toaddr) 342 // Wait for them to ping back and process our pong. 343 time.Sleep(respTimeout) 344 } 345 346 // Add a matcher for 'neighbours' replies to the pending reply queue. The matcher is 347 // active until enough nodes have been received. 348 nodes := make([]*node, 0, bucketSize) 349 nreceived := 0 350 errc := t.pending(toid, toaddr.IP, neighborsPacket, func(r interface{}) (matched bool, requestDone bool) { 351 reply := r.(*neighbors) 352 for _, rn := range reply.Nodes { 353 nreceived++ 354 n, err := t.nodeFromRPC(toaddr, rn) 355 if err != nil { 356 log.Trace("Invalid neighbor node received", "ip", rn.IP, "addr", toaddr, "err", err) 357 continue 358 } 359 nodes = append(nodes, n) 360 } 361 return true, nreceived >= bucketSize 362 }) 363 t.send(toaddr, toid, findnodePacket, &findnode{ 364 Target: target, 365 Expiration: uint64(time.Now().Add(expiration).Unix()), 366 }) 367 return nodes, <-errc 368 } 369 370 // pending adds a reply matcher to the pending reply queue. 371 // see the documentation of type replyMatcher for a detailed explanation. 372 func (t *udp) pending(id enode.ID, ip net.IP, ptype byte, callback replyMatchFunc) <-chan error { 373 ch := make(chan error, 1) 374 p := &replyMatcher{from: id, ip: ip, ptype: ptype, callback: callback, errc: ch} 375 select { 376 case t.addReplyMatcher <- p: 377 // loop will handle it 378 case <-t.closing: 379 ch <- errClosed 380 } 381 return ch 382 } 383 384 // handleReply dispatches a reply packet, invoking reply matchers. It returns 385 // whether any matcher considered the packet acceptable. 386 func (t *udp) handleReply(from enode.ID, fromIP net.IP, ptype byte, req packet) bool { 387 matched := make(chan bool, 1) 388 select { 389 case t.gotreply <- reply{from, fromIP, ptype, req, matched}: 390 // loop will handle it 391 return <-matched 392 case <-t.closing: 393 return false 394 } 395 } 396 397 // loop runs in its own goroutine. it keeps track of 398 // the refresh timer and the pending reply queue. 399 func (t *udp) loop() { 400 defer t.wg.Done() 401 402 var ( 403 plist = list.New() 404 timeout = time.NewTimer(0) 405 nextTimeout *replyMatcher // head of plist when timeout was last reset 406 contTimeouts = 0 // number of continuous timeouts to do NTP checks 407 ntpWarnTime = time.Unix(0, 0) 408 ) 409 <-timeout.C // ignore first timeout 410 defer timeout.Stop() 411 412 resetTimeout := func() { 413 if plist.Front() == nil || nextTimeout == plist.Front().Value { 414 return 415 } 416 // Start the timer so it fires when the next pending reply has expired. 417 now := time.Now() 418 for el := plist.Front(); el != nil; el = el.Next() { 419 nextTimeout = el.Value.(*replyMatcher) 420 if dist := nextTimeout.deadline.Sub(now); dist < 2*respTimeout { 421 timeout.Reset(dist) 422 return 423 } 424 // Remove pending replies whose deadline is too far in the 425 // future. These can occur if the system clock jumped 426 // backwards after the deadline was assigned. 427 nextTimeout.errc <- errClockWarp 428 plist.Remove(el) 429 } 430 nextTimeout = nil 431 timeout.Stop() 432 } 433 434 for { 435 resetTimeout() 436 437 select { 438 case <-t.closing: 439 for el := plist.Front(); el != nil; el = el.Next() { 440 el.Value.(*replyMatcher).errc <- errClosed 441 } 442 return 443 444 case p := <-t.addReplyMatcher: 445 p.deadline = time.Now().Add(respTimeout) 446 plist.PushBack(p) 447 448 case r := <-t.gotreply: 449 var matched bool // whether any replyMatcher considered the reply acceptable. 450 for el := plist.Front(); el != nil; el = el.Next() { 451 p := el.Value.(*replyMatcher) 452 if p.from == r.from && p.ptype == r.ptype && p.ip.Equal(r.ip) { 453 ok, requestDone := p.callback(r.data) 454 matched = matched || ok 455 // Remove the matcher if callback indicates that all replies have been received. 456 if requestDone { 457 p.errc <- nil 458 plist.Remove(el) 459 } 460 // Reset the continuous timeout counter (time drift detection) 461 contTimeouts = 0 462 } 463 } 464 r.matched <- matched 465 466 case now := <-timeout.C: 467 nextTimeout = nil 468 469 // Notify and remove callbacks whose deadline is in the past. 470 for el := plist.Front(); el != nil; el = el.Next() { 471 p := el.Value.(*replyMatcher) 472 if now.After(p.deadline) || now.Equal(p.deadline) { 473 p.errc <- errTimeout 474 plist.Remove(el) 475 contTimeouts++ 476 } 477 } 478 // If we've accumulated too many timeouts, do an NTP time sync check 479 if contTimeouts > ntpFailureThreshold { 480 if time.Since(ntpWarnTime) >= ntpWarningCooldown { 481 ntpWarnTime = time.Now() 482 go checkClockDrift() 483 } 484 contTimeouts = 0 485 } 486 } 487 } 488 } 489 490 const ( 491 macSize = 256 / 8 492 sigSize = 520 / 8 493 headSize = macSize + sigSize // space of packet frame data 494 ) 495 496 var ( 497 headSpace = make([]byte, headSize) 498 499 // Neighbors replies are sent across multiple packets to 500 // stay below the 1280 byte limit. We compute the maximum number 501 // of entries by stuffing a packet until it grows too large. 502 maxNeighbors int 503 ) 504 505 func init() { 506 p := neighbors{Expiration: ^uint64(0)} 507 maxSizeNode := rpcNode{IP: make(net.IP, 16), UDP: ^uint16(0), TCP: ^uint16(0)} 508 for n := 0; ; n++ { 509 p.Nodes = append(p.Nodes, maxSizeNode) 510 size, _, err := rlp.EncodeToReader(p) 511 if err != nil { 512 // If this ever happens, it will be caught by the unit tests. 513 panic("cannot encode: " + err.Error()) 514 } 515 if headSize+size+1 >= 1280 { 516 maxNeighbors = n 517 break 518 } 519 } 520 } 521 522 func (t *udp) send(toaddr *net.UDPAddr, toid enode.ID, ptype byte, req packet) ([]byte, error) { 523 packet, hash, err := encodePacket(t.priv, ptype, req) 524 if err != nil { 525 return hash, err 526 } 527 return hash, t.write(toaddr, toid, req.name(), packet) 528 } 529 530 func (t *udp) write(toaddr *net.UDPAddr, toid enode.ID, what string, packet []byte) error { 531 _, err := t.conn.WriteToUDP(packet, toaddr) 532 log.Trace(">> "+what, "id", toid, "addr", toaddr, "err", err) 533 return err 534 } 535 536 func encodePacket(priv *ecdsa.PrivateKey, ptype byte, req interface{}) (packet, hash []byte, err error) { 537 b := new(bytes.Buffer) 538 b.Write(headSpace) 539 b.WriteByte(ptype) 540 if err := rlp.Encode(b, req); err != nil { 541 log.Error("Can't encode discv4 packet", "err", err) 542 return nil, nil, err 543 } 544 packet = b.Bytes() 545 sig, err := crypto.Sign(crypto.Keccak256(packet[headSize:]), priv) 546 if err != nil { 547 log.Error("Can't sign discv4 packet", "err", err) 548 return nil, nil, err 549 } 550 copy(packet[macSize:], sig) 551 // add the hash to the front. Note: this doesn't protect the 552 // packet in any way. Our public key will be part of this hash in 553 // The future. 554 hash = crypto.Keccak256(packet[macSize:]) 555 copy(packet, hash) 556 return packet, hash, nil 557 } 558 559 // readLoop runs in its own goroutine. it handles incoming UDP packets. 560 func (t *udp) readLoop(unhandled chan<- ReadPacket) { 561 defer t.wg.Done() 562 if unhandled != nil { 563 defer close(unhandled) 564 } 565 566 // Discovery packets are defined to be no larger than 1280 bytes. 567 // Packets larger than this size will be cut at the end and treated 568 // as invalid because their hash won't match. 569 buf := make([]byte, 1280) 570 for { 571 nbytes, from, err := t.conn.ReadFromUDP(buf) 572 if netutil.IsTemporaryError(err) { 573 // Ignore temporary read errors. 574 log.Debug("Temporary UDP read error", "err", err) 575 continue 576 } else if err != nil { 577 // Shut down the loop for permament errors. 578 log.Debug("UDP read error", "err", err) 579 return 580 } 581 if t.handlePacket(from, buf[:nbytes]) != nil && unhandled != nil { 582 select { 583 case unhandled <- ReadPacket{buf[:nbytes], from}: 584 default: 585 } 586 } 587 } 588 } 589 590 func (t *udp) handlePacket(from *net.UDPAddr, buf []byte) error { 591 packet, fromKey, hash, err := decodePacket(buf) 592 if err != nil { 593 log.Debug("Bad discv4 packet", "addr", from, "err", err) 594 return err 595 } 596 fromID := fromKey.id() 597 if err == nil { 598 err = packet.preverify(t, from, fromID, fromKey) 599 } 600 log.Trace("<< "+packet.name(), "id", fromID, "addr", from, "err", err) 601 if err == nil { 602 packet.handle(t, from, fromID, hash) 603 } 604 return err 605 } 606 607 func decodePacket(buf []byte) (packet, encPubkey, []byte, error) { 608 if len(buf) < headSize+1 { 609 return nil, encPubkey{}, nil, errPacketTooSmall 610 } 611 hash, sig, sigdata := buf[:macSize], buf[macSize:headSize], buf[headSize:] 612 shouldhash := crypto.Keccak256(buf[macSize:]) 613 if !bytes.Equal(hash, shouldhash) { 614 return nil, encPubkey{}, nil, errBadHash 615 } 616 fromKey, err := recoverNodeKey(crypto.Keccak256(buf[headSize:]), sig) 617 if err != nil { 618 return nil, fromKey, hash, err 619 } 620 621 var req packet 622 switch ptype := sigdata[0]; ptype { 623 case pingXDC: 624 req = new(ping) 625 case pongPacket: 626 req = new(pong) 627 case findnodePacket: 628 req = new(findnode) 629 case neighborsPacket: 630 req = new(neighbors) 631 default: 632 return nil, fromKey, hash, fmt.Errorf("unknown type: %d", ptype) 633 } 634 s := rlp.NewStream(bytes.NewReader(sigdata[1:]), 0) 635 err = s.Decode(req) 636 return req, fromKey, hash, err 637 } 638 639 // Packet Handlers 640 641 func (req *ping) preverify(t *udp, from *net.UDPAddr, fromID enode.ID, fromKey encPubkey) error { 642 if expired(req.Expiration) { 643 return errExpired 644 } 645 key, err := decodePubkey(fromKey) 646 if err != nil { 647 return errors.New("invalid public key") 648 } 649 req.senderKey = key 650 return nil 651 } 652 653 func (req *ping) handle(t *udp, from *net.UDPAddr, fromID enode.ID, mac []byte) { 654 // Reply. 655 t.send(from, fromID, pongPacket, &pong{ 656 To: makeEndpoint(from, req.From.TCP), 657 ReplyTok: mac, 658 Expiration: uint64(time.Now().Add(expiration).Unix()), 659 }) 660 661 // Ping back if our last pong on file is too far in the past. 662 n := wrapNode(enode.NewV4(req.senderKey, from.IP, int(req.From.TCP), from.Port)) 663 if time.Since(t.db.LastPongReceived(n.ID(), from.IP)) > bondExpiration { 664 t.sendPing(fromID, from, func() { 665 t.tab.addVerifiedNode(n) 666 }) 667 } else { 668 t.tab.addVerifiedNode(n) 669 } 670 671 // Update node database and endpoint predictor. 672 t.db.UpdateLastPingReceived(n.ID(), from.IP, time.Now()) 673 t.localNode.UDPEndpointStatement(from, &net.UDPAddr{IP: req.To.IP, Port: int(req.To.UDP)}) 674 } 675 676 func (req *ping) name() string { return "PING XDC/v4" } 677 678 func (req *pong) preverify(t *udp, from *net.UDPAddr, fromID enode.ID, fromKey encPubkey) error { 679 if expired(req.Expiration) { 680 return errExpired 681 } 682 if !t.handleReply(fromID, from.IP, pongPacket, req) { 683 return errUnsolicitedReply 684 } 685 return nil 686 } 687 688 func (req *pong) handle(t *udp, from *net.UDPAddr, fromID enode.ID, mac []byte) { 689 t.localNode.UDPEndpointStatement(from, &net.UDPAddr{IP: req.To.IP, Port: int(req.To.UDP)}) 690 t.db.UpdateLastPongReceived(fromID, from.IP, time.Now()) 691 } 692 693 func (req *pong) name() string { return "PONG/v4" } 694 695 func (req *findnode) preverify(t *udp, from *net.UDPAddr, fromID enode.ID, fromKey encPubkey) error { 696 if expired(req.Expiration) { 697 return errExpired 698 } 699 if time.Since(t.db.LastPongReceived(fromID, from.IP)) > bondExpiration { 700 // No endpoint proof pong exists, we don't process the packet. This prevents an 701 // attack vector where the discovery protocol could be used to amplify traffic in a 702 // DDOS attack. A malicious actor would send a findnode request with the IP address 703 // and UDP port of the target as the source address. The recipient of the findnode 704 // packet would then send a neighbors packet (which is a much bigger packet than 705 // findnode) to the victim. 706 return errUnknownNode 707 } 708 return nil 709 } 710 711 func (req *findnode) handle(t *udp, from *net.UDPAddr, fromID enode.ID, mac []byte) { 712 // Determine closest nodes. 713 target := enode.ID(crypto.Keccak256Hash(req.Target[:])) 714 t.tab.mutex.Lock() 715 closest := t.tab.closest(target, bucketSize).entries 716 t.tab.mutex.Unlock() 717 log.Trace("find neighbors ", "from", from, "fromID", fromID, "closest", len(closest)) 718 719 // Send neighbors in chunks with at most maxNeighbors per packet 720 // to stay below the 1280 byte limit. 721 p := neighbors{Expiration: uint64(time.Now().Add(expiration).Unix())} 722 var sent bool 723 for _, n := range closest { 724 if netutil.CheckRelayIP(from.IP, n.IP()) == nil { 725 p.Nodes = append(p.Nodes, nodeToRPC(n)) 726 } 727 if len(p.Nodes) == maxNeighbors { 728 t.send(from, fromID, neighborsPacket, &p) 729 p.Nodes = p.Nodes[:0] 730 sent = true 731 } 732 } 733 if len(p.Nodes) > 0 || !sent { 734 t.send(from, fromID, neighborsPacket, &p) 735 } 736 } 737 738 func (req *findnode) name() string { return "FINDNODE/v4" } 739 740 func (req *neighbors) preverify(t *udp, from *net.UDPAddr, fromID enode.ID, fromKey encPubkey) error { 741 if expired(req.Expiration) { 742 return errExpired 743 } 744 if !t.handleReply(fromID, from.IP, neighborsPacket, req) { 745 return errUnsolicitedReply 746 } 747 return nil 748 } 749 750 func (req *neighbors) handle(t *udp, from *net.UDPAddr, fromID enode.ID, mac []byte) { 751 } 752 753 func (req *neighbors) name() string { return "NEIGHBORS/v4" } 754 755 func expired(ts uint64) bool { 756 return time.Unix(int64(ts), 0).Before(time.Now()) 757 }