// Package ssl 提供 SSL/TLS 性能基准测试。 // // 测试覆盖: // - TLS 握手性能(模拟客户端握手) // - 证书加载性能 // - 重新协商开销 // - OCSP 装订性能 // - 会话恢复性能(使用 session ticket) // // 作者:xfy package ssl import ( "crypto/tls" "os" "testing" "time" "rua.plus/lolly/internal/config" "rua.plus/lolly/internal/sslutil" ) // BenchmarkTLSHandshake 基准测试 TLS 握手性能。 // // 使用本地 TCP 环回连接模拟真实客户端握手, // 测量完整 TLS 握手(包括密钥交换和证书验证)的开销。 func BenchmarkTLSHandshake(b *testing.B) { tmpDir := b.TempDir() certPEM, keyPEM := generateTestCert(&testing.T{}) certPath := tmpDir + "/cert.pem" keyPath := tmpDir + "/key.pem" if err := os.WriteFile(certPath, certPEM, 0o644); err != nil { b.Fatalf("write cert: %v", err) } if err := os.WriteFile(keyPath, keyPEM, 0o600); err != nil { b.Fatalf("write key: %v", err) } cfg := &config.SSLConfig{ Cert: certPath, Key: keyPath, Protocols: []string{"TLSv1.2", "TLSv1.3"}, } manager, err := NewTLSManager(cfg) if err != nil { b.Fatalf("NewTLSManager() failed: %v", err) } defer manager.Close() serverTLS := manager.GetTLSConfig() listener, err := tls.Listen("tcp", "127.0.0.1:0", serverTLS) if err != nil { b.Fatalf("tls.Listen failed: %v", err) } defer listener.Close() // 后台接受连接 go func() { for { conn, err := listener.Accept() if err != nil { return } // 读取少量数据以完成握手 buf := make([]byte, 1) _, _ = conn.Read(buf) _ = conn.Close() } }() clientTLS := &tls.Config{ InsecureSkipVerify: true, MinVersion: tls.VersionTLS12, } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { conn, err := tls.Dial("tcp", listener.Addr().String(), clientTLS) if err != nil { b.Error(err) continue } _, _ = conn.Write([]byte{0}) _ = conn.Close() } }) } // BenchmarkTLSHandshake_TLS13Only 基准测试仅 TLS 1.3 的握手性能。 // // TLS 1.3 握手比 TLS 1.2 更快(1-RTT),测量两者的差异。 func BenchmarkTLSHandshake_TLS13Only(b *testing.B) { tmpDir := b.TempDir() certPEM, keyPEM := generateTestCert(&testing.T{}) certPath := tmpDir + "/cert.pem" keyPath := tmpDir + "/key.pem" if err := os.WriteFile(certPath, certPEM, 0o644); err != nil { b.Fatalf("write cert: %v", err) } if err := os.WriteFile(keyPath, keyPEM, 0o600); err != nil { b.Fatalf("write key: %v", err) } cfg := &config.SSLConfig{ Cert: certPath, Key: keyPath, Protocols: []string{"TLSv1.3"}, } manager, err := NewTLSManager(cfg) if err != nil { b.Fatalf("NewTLSManager() failed: %v", err) } defer manager.Close() serverTLS := manager.GetTLSConfig() listener, err := tls.Listen("tcp", "127.0.0.1:0", serverTLS) if err != nil { b.Fatalf("tls.Listen failed: %v", err) } defer listener.Close() go func() { for { conn, err := listener.Accept() if err != nil { return } buf := make([]byte, 1) _, _ = conn.Read(buf) _ = conn.Close() } }() clientTLS := &tls.Config{ InsecureSkipVerify: true, MinVersion: tls.VersionTLS13, MaxVersion: tls.VersionTLS13, } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { conn, err := tls.Dial("tcp", listener.Addr().String(), clientTLS) if err != nil { b.Error(err) continue } _, _ = conn.Write([]byte{0}) _ = conn.Close() } }) } // BenchmarkTLSCertificateLoad 基准测试证书加载性能。 // // 测量从磁盘加载 X509 密钥对的开销,包括 PEM 解码和 // 私钥解析。 func BenchmarkTLSCertificateLoad(b *testing.B) { tmpDir := b.TempDir() certPEM, keyPEM := generateTestCert(&testing.T{}) certPath := tmpDir + "/cert.pem" keyPath := tmpDir + "/key.pem" if err := os.WriteFile(certPath, certPEM, 0o644); err != nil { b.Fatalf("write cert: %v", err) } if err := os.WriteFile(keyPath, keyPEM, 0o600); err != nil { b.Fatalf("write key: %v", err) } b.ResetTimer() for b.Loop() { _, err := tls.LoadX509KeyPair(certPath, keyPath) if err != nil { b.Fatal(err) } } } // BenchmarkTLSCertificateLoad_InMemory 基准测试内存中证书加载性能。 // // 不经过磁盘 I/O,直接测量 PEM 解析和证书构建的开销。 func BenchmarkTLSCertificateLoad_InMemory(b *testing.B) { certPEM, keyPEM := generateTestCert(&testing.T{}) b.ResetTimer() for b.Loop() { _, err := tls.X509KeyPair(certPEM, keyPEM) if err != nil { b.Fatal(err) } } } // BenchmarkTLSCertificateLoad_Parallel 基准测试并发证书加载性能。 // // 模拟多协程同时加载证书的场景,验证线程安全性。 func BenchmarkTLSCertificateLoad_Parallel(b *testing.B) { tmpDir := b.TempDir() certPEM, keyPEM := generateTestCert(&testing.T{}) certPath := tmpDir + "/cert.pem" keyPath := tmpDir + "/key.pem" if err := os.WriteFile(certPath, certPEM, 0o644); err != nil { b.Fatalf("write cert: %v", err) } if err := os.WriteFile(keyPath, keyPEM, 0o600); err != nil { b.Fatalf("write key: %v", err) } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _, err := tls.LoadX509KeyPair(certPath, keyPath) if err != nil { b.Error(err) } } }) } // BenchmarkTLSRenegotiation 基准测试 TLS 重新协商开销。 // // TLS 1.3 已移除重新协商,该测试测量 TLS 1.2 下的 // 重新协商成本,用于评估是否值得启用重新协商。 // 通过建立 TLS 1.2 连接并检查握手统计来测量开销。 func BenchmarkTLSRenegotiation(b *testing.B) { tmpDir := b.TempDir() certPEM, keyPEM := generateTestCert(&testing.T{}) certPath := tmpDir + "/cert.pem" keyPath := tmpDir + "/key.pem" if err := os.WriteFile(certPath, certPEM, 0o644); err != nil { b.Fatalf("write cert: %v", err) } if err := os.WriteFile(keyPath, keyPEM, 0o600); err != nil { b.Fatalf("write key: %v", err) } cert, err := tls.LoadX509KeyPair(certPath, keyPath) if err != nil { b.Fatalf("tls.LoadX509KeyPair failed: %v", err) } serverTLS := &tls.Config{ Certificates: []tls.Certificate{cert}, MinVersion: tls.VersionTLS12, MaxVersion: tls.VersionTLS12, } listener, err := tls.Listen("tcp", "127.0.0.1:0", serverTLS) if err != nil { b.Fatalf("tls.Listen failed: %v", err) } defer listener.Close() // 服务端接受连接 acceptDone := make(chan struct{}) go func() { defer close(acceptDone) for { conn, err := listener.Accept() if err != nil { return } // 读取数据完成握手后关闭 buf := make([]byte, 1) _, _ = conn.Read(buf) _ = conn.Close() } }() clientTLS := &tls.Config{ InsecureSkipVerify: true, MinVersion: tls.VersionTLS12, MaxVersion: tls.VersionTLS12, Renegotiation: tls.RenegotiateOnceAsClient, } b.ResetTimer() for b.Loop() { conn, err := tls.Dial("tcp", listener.Addr().String(), clientTLS) if err != nil { b.Fatalf("Dial failed: %v", err) } _, _ = conn.Write([]byte{0}) _ = conn.Close() } b.StopTimer() listener.Close() <-acceptDone } // BenchmarkOCSPStapling 基准测试 OCSP 装订性能。 // // 测量启用 OCSP Stapling 后,GetConfigForClient 回调中 // 获取和附加 OCSP 响应的开销。 func BenchmarkOCSPStapling(b *testing.B) { // 直接测试 OCSPManager 的响应获取性能 // (自签证书没有 OCSP Server URL,无法端到端测试) ocspMgr := NewOCSPManager(DefaultOCSPConfig()) ocspMgr.Start() defer ocspMgr.Stop() // 注册一个模拟序列号的状态 testSerial := "1234567890" ocspMgr.mu.Lock() ocspMgr.responses[testSerial] = &ocspResponse{ response: make([]byte, 1024), thisUpdate: time.Now(), nextUpdate: time.Now().Add(time.Hour), status: statusValid, fetchedAt: time.Now(), errors: 0, } ocspMgr.mu.Unlock() b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { resp := ocspMgr.GetOCSPResponse(testSerial) if resp == nil { b.Error("expected non-nil OCSP response") } } }) } // BenchmarkOCSPStapling_Miss 基准测试 OCSP 未命中性能。 // // 测量查询不存在序列号时的开销,验证优雅降级不影响性能。 func BenchmarkOCSPStapling_Miss(b *testing.B) { ocspMgr := NewOCSPManager(DefaultOCSPConfig()) ocspMgr.Start() defer ocspMgr.Stop() nonExistentSerial := "nonexistent" b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { resp := ocspMgr.GetOCSPResponse(nonExistentSerial) if resp != nil { b.Error("expected nil OCSP response for non-existent serial") } } }) } // BenchmarkOCSPStapling_GetStatus 基准测试 OCSP 状态查询性能。 // // 测量 GetStatus 方法获取证书状态信息的开销。 // BenchmarkSessionResumption 基准测试使用 Session Ticket 的会话恢复性能。 // // 使用 ClientSessionCache 实现会话恢复, // 测量使用缓存 session 时的握手开销。 // BenchmarkSessionResumption_FullHandshake 基准测试完整握手(无会话恢复)。 // // 作为对照组,测量没有 session ticket 的完整 TLS 握手开销, // 与 BenchmarkSessionResumption 对比评估会话恢复的性能提升。 // BenchmarkSessionTicketManager_ApplyToTLSConfig 基准测试应用 Session Ticket 到 TLS 配置的开销。 func BenchmarkSessionTicketManager_ApplyToTLSConfig(b *testing.B) { sessionMgr, err := NewSessionTicketManager(config.SessionTicketsConfig{ Enabled: true, RotateInterval: time.Hour, RetainKeys: 3, }) if err != nil { b.Fatalf("NewSessionTicketManager failed: %v", err) } defer sessionMgr.Stop() for range 2 { _ = sessionMgr.RotateKey() } baseTLS := &tls.Config{ Certificates: []tls.Certificate{}, MinVersion: tls.VersionTLS12, } b.ResetTimer() for b.Loop() { tlsCfg := baseTLS.Clone() sessionMgr.ApplyToTLSConfig(tlsCfg) } } // BenchmarkSNI_GetCertificate 基准测试 SNI 证书查找性能。 // // 测量 GetCertificate 回调在多证书场景下的查找开销。 // BenchmarkCipherSuiteParsing 基准测试加密套件解析性能。 func BenchmarkCipherSuiteParsing(b *testing.B) { ciphers := []string{ "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", } b.ResetTimer() for b.Loop() { _, err := sslutil.ParseCipherSuites(ciphers) if err != nil { b.Fatal(err) } } } // BenchmarkTLSVersionsParsing 基准测试 TLS 版本解析性能。 func BenchmarkTLSVersionsParsing(b *testing.B) { protocols := []string{"TLSv1.2", "TLSv1.3"} b.ResetTimer() for b.Loop() { _, _, err := sslutil.ParseTLSVersions(protocols) if err != nil { b.Fatal(err) } } }