| 3628 | } |
| 3629 | |
| 3630 | func TestTLSEOFAfterHandshakeBrokenPipe(t *testing.T) { |
| 3631 | // Simulate a scenario where the server does a hard close (TCP RST) |
| 3632 | // after TLS handshake, which can cause "broken pipe" or |
| 3633 | // "connection reset by peer" on the client side. |
| 3634 | |
| 3635 | tc := &server.TLSConfigOpts{ |
| 3636 | CertFile: "./configs/certs/server.pem", |
| 3637 | KeyFile: "./configs/certs/key.pem", |
| 3638 | } |
| 3639 | tlsConf, err := server.GenTLSConfig(tc) |
| 3640 | if err != nil { |
| 3641 | t.Fatalf("Can't build TLSConfig: %v", err) |
| 3642 | } |
| 3643 | tlsConf.ServerName = "localhost" |
| 3644 | |
| 3645 | l, err := net.Listen("tcp", "127.0.0.1:0") |
| 3646 | if err != nil { |
| 3647 | t.Fatalf("Could not listen: %v", err) |
| 3648 | } |
| 3649 | defer l.Close() |
| 3650 | |
| 3651 | addr := l.Addr().(*net.TCPAddr) |
| 3652 | |
| 3653 | go func() { |
| 3654 | conn, err := l.Accept() |
| 3655 | if err != nil { |
| 3656 | return |
| 3657 | } |
| 3658 | |
| 3659 | // Send INFO with tls_required. |
| 3660 | info := fmt.Sprintf("INFO {\"server_id\":\"test\",\"host\":\"localhost\",\"port\":%d,\"tls_required\":true,\"tls_available\":true,\"max_payload\":1048576}\r\n", addr.Port) |
| 3661 | conn.Write([]byte(info)) |
| 3662 | |
| 3663 | // Upgrade to TLS. |
| 3664 | tlsConn := tls.Server(conn, tlsConf) |
| 3665 | if err := tlsConn.Handshake(); err != nil { |
| 3666 | conn.Close() |
| 3667 | return |
| 3668 | } |
| 3669 | |
| 3670 | // Force a TCP RST by setting linger to 0 then closing. |
| 3671 | // This causes "connection reset by peer" on the client |
| 3672 | // instead of a graceful EOF. |
| 3673 | if tcpConn, ok := conn.(*net.TCPConn); ok { |
| 3674 | tcpConn.SetLinger(0) |
| 3675 | } |
| 3676 | conn.Close() |
| 3677 | }() |
| 3678 | |
| 3679 | _, err = nats.Connect( |
| 3680 | fmt.Sprintf("nats://localhost:%d", addr.Port), |
| 3681 | nats.RootCAs("./configs/certs/ca.pem"), |
| 3682 | ) |
| 3683 | if err == nil { |
| 3684 | t.Fatal("Expected error, got nil") |
| 3685 | } |
| 3686 | if !errors.Is(err, nats.ErrTLS) { |
| 3687 | t.Fatalf("Expected error to wrap nats.ErrTLS, got: %v", err) |