From 09ccedbf8999230ecb72c388b905359779839032 Mon Sep 17 00:00:00 2001 From: wi1dcard Date: Wed, 17 Apr 2024 02:01:19 +0800 Subject: [PATCH] Improve TLS handshake error logging. --- pkg/proxyserver/proxyserver.go | 14 ++++++++--- pkg/proxyserver/proxyserver_test.go | 38 +++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 pkg/proxyserver/proxyserver_test.go diff --git a/pkg/proxyserver/proxyserver.go b/pkg/proxyserver/proxyserver.go index 685fe50..1580b02 100644 --- a/pkg/proxyserver/proxyserver.go +++ b/pkg/proxyserver/proxyserver.go @@ -84,9 +84,7 @@ func (server *Server) serveConn(conn net.Conn) { io.WriteString(re.Conn, "HTTP/1.0 400 Bad Request\r\n\r\nClient sent an HTTP request to an HTTPS server.\n") } - if errors.Is(err, context.Canceled) || - errors.Is(err, io.EOF) || - errors.Is(err, syscall.ECONNRESET) { + if isNetworkOrClientError(err) { server.vlogf("tls handshake failed (%s), client error: %s", conn.RemoteAddr(), err) } else { server.logf("tls handshake error (%s): %s", conn.RemoteAddr(), err) @@ -312,3 +310,13 @@ func tlsRecordHeaderLooksLikeHTTP(hdr [5]byte) bool { } return false } + +func isNetworkOrClientError(err error) bool { + var netOpErr *net.OpError + return errors.Is(err, context.Canceled) || + errors.Is(err, context.DeadlineExceeded) || + errors.Is(err, io.EOF) || + errors.Is(err, syscall.ECONNRESET) || + // https://github.com/golang/go/blob/release-branch.go1.22/src/crypto/tls/conn.go#L724 + (errors.As(err, &netOpErr) && netOpErr.Op == "remote error") +} diff --git a/pkg/proxyserver/proxyserver_test.go b/pkg/proxyserver/proxyserver_test.go new file mode 100644 index 0000000..8d2650d --- /dev/null +++ b/pkg/proxyserver/proxyserver_test.go @@ -0,0 +1,38 @@ +package proxyserver + +import ( + "fmt" + "net" + "testing" +) + +func TestIsNetworkOrClientError(t *testing.T) { + // https://github.com/golang/go/blob/release-branch.go1.22/src/crypto/tls/alert.go#L77 + alert := fmt.Errorf("unknown certificate authority") + // https://github.com/golang/go/blob/release-branch.go1.22/src/crypto/tls/conn.go#L724 + err := setErrorLocked(&net.OpError{Op: "remote error", Err: alert}) + if isNetworkOrClientError(err) == false { + t.Error("expected tls alert record is client error, got false") + } + + if isNetworkOrClientError(fmt.Errorf("some random error")) { + t.Error("expected random error is not client error, got true") + } +} + +type permanentError struct { + err net.Error +} + +func (e *permanentError) Error() string { return e.err.Error() } +func (e *permanentError) Unwrap() error { return e.err } +func (e *permanentError) Timeout() bool { return e.err.Timeout() } +func (e *permanentError) Temporary() bool { return false } + +func setErrorLocked(err error) error { + if e, ok := err.(net.Error); ok { + return &permanentError{err: e} + } else { + return err + } +}