Add a separate HTTP listener for observability, configured through
metricsServer in both frps and frpc. It serves /healthz and, when
pprofEnable is set, the pprof handlers except /debug/pprof/cmdline. It
never serves the dashboard, static assets or the admin API, and it does
not touch the global assets filesystem.
frps also serves /metrics on this listener with both runtime and business
metrics, enabled by metricsServer.port alone. The in-memory collector
still starts only with the dashboard, and the Prometheus collector starts
either with metricsServer or with enablePrometheus plus webServer, so a
configuration that collected nothing before still collects nothing.
The /healthz, /metrics and pprof endpoints on webServer, and
enablePrometheus, keep working but are deprecated and log a hint at
startup. frpc does not serve /metrics yet.
A constructor that binds a port before its fallible preparation leaks the
listener when a later step returns an error, and no one can close it because
the returned service is nil.
pkg/util/http: load the TLS keypair and build the auth middleware before
net.Listen, so binding is the last step that can run and a failure leaves no
bound port behind.
server: create the web server after auth, the tcpmux, main, kcp, quic, ssh
gateway and vhost listeners, and the nat hole controller, following what frpc
already does. If the web server itself fails, close the resources created so
far before returning. The port managers start their cleanup workers on
creation, so they are created after every fallible step too, and the metrics
collectors keep being enabled only when the web server is configured.
Add regression tests for all three failure paths.
Use net/http Server.Protocols and the merged golib listener path instead of the deprecated h2c handler. Keep HTTP/1.1 and cleartext HTTP/2 prior-knowledge support, while intentionally dropping HTTP/1.1 Upgrade: h2c.
SUDP payload codec follows transport wireProtocol; same-protocol v1/v1 and v2/v2 keep raw join; only mixed proxy/visitor protocols use message-aware bridge; no new capability/selection field.
Replace 10 positional parameters in NewControl() with a single
SessionContext struct, matching the client-side pattern. This also
eliminates the post-construction mutation of clientRegistry and
removes two TODO comments.
- Fix SSH tunnel gateway incorrectly binding to proxyBindAddr instead of bindAddr
- This caused external connections to fail when proxyBindAddr was set to 127.0.0.1
- SSH tunnel gateway now correctly binds to bindAddr for external accessibility
- Update Release.md with bug fix description
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- Update go.mod to use github.com/quic-go/quic-go v0.53.0
- Replace quic.Connection interface with *quic.Conn struct
- Replace quic.Stream interface with *quic.Stream struct
- Update all affected files to use new API:
- pkg/util/net/conn.go: Update QuicStreamToNetConn function and wrapQuicStream struct
- server/service.go: Update HandleQUICListener function parameter
- client/visitor/xtcp.go: Update QUICTunnelSession struct field
- client/connector.go: Update defaultConnectorImpl struct field
Fixes#4852
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>