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