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