diff --git a/cmd/client.go b/cmd/client.go
@@ -2,6 +2,7 @@ package cmd
import (
"crypto/x509"
+ "fmt"
"log"
"os"
@@ -28,7 +29,7 @@ func newClientCmd() *cobra.Command {
if caPath != "" {
caCert, err := os.ReadFile(caPath)
if err != nil {
- log.Fatalf("[!] Failed to read CA certificate: %v", err)
+ return fmt.Errorf("reading CA certificate: %w", err)
}
pool := x509.NewCertPool()
pool.AppendCertsFromPEM(caCert)
@@ -38,7 +39,7 @@ func newClientCmd() *cobra.Command {
if fpName != "" {
fp, err := fingerprint.ByName(fpName)
if err != nil {
- log.Fatalf("[!] Failed to load fingerprint: %v", err)
+ return fmt.Errorf("loading fingerprint: %w", err)
}
p.Fingerprint = fp
log.Printf("[+] Using TLS fingerprint: %s", fp.Name())
@@ -47,7 +48,7 @@ func newClientCmd() *cobra.Command {
if interceptCert != "" || interceptKey != "" {
ca, err := proxy.LoadOrGenerateCA(interceptCert, interceptKey)
if err != nil {
- log.Fatalf("[!] Failed to load/generate intercept CA: %v", err)
+ return fmt.Errorf("loading/generating intercept CA: %w", err)
}
p.LocalCA = ca
log.Printf("[+] MitM CA ready — import %s, then: curl --cacert %s -x http://localhost%s https://<target>",
diff --git a/cmd/server.go b/cmd/server.go
@@ -2,6 +2,8 @@ package cmd
import (
"crypto/x509"
+ "errors"
+ "fmt"
"log"
"os"
@@ -25,10 +27,10 @@ func newServerCmd() *cobra.Command {
Short: "TLS termination proxy with upstream fingerprinting",
RunE: func(cmd *cobra.Command, args []string) error {
if backend == "" {
- log.Fatal("[!] --backend is required for server mode")
+ return errors.New("--backend is required for server mode")
}
if cert == "" || key == "" {
- log.Fatal("[!] --cert and --key are required for server mode")
+ return errors.New("--cert and --key are required for server mode")
}
p := &proxy.Proxy{
@@ -39,7 +41,7 @@ func newServerCmd() *cobra.Command {
if caPath != "" {
caCert, err := os.ReadFile(caPath)
if err != nil {
- log.Fatalf("[!] Failed to read CA certificate: %v", err)
+ return fmt.Errorf("reading CA certificate: %w", err)
}
pool := x509.NewCertPool()
pool.AppendCertsFromPEM(caCert)
@@ -49,14 +51,19 @@ func newServerCmd() *cobra.Command {
if fpName != "" {
fp, err := fingerprint.ByName(fpName)
if err != nil {
- log.Fatalf("[!] Failed to load fingerprint: %v", err)
+ return fmt.Errorf("loading fingerprint: %w", err)
}
p.Fingerprint = fp
log.Printf("[+] Using TLS fingerprint: %s", fp.Name())
}
+ handler, err := proxy.ServerFrontHandler(cert, key)
+ if err != nil {
+ return err
+ }
+ p.Handler = handler
+
log.Printf("[+] Mode: server (TLS termination → backend %s)", backend)
- p.Handler = proxy.ServerFrontHandler(cert, key)
return p.Run()
},
}
diff --git a/proxy/integration_test.go b/proxy/integration_test.go
@@ -157,7 +157,11 @@ func TestServerFront_Integration(t *testing.T) {
CAPool: backendCAPool,
Fingerprint: fp,
}
- proxyAddr := serveHandler(t, p, ServerFrontHandler(certFile, keyFile))
+ handler, err := ServerFrontHandler(certFile, keyFile)
+ if err != nil {
+ t.Fatalf("ServerFrontHandler: %v", err)
+ }
+ proxyAddr := serveHandler(t, p, handler)
tlsConn, err := tls.DialWithDialer(
&net.Dialer{Timeout: testTimeout},
diff --git a/proxy/ja4_integration_test.go b/proxy/ja4_integration_test.go
@@ -85,7 +85,11 @@ func TestServerFront_JA4(t *testing.T) {
}
p := &Proxy{BackendAddr: captureAddr, CAPool: capturePool, Fingerprint: fp}
- proxyAddr := serveHandler(t, p, ServerFrontHandler(proxyCertFile, proxyKeyFile))
+ handler, err := ServerFrontHandler(proxyCertFile, proxyKeyFile)
+ if err != nil {
+ t.Fatalf("ServerFrontHandler: %v", err)
+ }
+ proxyAddr := serveHandler(t, p, handler)
tlsConn, err := tls.DialWithDialer(
&net.Dialer{Timeout: testTimeout},
diff --git a/proxy/serverfront.go b/proxy/serverfront.go
@@ -3,16 +3,17 @@ package proxy
import (
"bufio"
"crypto/tls"
+ "fmt"
"log"
"net"
)
// ServerFrontHandler returns a Handler that terminates incoming TLS using certFile/keyFile,
// then forwards to p.BackendAddr using the configured fingerprint.
-func ServerFrontHandler(certFile, keyFile string) Handler {
+func ServerFrontHandler(certFile, keyFile string) (Handler, error) {
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
- log.Fatalf("ServerFrontHandler: loading certificate: %v", err)
+ return nil, fmt.Errorf("ServerFrontHandler: loading certificate: %w", err)
}
tlsCfg := &tls.Config{
@@ -38,5 +39,5 @@ func ServerFrontHandler(certFile, keyFile string) Handler {
defer targetConn.Close()
pipe(tlsConn, bufio.NewReader(tlsConn), targetConn)
- }
+ }, nil
}
| | | | |