diff --git a/agent/agentssh/agentssh.go b/agent/agentssh/agentssh.go index 0d3eeb8dcc..ede58cf4e3 100644 --- a/agent/agentssh/agentssh.go +++ b/agent/agentssh/agentssh.go @@ -110,6 +110,11 @@ type Config struct { // X11DisplayOffset is the offset to add to the X11 display number. // Default is 10. X11DisplayOffset *int + // X11MaxPort overrides the highest port used for X11 forwarding + // listeners. Defaults to X11MaxPort (6200). Useful in tests + // to shrink the port range and reduce the number of sessions + // required. + X11MaxPort *int // BlockFileTransfer restricts use of file transfer applications. BlockFileTransfer bool // ReportConnection. @@ -158,6 +163,10 @@ func NewServer(ctx context.Context, logger slog.Logger, prometheusRegistry *prom offset := X11DefaultDisplayOffset config.X11DisplayOffset = &offset } + if config.X11MaxPort == nil { + maxPort := X11MaxPort + config.X11MaxPort = &maxPort + } if config.UpdateEnv == nil { config.UpdateEnv = func(current []string) ([]string, error) { return current, nil } } @@ -201,6 +210,7 @@ func NewServer(ctx context.Context, logger slog.Logger, prometheusRegistry *prom x11HandlerErrors: metrics.x11HandlerErrors, fs: fs, displayOffset: *config.X11DisplayOffset, + maxPort: *config.X11MaxPort, sessions: make(map[*x11Session]struct{}), connections: make(map[net.Conn]struct{}), network: func() X11Network { diff --git a/agent/agentssh/x11.go b/agent/agentssh/x11.go index bfbdfc689c..957762e691 100644 --- a/agent/agentssh/x11.go +++ b/agent/agentssh/x11.go @@ -57,6 +57,7 @@ type x11Forwarder struct { x11HandlerErrors *prometheus.CounterVec fs afero.Fs displayOffset int + maxPort int // network creates X11 listener sockets. Defaults to osNet{}. network X11Network @@ -314,7 +315,7 @@ func (x *x11Forwarder) evictLeastRecentlyUsedSession() { // the next available port starting from X11StartPort and displayOffset. func (x *x11Forwarder) createX11Listener(ctx context.Context) (ln net.Listener, display int, err error) { // Look for an open port to listen on. - for port := X11StartPort + x.displayOffset; port <= X11MaxPort; port++ { + for port := X11StartPort + x.displayOffset; port <= x.maxPort; port++ { if ctx.Err() != nil { return nil, -1, ctx.Err() } diff --git a/agent/agentssh/x11_test.go b/agent/agentssh/x11_test.go index 2f2c657f65..43613ba798 100644 --- a/agent/agentssh/x11_test.go +++ b/agent/agentssh/x11_test.go @@ -142,8 +142,13 @@ func TestServer_X11_EvictionLRU(t *testing.T) { // Use in-process networking for X11 forwarding. inproc := testutil.NewInProcNet() + // Limit port range so we only need a handful of sessions to fill it + // (the default 190 ports may easily timeout or conflict with other + // ports on the system). + maxPort := agentssh.X11StartPort + agentssh.X11DefaultDisplayOffset + 5 cfg := &agentssh.Config{ - X11Net: inproc, + X11Net: inproc, + X11MaxPort: &maxPort, } s, err := agentssh.NewServer(ctx, logger, prometheus.NewRegistry(), fs, agentexec.DefaultExecer, cfg) @@ -172,7 +177,7 @@ func TestServer_X11_EvictionLRU(t *testing.T) { // configured port range. startPort := agentssh.X11StartPort + agentssh.X11DefaultDisplayOffset - maxSessions := agentssh.X11MaxPort - startPort + 1 - 1 // -1 for the blocked port + maxSessions := maxPort - startPort + 1 - 1 // -1 for the blocked port require.Greater(t, maxSessions, 0, "expected a positive maxSessions value") // shellSession holds references to the session and its standard streams so