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