diff --git a/listener/ws/listener.go b/listener/ws/listener.go index 6b70e8fc..12e51469 100644 --- a/listener/ws/listener.go +++ b/listener/ws/listener.go @@ -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 +}