github.com/core-coin/go-core/v2@v2.1.9/p2p/server_test.go (about) 1 // Copyright 2014 by the Authors 2 // This file is part of the go-core library. 3 // 4 // The go-core 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-core 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-core library. If not, see <http://www.gnu.org/licenses/>. 16 17 package p2p 18 19 import ( 20 crand "crypto/rand" 21 "errors" 22 "io" 23 "math/rand" 24 "net" 25 "reflect" 26 "testing" 27 "time" 28 29 "golang.org/x/crypto/sha3" 30 31 "github.com/core-coin/go-core/v2/crypto" 32 "github.com/core-coin/go-core/v2/internal/testlog" 33 "github.com/core-coin/go-core/v2/log" 34 "github.com/core-coin/go-core/v2/p2p/enode" 35 "github.com/core-coin/go-core/v2/p2p/enr" 36 "github.com/core-coin/go-core/v2/p2p/rlpx" 37 ) 38 39 type testTransport struct { 40 *rlpxTransport 41 rpub *crypto.PublicKey 42 closeErr error 43 } 44 45 func newTestTransport(rpub *crypto.PublicKey, fd net.Conn, dialDest *crypto.PublicKey) transport { 46 wrapped := newRLPX(fd, dialDest).(*rlpxTransport) 47 wrapped.conn.InitWithSecrets(rlpx.Secrets{ 48 AES: make([]byte, 16), 49 MAC: make([]byte, 16), 50 EgressMAC: sha3.New256(), 51 IngressMAC: sha3.New256(), 52 }) 53 return &testTransport{rpub: rpub, rlpxTransport: wrapped} 54 } 55 56 func (c *testTransport) doEncHandshake(prv *crypto.PrivateKey) (*crypto.PublicKey, error) { 57 return c.rpub, nil 58 } 59 60 func (c *testTransport) doProtoHandshake(our *protoHandshake) (*protoHandshake, error) { 61 return &protoHandshake{ID: c.rpub[:], Name: "test"}, nil 62 } 63 64 func (c *testTransport) close(err error) { 65 c.conn.Close() 66 c.closeErr = err 67 } 68 69 func startTestServer(t *testing.T, remoteKey *crypto.PublicKey, pf func(*Peer)) *Server { 70 config := Config{ 71 Name: "test", 72 MaxPeers: 10, 73 ListenAddr: "127.0.0.1:0", 74 NoDiscovery: true, 75 PrivateKey: newkey(), 76 Logger: testlog.Logger(t, log.LvlTrace), 77 } 78 server := &Server{ 79 Config: config, 80 newPeerHook: pf, 81 newTransport: func(fd net.Conn, dialDest *crypto.PublicKey) transport { 82 return newTestTransport(remoteKey, fd, dialDest) 83 }, 84 } 85 if err := server.Start(); err != nil { 86 t.Fatalf("Could not start server: %v", err) 87 } 88 return server 89 } 90 91 func TestServerListen(t *testing.T) { 92 // start the test server 93 connected := make(chan *Peer) 94 key := newkey() 95 srv := startTestServer(t, key.PublicKey(), func(p *Peer) { 96 if p.ID() != enode.PubkeyToIDV4(key.PublicKey()) { 97 t.Error("peer func called with wrong node id") 98 } 99 connected <- p 100 }) 101 defer close(connected) 102 defer srv.Stop() 103 104 // dial the test server 105 conn, err := net.DialTimeout("tcp", srv.ListenAddr, 5*time.Second) 106 if err != nil { 107 t.Fatalf("could not dial: %v", err) 108 } 109 defer conn.Close() 110 111 select { 112 case peer := <-connected: 113 if peer.LocalAddr().String() != conn.RemoteAddr().String() { 114 t.Errorf("peer started with wrong conn: got %v, want %v", 115 peer.LocalAddr(), conn.RemoteAddr()) 116 } 117 peers := srv.Peers() 118 if !reflect.DeepEqual(peers, []*Peer{peer}) { 119 t.Errorf("Peers mismatch: got %v, want %v", peers, []*Peer{peer}) 120 } 121 case <-time.After(1 * time.Second): 122 t.Error("server did not accept within one second") 123 } 124 } 125 126 func TestServerDial(t *testing.T) { 127 // run a one-shot TCP server to handle the connection. 128 listener, err := net.Listen("tcp", "127.0.0.1:0") 129 if err != nil { 130 t.Fatalf("could not setup listener: %v", err) 131 } 132 defer listener.Close() 133 accepted := make(chan net.Conn, 1) 134 go func() { 135 conn, err := listener.Accept() 136 if err != nil { 137 return 138 } 139 accepted <- conn 140 }() 141 142 // start the server 143 connected := make(chan *Peer) 144 key := newkey() 145 srv := startTestServer(t, key.PublicKey(), func(p *Peer) { connected <- p }) 146 defer close(connected) 147 defer srv.Stop() 148 149 // tell the server to connect 150 tcpAddr := listener.Addr().(*net.TCPAddr) 151 node := enode.NewV4(key.PublicKey(), tcpAddr.IP, tcpAddr.Port, 0) 152 srv.AddPeer(node) 153 154 select { 155 case conn := <-accepted: 156 defer conn.Close() 157 158 select { 159 case peer := <-connected: 160 if peer.ID() != enode.PubkeyToIDV4(key.PublicKey()) { 161 t.Errorf("peer has wrong id") 162 } 163 if peer.Name() != "test" { 164 t.Errorf("peer has wrong name") 165 } 166 if peer.RemoteAddr().String() != conn.LocalAddr().String() { 167 t.Errorf("peer started with wrong conn: got %v, want %v", 168 peer.RemoteAddr(), conn.LocalAddr()) 169 } 170 peers := srv.Peers() 171 if !reflect.DeepEqual(peers, []*Peer{peer}) { 172 t.Errorf("Peers mismatch: got %v, want %v", peers, []*Peer{peer}) 173 } 174 175 // Test AddTrustedPeer/RemoveTrustedPeer and changing Trusted flags 176 // Particularly for race conditions on changing the flag state. 177 if peer := srv.Peers()[0]; peer.Info().Network.Trusted { 178 t.Errorf("peer is trusted prematurely: %v", peer) 179 } 180 done := make(chan bool) 181 go func() { 182 srv.AddTrustedPeer(node) 183 if peer := srv.Peers()[0]; !peer.Info().Network.Trusted { 184 t.Errorf("peer is not trusted after AddTrustedPeer: %v", peer) 185 } 186 srv.RemoveTrustedPeer(node) 187 if peer := srv.Peers()[0]; peer.Info().Network.Trusted { 188 t.Errorf("peer is trusted after RemoveTrustedPeer: %v", peer) 189 } 190 done <- true 191 }() 192 // Trigger potential race conditions 193 peer = srv.Peers()[0] 194 _ = peer.Inbound() 195 _ = peer.Info() 196 <-done 197 case <-time.After(1 * time.Second): 198 t.Error("server did not launch peer within one second") 199 } 200 201 case <-time.After(1 * time.Second): 202 t.Error("server did not connect within one second") 203 } 204 } 205 206 // This test checks that RemovePeer disconnects the peer if it is connected. 207 func TestServerRemovePeerDisconnect(t *testing.T) { 208 srv1 := &Server{Config: Config{ 209 PrivateKey: newkey(), 210 MaxPeers: 1, 211 NoDiscovery: true, 212 Logger: testlog.Logger(t, log.LvlTrace).New("server", "1"), 213 }} 214 srv2 := &Server{Config: Config{ 215 PrivateKey: newkey(), 216 MaxPeers: 1, 217 NoDiscovery: true, 218 NoDial: true, 219 ListenAddr: "127.0.0.1:0", 220 Logger: testlog.Logger(t, log.LvlTrace).New("server", "2"), 221 }} 222 srv1.Start() 223 defer srv1.Stop() 224 srv2.Start() 225 defer srv2.Stop() 226 227 if !syncAddPeer(srv1, srv2.Self()) { 228 t.Fatal("peer not connected") 229 } 230 srv1.RemovePeer(srv2.Self()) 231 if srv1.PeerCount() > 0 { 232 t.Fatal("removed peer still connected") 233 } 234 } 235 236 // This test checks that connections are disconnected just after the encryption handshake 237 // when the server is at capacity. Trusted connections should still be accepted. 238 func TestServerAtCap(t *testing.T) { 239 trustedNode := newkey() 240 trustedID := enode.PubkeyToIDV4(trustedNode.PublicKey()) 241 srv := &Server{ 242 Config: Config{ 243 PrivateKey: newkey(), 244 MaxPeers: 10, 245 NoDial: true, 246 NoDiscovery: true, 247 TrustedNodes: []*enode.Node{newNode(trustedID, "")}, 248 Logger: testlog.Logger(t, log.LvlTrace), 249 }, 250 } 251 if err := srv.Start(); err != nil { 252 t.Fatalf("could not start: %v", err) 253 } 254 defer srv.Stop() 255 256 newconn := func(id enode.ID) *conn { 257 fd, _ := net.Pipe() 258 tx := newTestTransport(trustedNode.PublicKey(), fd, nil) 259 node := enode.SignNull(new(enr.Record), id) 260 return &conn{fd: fd, transport: tx, flags: inboundConn, node: node, cont: make(chan error)} 261 } 262 263 // Inject a few connections to fill up the peer set. 264 for i := 0; i < 10; i++ { 265 c := newconn(randomID()) 266 if err := srv.checkpoint(c, srv.checkpointAddPeer); err != nil { 267 t.Fatalf("could not add conn %d: %v", i, err) 268 } 269 } 270 // Try inserting a non-trusted connection. 271 anotherID := randomID() 272 c := newconn(anotherID) 273 if err := srv.checkpoint(c, srv.checkpointPostHandshake); err != DiscTooManyPeers { 274 t.Error("wrong error for insert:", err) 275 } 276 // Try inserting a trusted connection. 277 c = newconn(trustedID) 278 if err := srv.checkpoint(c, srv.checkpointPostHandshake); err != nil { 279 t.Error("unexpected error for trusted conn @posthandshake:", err) 280 } 281 if !c.is(trustedConn) { 282 t.Error("Server did not set trusted flag") 283 } 284 285 // Remove from trusted set and try again 286 srv.RemoveTrustedPeer(newNode(trustedID, "")) 287 c = newconn(trustedID) 288 if err := srv.checkpoint(c, srv.checkpointPostHandshake); err != DiscTooManyPeers { 289 t.Error("wrong error for insert:", err) 290 } 291 292 // Add anotherID to trusted set and try again 293 srv.AddTrustedPeer(newNode(anotherID, "")) 294 c = newconn(anotherID) 295 if err := srv.checkpoint(c, srv.checkpointPostHandshake); err != nil { 296 t.Error("unexpected error for trusted conn @posthandshake:", err) 297 } 298 if !c.is(trustedConn) { 299 t.Error("Server did not set trusted flag") 300 } 301 } 302 303 func TestServerPeerLimits(t *testing.T) { 304 srvkey := newkey() 305 clientkey := newkey() 306 clientnode := enode.NewV4(clientkey.PublicKey(), nil, 0, 0) 307 308 var tp = &setupTransport{ 309 pubkey: clientkey.PublicKey(), 310 phs: protoHandshake{ 311 ID: clientkey.PublicKey()[:], 312 // Force "DiscUselessPeer" due to unmatching caps 313 // Caps: []Cap{discard.cap()}, 314 }, 315 } 316 317 srv := &Server{ 318 Config: Config{ 319 PrivateKey: srvkey, 320 MaxPeers: 0, 321 NoDial: true, 322 NoDiscovery: true, 323 Protocols: []Protocol{discard}, 324 Logger: testlog.Logger(t, log.LvlTrace), 325 }, 326 newTransport: func(fd net.Conn, dialDest *crypto.PublicKey) transport { return tp }, 327 } 328 if err := srv.Start(); err != nil { 329 t.Fatalf("couldn't start server: %v", err) 330 } 331 defer srv.Stop() 332 333 // Check that server is full (MaxPeers=0) 334 flags := dynDialedConn 335 dialDest := clientnode 336 conn, _ := net.Pipe() 337 srv.SetupConn(conn, flags, dialDest) 338 if tp.closeErr != DiscTooManyPeers { 339 t.Errorf("unexpected close error: %q", tp.closeErr) 340 } 341 conn.Close() 342 343 srv.AddTrustedPeer(clientnode) 344 345 // Check that server allows a trusted peer despite being full. 346 conn, _ = net.Pipe() 347 srv.SetupConn(conn, flags, dialDest) 348 if tp.closeErr == DiscTooManyPeers { 349 t.Errorf("failed to bypass MaxPeers with trusted node: %q", tp.closeErr) 350 } 351 352 if tp.closeErr != DiscUselessPeer { 353 t.Errorf("unexpected close error: %q", tp.closeErr) 354 } 355 conn.Close() 356 357 srv.RemoveTrustedPeer(clientnode) 358 359 // Check that server is full again. 360 conn, _ = net.Pipe() 361 srv.SetupConn(conn, flags, dialDest) 362 if tp.closeErr != DiscTooManyPeers { 363 t.Errorf("unexpected close error: %q", tp.closeErr) 364 } 365 conn.Close() 366 } 367 368 func TestServerSetupConn(t *testing.T) { 369 var ( 370 clientkey, srvkey = newkey(), newkey() 371 ) 372 tests := []struct { 373 dontstart bool 374 tt *setupTransport 375 flags connFlag 376 dialDest *enode.Node 377 378 wantCloseErr error 379 wantCalls string 380 }{ 381 { 382 dontstart: true, 383 tt: &setupTransport{pubkey: clientkey.PublicKey()}, 384 wantCalls: "close,", 385 wantCloseErr: errServerStopped, 386 }, 387 { 388 tt: &setupTransport{pubkey: clientkey.PublicKey(), encHandshakeErr: errors.New("read error")}, 389 flags: inboundConn, 390 wantCalls: "doEncHandshake,close,", 391 wantCloseErr: errors.New("read error"), 392 }, 393 { 394 tt: &setupTransport{pubkey: clientkey.PublicKey(), phs: protoHandshake{ID: randomID().Bytes()}}, 395 dialDest: enode.NewV4(clientkey.PublicKey(), nil, 0, 0), 396 flags: dynDialedConn, 397 wantCalls: "doEncHandshake,doProtoHandshake,close,", 398 wantCloseErr: DiscUnexpectedIdentity, 399 }, 400 { 401 tt: &setupTransport{pubkey: clientkey.PublicKey(), protoHandshakeErr: errors.New("foo")}, 402 dialDest: enode.NewV4(clientkey.PublicKey(), nil, 0, 0), 403 flags: dynDialedConn, 404 wantCalls: "doEncHandshake,doProtoHandshake,close,", 405 wantCloseErr: errors.New("foo"), 406 }, 407 { 408 tt: &setupTransport{pubkey: srvkey.PublicKey(), phs: protoHandshake{ID: srvkey.PublicKey()[:]}}, 409 flags: inboundConn, 410 wantCalls: "doEncHandshake,close,", 411 wantCloseErr: DiscSelf, 412 }, 413 { 414 tt: &setupTransport{pubkey: clientkey.PublicKey(), phs: protoHandshake{ID: clientkey.PublicKey()[:]}}, 415 flags: inboundConn, 416 wantCalls: "doEncHandshake,doProtoHandshake,close,", 417 wantCloseErr: DiscUselessPeer, 418 }, 419 } 420 421 for i, test := range tests { 422 t.Run(test.wantCalls, func(t *testing.T) { 423 cfg := Config{ 424 PrivateKey: srvkey, 425 MaxPeers: 10, 426 NoDial: true, 427 NoDiscovery: true, 428 Protocols: []Protocol{discard}, 429 Logger: testlog.Logger(t, log.LvlTrace), 430 } 431 srv := &Server{ 432 Config: cfg, 433 newTransport: func(fd net.Conn, dialDest *crypto.PublicKey) transport { return test.tt }, 434 log: cfg.Logger, 435 } 436 if !test.dontstart { 437 if err := srv.Start(); err != nil { 438 t.Fatalf("couldn't start server: %v", err) 439 } 440 defer srv.Stop() 441 } 442 p1, _ := net.Pipe() 443 srv.SetupConn(p1, test.flags, test.dialDest) 444 if !reflect.DeepEqual(test.tt.closeErr, test.wantCloseErr) { 445 t.Errorf("test %d: close error mismatch: got %q, want %q", i, test.tt.closeErr, test.wantCloseErr) 446 } 447 if test.tt.calls != test.wantCalls { 448 t.Errorf("test %d: calls mismatch: got %q, want %q", i, test.tt.calls, test.wantCalls) 449 } 450 }) 451 } 452 } 453 454 type setupTransport struct { 455 pubkey *crypto.PublicKey 456 encHandshakeErr error 457 phs protoHandshake 458 protoHandshakeErr error 459 460 calls string 461 closeErr error 462 } 463 464 func (c *setupTransport) doEncHandshake(prv *crypto.PrivateKey) (*crypto.PublicKey, error) { 465 c.calls += "doEncHandshake," 466 return c.pubkey, c.encHandshakeErr 467 } 468 469 func (c *setupTransport) doProtoHandshake(our *protoHandshake) (*protoHandshake, error) { 470 c.calls += "doProtoHandshake," 471 if c.protoHandshakeErr != nil { 472 return nil, c.protoHandshakeErr 473 } 474 return &c.phs, nil 475 } 476 func (c *setupTransport) close(err error) { 477 c.calls += "close," 478 c.closeErr = err 479 } 480 481 // setupConn shouldn't write to/read from the connection. 482 func (c *setupTransport) WriteMsg(Msg) error { 483 panic("WriteMsg called on setupTransport") 484 } 485 func (c *setupTransport) ReadMsg() (Msg, error) { 486 panic("ReadMsg called on setupTransport") 487 } 488 489 func newkey() *crypto.PrivateKey { 490 key, err := crypto.GenerateKey(crand.Reader) 491 if err != nil { 492 panic("couldn't generate key: " + err.Error()) 493 } 494 return key 495 } 496 497 func randomID() (id enode.ID) { 498 for i := range id { 499 id[i] = byte(rand.Intn(255)) 500 } 501 return id 502 } 503 504 // This test checks that inbound connections are throttled by IP. 505 func TestServerInboundThrottle(t *testing.T) { 506 const timeout = 5 * time.Second 507 newTransportCalled := make(chan struct{}) 508 srv := &Server{ 509 Config: Config{ 510 PrivateKey: newkey(), 511 ListenAddr: "127.0.0.1:0", 512 MaxPeers: 10, 513 NoDial: true, 514 NoDiscovery: true, 515 Protocols: []Protocol{discard}, 516 Logger: testlog.Logger(t, log.LvlTrace), 517 }, 518 newTransport: func(fd net.Conn, dialDest *crypto.PublicKey) transport { 519 newTransportCalled <- struct{}{} 520 return newRLPX(fd, dialDest) 521 }, 522 listenFunc: func(network, laddr string) (net.Listener, error) { 523 fakeAddr := &net.TCPAddr{IP: net.IP{95, 33, 21, 2}, Port: 4444} 524 return listenFakeAddr(network, laddr, fakeAddr) 525 }, 526 } 527 if err := srv.Start(); err != nil { 528 t.Fatal("can't start: ", err) 529 } 530 defer srv.Stop() 531 532 // Dial the test server. 533 conn, err := net.DialTimeout("tcp", srv.ListenAddr, timeout) 534 if err != nil { 535 t.Fatalf("could not dial: %v", err) 536 } 537 select { 538 case <-newTransportCalled: 539 // OK 540 case <-time.After(timeout): 541 t.Error("newTransport not called") 542 } 543 conn.Close() 544 545 // Dial again. This time the server should close the connection immediately. 546 connClosed := make(chan struct{}, 1) 547 conn, err = net.DialTimeout("tcp", srv.ListenAddr, timeout) 548 if err != nil { 549 t.Fatalf("could not dial: %v", err) 550 } 551 defer conn.Close() 552 go func() { 553 conn.SetDeadline(time.Now().Add(timeout)) 554 buf := make([]byte, 10) 555 if n, err := conn.Read(buf); err != io.EOF || n != 0 { 556 t.Errorf("expected io.EOF and n == 0, got error %q and n == %d", err, n) 557 } 558 connClosed <- struct{}{} 559 }() 560 select { 561 case <-connClosed: 562 // OK 563 case <-newTransportCalled: 564 t.Error("newTransport called for second attempt") 565 case <-time.After(timeout): 566 t.Error("connection not closed within timeout") 567 } 568 } 569 570 func listenFakeAddr(network, laddr string, remoteAddr net.Addr) (net.Listener, error) { 571 l, err := net.Listen(network, laddr) 572 if err == nil { 573 l = &fakeAddrListener{l, remoteAddr} 574 } 575 return l, err 576 } 577 578 // fakeAddrListener is a listener that creates connections with a mocked remote address. 579 type fakeAddrListener struct { 580 net.Listener 581 remoteAddr net.Addr 582 } 583 584 type fakeAddrConn struct { 585 net.Conn 586 remoteAddr net.Addr 587 } 588 589 func (l *fakeAddrListener) Accept() (net.Conn, error) { 590 c, err := l.Listener.Accept() 591 if err != nil { 592 return nil, err 593 } 594 return &fakeAddrConn{c, l.remoteAddr}, nil 595 } 596 597 func (c *fakeAddrConn) RemoteAddr() net.Addr { 598 return c.remoteAddr 599 } 600 601 func syncAddPeer(srv *Server, node *enode.Node) bool { 602 var ( 603 ch = make(chan *PeerEvent) 604 sub = srv.SubscribeEvents(ch) 605 timeout = time.After(2 * time.Second) 606 ) 607 defer sub.Unsubscribe() 608 srv.AddPeer(node) 609 for { 610 select { 611 case ev := <-ch: 612 if ev.Type == PeerEventTypeAdd && ev.Peer == node.ID() { 613 return true 614 } 615 case <-timeout: 616 return false 617 } 618 } 619 }