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