diff --git a/internal/stream/ssl.go b/internal/stream/ssl.go deleted file mode 100644 index e4b340e..0000000 --- a/internal/stream/ssl.go +++ /dev/null @@ -1,40 +0,0 @@ -// Package stream 提供 TCP/UDP Stream 代理功能。 -// -// 该文件实现 Stream 模块的 SSL/TLS 支持,包括: -// - 服务端 TLS 终端 -// - 客户端 TLS 连接(上游 SSL) -// - 证书加载和配置 -// - mTLS 客户端证书验证 -// -// 作者:xfy -package stream - -import ( - "crypto/tls" - "crypto/x509" - "sync" - - "rua.plus/lolly/internal/config" -) - -// SSLManager 管理 Stream SSL/TLS 配置。 -// -// 负责加载证书、配置 TLS 连接,支持服务端和客户端两种模式。 -type SSLManager struct { - cert tls.Certificate - clientCAPool *x509.CertPool - config config.StreamSSLConfig - mu sync.RWMutex -} - -// ProxySSLManager 管理上游 SSL 连接。 -// -// 负责创建到上游服务器的 TLS 连接,支持证书验证和客户端证书。 -type ProxySSLManager struct { - cert tls.Certificate - rootCAPool *x509.CertPool - config config.StreamProxySSLConfig - mu sync.RWMutex -} - - diff --git a/internal/stream/ssl_test.go b/internal/stream/ssl_test.go deleted file mode 100644 index f57140a..0000000 --- a/internal/stream/ssl_test.go +++ /dev/null @@ -1,195 +0,0 @@ -// Package stream 提供 TCP/UDP Stream 代理功能。 -// -// 该文件包含 Stream SSL/TLS 支持的单元测试。 -// -// 作者:xfy -package stream - -import ( - "crypto/rand" - "crypto/rsa" - "crypto/tls" - "crypto/x509" - "encoding/pem" - "math/big" - "os" - "path/filepath" - "testing" - "time" - - "rua.plus/lolly/internal/sslutil" -) - -// generateTestCertificate 生成测试用的自签名证书 -func generateTestCertificate(t *testing.T, certFile, keyFile string) { - t.Helper() - - // 创建证书模板 - template := &x509.Certificate{ - SerialNumber: big.NewInt(1), - NotBefore: time.Now(), - NotAfter: time.Now().Add(24 * time.Hour), - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - BasicConstraintsValid: true, - DNSNames: []string{"localhost"}, - } - - // 生成私钥和证书 - key, err := rsa.GenerateKey(rand.Reader, 2048) - if err != nil { - t.Fatalf("Failed to generate key: %v", err) - } - - certDER, err := x509.CreateCertificate(rand.Reader, template, template, &key.PublicKey, key) - if err != nil { - t.Fatalf("Failed to create certificate: %v", err) - } - - // 写入证书文件 - certOut, err := os.Create(certFile) - if err != nil { - t.Fatalf("Failed to create cert file: %v", err) - } - defer func() { _ = certOut.Close() }() - if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: certDER}); err != nil { - t.Fatalf("Failed to encode certificate: %v", err) - } - - // 写入私钥文件 - keyOut, err := os.Create(keyFile) - if err != nil { - t.Fatalf("Failed to create key file: %v", err) - } - defer func() { _ = keyOut.Close() }() - if err := pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)}); err != nil { - t.Fatalf("Failed to encode key: %v", err) - } -} - - - - - - - - - - - - - -func TestParseMinTLSVersion(t *testing.T) { - tests := []struct { - protocols []string - wantVersion uint16 - }{ - {[]string{"TLSv1.3"}, tls.VersionTLS13}, - {[]string{"TLSv1.2"}, tls.VersionTLS12}, - {[]string{"TLSv1.2", "TLSv1.3"}, tls.VersionTLS12}, - {[]string{}, tls.VersionTLS12}, - {[]string{"Unknown"}, tls.VersionTLS12}, - } - - for _, tt := range tests { - got := sslutil.ParseMinTLSVersion(tt.protocols) - if got != tt.wantVersion { - t.Errorf("parseMinTLSVersion(%v) = %v, want %v", tt.protocols, got, tt.wantVersion) - } - } -} - -func TestParseCipherSuites(t *testing.T) { - tests := []struct { - name string - ciphers []string - wantLen int - }{ - { - name: "valid ciphers", - ciphers: []string{"ECDHE-RSA-AES128-GCM-SHA256", "ECDHE-RSA-AES256-GCM-SHA384"}, - wantLen: 2, - }, - { - name: "empty ciphers", - ciphers: []string{}, - wantLen: 0, // returns nil for empty - }, - { - name: "unknown ciphers", - ciphers: []string{"UNKNOWN-CIPHER"}, - wantLen: 0, // returns nil for no valid ciphers - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := sslutil.ParseCipherSuitesLenient(tt.ciphers) - if tt.wantLen == 0 && got != nil { - t.Errorf("Expected nil, got %v", got) - } else if tt.wantLen > 0 && len(got) != tt.wantLen { - t.Errorf("Expected %d ciphers, got %d", tt.wantLen, len(got)) - } - }) - } -} - -func TestLoadCertPool(t *testing.T) { - t.Run("valid cert", func(t *testing.T) { - tempDir := t.TempDir() - certFile := filepath.Join(tempDir, "ca.crt") - - // 创建证书 - template := &x509.Certificate{ - SerialNumber: big.NewInt(1), - NotBefore: time.Now(), - NotAfter: time.Now().Add(24 * time.Hour), - IsCA: true, - KeyUsage: x509.KeyUsageCertSign, - } - - key, _ := rsa.GenerateKey(rand.Reader, 2048) - certDER, _ := x509.CreateCertificate(rand.Reader, template, template, &key.PublicKey, key) - - certOut, err := os.Create(certFile) - if err != nil { - t.Fatalf("Failed to create cert file: %v", err) - } - defer func() { _ = certOut.Close() }() - if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: certDER}); err != nil { - t.Fatalf("Failed to encode certificate: %v", err) - } - - pool, err := sslutil.LoadCertPool(certFile, "test") - if err != nil { - t.Fatalf("loadCertPool failed: %v", err) - } - if pool == nil { - t.Error("Expected non-nil pool") - } - }) - - t.Run("invalid path", func(t *testing.T) { - _, err := sslutil.LoadCertPool("/nonexistent/cert.pem", "test") - if err == nil { - t.Error("Expected error for nonexistent file") - } - }) - - t.Run("invalid content", func(t *testing.T) { - tempDir := t.TempDir() - certFile := filepath.Join(tempDir, "invalid.crt") - if err := os.WriteFile(certFile, []byte("not a certificate"), 0o644); err != nil { - t.Fatalf("写入无效证书文件失败: %v", err) - } - - _, err := sslutil.LoadCertPool(certFile, "test") - if err == nil { - t.Error("Expected error for invalid certificate content") - } - }) -} - - - -