From 2e16457467aa36df9d403fb70762b9ad2a34e8ca Mon Sep 17 00:00:00 2001 From: ginuerzh Date: Mon, 22 Jun 2026 14:29:41 +0800 Subject: [PATCH] fix(config): warn when TLS options are set on a plaintext listener (#108) Log a warning in ParseService when certFile/keyFile/caFile are configured for a listener type that never terminates TLS (tcp, udp, ws, mws, redirect, tproxy, rtcp, rudp, unix, runix, serial, stdio), so the misconfiguration is no longer silent. Uses a conservative plaintext blocklist; TLS-keyed off raw config strings so normal plaintext services stay quiet. Refs go-gost/gost#579. --- config/parsing/service/parse.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/config/parsing/service/parse.go b/config/parsing/service/parse.go index c1a06a1c..e9658338 100644 --- a/config/parsing/service/parse.go +++ b/config/parsing/service/parse.go @@ -40,6 +40,21 @@ import ( "github.com/vishvananda/netns" ) +// plaintextListeners are listener types that never terminate TLS on their +// accepted connections, so any certFile/keyFile/caFile configured for them is +// silently ignored. This catches the common footgun where a user writes e.g. +// `tls+mws://...?certFile=...` expecting TLS: the "tls+" prefix is parsed as +// the handler scheme (see x/config/cmd/cmd.go buildServiceConfig), not a TLS +// wrapper, so the underlying mws listener stays plaintext. Extend this set when +// new plaintext listeners are added. +var plaintextListeners = map[string]bool{ + "tcp": true, "udp": true, + "ws": true, "mws": true, + "redirect": true, "tproxy": true, + "rtcp": true, "rudp": true, + "unix": true, "runix": true, "serial": true, "stdio": true, +} + // ParseService constructs a fully-wired service.Service from a ServiceConfig. // It defaults the listener to "tcp" and the handler to "auto", resolves named // components from the registry (authers, admissions, bypasses, resolvers, @@ -89,6 +104,11 @@ func ParseService(cfg *config.ServiceConfig) (service.Service, error) { tls_util.RejectUnknownSNIConfig(tlsConfig, tlsCfg.RejectUnknownSNI, tlsCfg.ServerNames) } + if (tlsCfg.CertFile != "" || tlsCfg.KeyFile != "" || tlsCfg.CAFile != "") && plaintextListeners[cfg.Listener.Type] { + serviceLogger.Warnf("TLS certificate options are configured but the %q listener does not use TLS and will ignore them; the connection will be plaintext. Use a TLS-capable listener (e.g. mwss, wss, tls, quic, grpc, http2, http3) to enable TLS.", + cfg.Listener.Type) + } + authers := auth_parser.List(cfg.Listener.Auther, cfg.Listener.Authers...) if len(authers) == 0 { if auther := auth_parser.ParseAutherFromAuth(cfg.Listener.Auth); auther != nil {