fix(listener): route WS/WSS HTTP server errors through GOST logger

Set http.Server.ErrorLog to a logWriter that routes HTTP server errors
(TLS handshake failures, malformed requests) to the GOST logger at Debug
level instead of escaping to stderr via log.Printf.

Without this, network scanners and protocol filters probing the WSS port
produce uncontrolled output:
  http: TLS handshake error from ...

Also downgrade WebSocket upgrade failures from Error to Warn — plain HTTP
requests hitting the WebSocket endpoint are operational noise.

Fixes go-gost/gost#419
This commit is contained in:
ginuerzh
2026-06-21 13:47:51 +08:00
parent a424148018
commit 92002fa35e
+25 -1
View File
@@ -2,9 +2,11 @@ package ws
import (
"context"
stdlog "log"
"net"
"net/http"
"net/http/httputil"
"strings"
"time"
"github.com/go-gost/core/limiter"
@@ -85,6 +87,12 @@ func (l *wsListener) Init(md md.Metadata) (err error) {
Addr: l.options.Addr,
Handler: mux,
ReadHeaderTimeout: l.md.readHeaderTimeout,
// Route HTTP server errors (TLS handshake failures, malformed
// requests) to the GOST logger instead of the default stderr
// output via log.Printf. Without this, network scanners and
// protocol filters probing the WSS port produce uncontrolled
// noise: "http: TLS handshake error from ...".
ErrorLog: stdlog.New(&logWriter{log: l.log}, "", 0),
}
l.cqueue = make(chan net.Conn, l.md.backlog)
@@ -186,7 +194,9 @@ func (l *wsListener) upgrade(w http.ResponseWriter, r *http.Request) {
conn, err := l.upgrader.Upgrade(w, r, l.md.header)
if err != nil {
log.Error(err)
// Upgrade failures (plain HTTP requests, websocket
// handshake errors) are operational noise — log at Warn.
log.Warn(err)
return
}
@@ -208,3 +218,17 @@ func (l *wsListener) upgrade(w http.ResponseWriter, r *http.Request) {
log.Warnf("connection queue is full, client %s discarded", conn.RemoteAddr())
}
}
// logWriter adapts a GOST logger to the io.Writer interface required by
// http.Server.ErrorLog. It writes each log entry as a Debug-level message
// so that HTTP server errors (TLS handshake failures, malformed requests)
// are captured in GOST's logging pipeline instead of escaping to stderr
// via log.Printf.
type logWriter struct {
log logger.Logger
}
func (w *logWriter) Write(p []byte) (n int, err error) {
w.log.Debug(strings.TrimSpace(string(p)))
return len(p), nil
}