Skip to content

fix(ssh): restore TLS-to-backend in web endpoint proxy#6320

Merged
gustavosbarreto merged 1 commit into
masterfrom
fix/web-endpoint-tls-regression
May 13, 2026
Merged

fix(ssh): restore TLS-to-backend in web endpoint proxy#6320
gustavosbarreto merged 1 commit into
masterfrom
fix/web-endpoint-tls-regression

Conversation

@gustavosbarreto
Copy link
Copy Markdown
Member

Closes #6316.

What

Reintroduces the TLS-to-backend block in ssh/http/handlers.go::HandleHTTPProxy that was silently lost when ssh/pkg/tunnel/tunnel.go was deleted during the agent V2 multistream refactor. Until this lands, the tls.enabled / tls.verify / tls.domain fields captured by the UI and persisted by the API have no effect at runtime.

Behavior change

  • When endpoint.TLS.Enabled is true, the proxy now wraps the raw tunnel net.Conn returned by Dialer.DialTo with tls.Client. SNI and the outgoing Host header are set to endpoint.TLS.Domain. endpoint.TLS.Verify toggles RootCAs = SystemCertPool() vs InsecureSkipVerify.
  • req.URL is now reconstructed as http://<host>:<port>/<path> so req.Write produces a complete request line. Scheme stays http:// because tls.Client wraps the conn; the wire is TLS regardless of the URL scheme.
  • Backend-side TLS minimum is tls.VersionTLS13.
  • When TLS is disabled, behavior is unchanged: Host stays as <address>.<endpoints_domain>, no TLS wrap.

Verification

Reproduced and validated end-to-end against a local stack with a Python backend serving HTTP on 9080 and HTTPS on 9443. Both backends respond 200 only when Host: app.local, otherwise 302 Location: https://app.local/....

Endpoint Target TLS Domain Before this PR After this PR
A 127.0.0.1:9080 (HTTP) n/a 302 -> https://app.local (canonical redirect, expected) unchanged: 302 -> https://app.local
B 127.0.0.1:9443 (HTTPS), tls.enabled=true, tls.domain=app.local app.local 504 Gateway Time-out (proxy wrote cleartext to TLS socket) 200 OK, backend logs Host: app.local

Backend log after the fix on scenario B:

[HTTPS:9443] GET /foo (Host='app.local')
    Host: app.local
    ...
-> 200 (Host matched 'app.local')

Out of scope (separate issues)

@gustavosbarreto gustavosbarreto requested a review from a team as a code owner May 13, 2026 12:57
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 13, 2026

Claude finished @gustavosbarreto's task in 2m 29s —— View job


Code Review Complete

Reviewed 1 file across code quality, security, testing, Go patterns, and architecture — no issues found. The code looks good as-is.

The TLS-to-backend restoration is clean: correct use of tls.Client wrapping, proper MinVersion floor at TLS 1.3, system CA pool for verified connections, intentional InsecureSkipVerify gated behind the user-controlled TLS.Verify toggle, and consistent use of transportConn throughout the bidirectional copy. The error constant fix (ErrDeviceTunnelReadResponseErrDeviceTunnelParsePath) is also appropriate.

To request another review round, comment /review.


Reintroduce the TLS handshake the proxy needs to talk to HTTPS backends
through a Web Endpoint. The block was lost when ssh/pkg/tunnel/tunnel.go
was deleted during the agent V2 multistream refactor and the new
ssh/http/handlers.go was created without porting it. The struct is still
persisted and returned by the API, but the runtime path was silently
ignoring tls.enabled / tls.verify / tls.domain.

When endpoint.TLS.Enabled is true, wrap the raw tunnel conn with
tls.Client using endpoint.TLS.Domain as SNI and the outgoing Host
header. Honor endpoint.TLS.Verify against the system CA pool, otherwise
fall back to InsecureSkipVerify. Reconstruct req.URL as
http://host:port/path so req.Write produces a proper request line even
without a path-only URL.

Closes #6316
@gustavosbarreto gustavosbarreto force-pushed the fix/web-endpoint-tls-regression branch from 0195504 to 848bb25 Compare May 13, 2026 13:13
@gustavosbarreto
Copy link
Copy Markdown
Member Author

/review

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 13, 2026

Claude finished @gustavosbarreto's task in 6m 12s —— View job


Code Review Complete

Reviewed 1 file across code quality, security, testing, Go patterns, and architecture — no issues found. The code looks good as-is.

The TLS-to-backend restoration is clean: correct use of tls.Client wrapping, proper MinVersion floor at TLS 1.3, system CA pool for verified connections, intentional InsecureSkipVerify gated behind the user-controlled TLS.Verify toggle, and consistent use of transportConn throughout the bidirectional copy. The error constant fix (ErrDeviceTunnelReadResponseErrDeviceTunnelParsePath) is also appropriate. Cross-repo check confirmed no impact on cloud — the WebEndpointTLS JSON contract is unchanged.

To request another review round, comment /review.


@gustavosbarreto gustavosbarreto enabled auto-merge (rebase) May 13, 2026 13:16
@gustavosbarreto gustavosbarreto merged commit f2ada59 into master May 13, 2026
10 of 11 checks passed
@gustavosbarreto gustavosbarreto deleted the fix/web-endpoint-tls-regression branch May 13, 2026 13:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Web endpoint TLS-to-backend regression: code dropped during V2 multistream refactor

1 participant