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