feat(ssh): use tls.domain as Host override even when TLS is disabled#6321
Merged
Conversation
|
Claude finished @gustavosbarreto's task in 2m 58s —— View job Code Review CompleteReviewed 1 file across code quality, security, testing, Go patterns, and architecture — no issues found. The code looks good as-is. The change is a clean, well-scoped refactor: moving the |
When endpoint.TLS.Domain is non-empty, rewrite the outgoing Host header to that value regardless of endpoint.TLS.Enabled. This lets users reach backends that validate Host or redirect to a canonical hostname without forcing them to also enable TLS-to-backend, common with plain-HTTP apps that hardcode their canonical FQDN. Previously the Host override only ran inside the TLS branch, so an HTTP target with a configured domain would still receive Host: <address>.<endpoints_domain> and the backend would 302 to its canonical hostname, which is typically not publicly resolvable. Behavior matrix after this change: - tls.enabled=true, domain set: Host=domain, SNI=domain (unchanged) - tls.enabled=false, domain set: Host=domain, plain HTTP (new) - tls.enabled=false, domain empty: Host=default, plain HTTP (unchanged) - tls.enabled=true, domain empty: rejected by service validation Closes #6319
a17e632 to
5c31c6e
Compare
gustavosbarreto
added a commit
that referenced
this pull request
May 13, 2026
The Domain input was hidden unless the TLS toggle was on, and the create payload only included the tls object when tls.enabled was true. After #6321 the backend uses tls.domain as a Host override even when TLS-to-backend is disabled, which is what users need to reach apps that validate Host or auto-redirect to a canonical hostname over plain HTTP. Changes: - Domain field is always visible. Required only when TLS is on. - FQDN validation runs whenever Domain is filled, regardless of TLS state. - Payload always includes the tls object when either TLS is on or Domain is non-empty, so the backend receives the host hint. - Labels and hints clarify the dual role: * "Use TLS to backend" toggle controls only the proxy-to-backend leg; the public URL is always HTTPS. * Domain is described as the Host override, becoming SNI when TLS is enabled. Refs #6322
gustavosbarreto
added a commit
that referenced
this pull request
May 13, 2026
The Domain input was hidden unless the TLS toggle was on, and the create payload only included the tls object when tls.enabled was true. After #6321 the backend uses tls.domain as a Host override even when TLS-to-backend is disabled, which is what users need to reach apps that validate Host or auto-redirect to a canonical hostname over plain HTTP. Changes: - Domain field is always visible. Required only when TLS is on. - FQDN validation runs whenever Domain is filled, regardless of TLS state. - Payload always includes the tls object when either TLS is on or Domain is non-empty, so the backend receives the host hint. - Labels and hints clarify the dual role: * "Use TLS to backend" toggle controls only the proxy-to-backend leg; the public URL is always HTTPS. * Domain is described as the Host override, becoming SNI when TLS is enabled. Refs #6322
gustavosbarreto
added a commit
that referenced
this pull request
May 13, 2026
The Domain input was hidden unless the TLS toggle was on, and the create payload only included the tls object when tls.enabled was true. After #6321 the backend uses tls.domain as a Host override even when TLS-to-backend is disabled, which is what users need to reach apps that validate Host or auto-redirect to a canonical hostname over plain HTTP. Changes: - Domain field is always visible. Required only when TLS is on. - FQDN validation runs whenever Domain is filled, regardless of TLS state. - Payload always includes the tls object when either TLS is on or Domain is non-empty, so the backend receives the host hint. - Labels and hints clarify the dual role: * "Use TLS to backend" toggle controls only the proxy-to-backend leg; the public URL is always HTTPS. * Domain is described as the Host override, becoming SNI when TLS is enabled. Refs #6322
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #6319.
What
Decouples the Host rewrite from
endpoint.TLS.Enabledinssh/http/handlers.go::HandleHTTPProxy. Whenendpoint.TLS.Domainis non-empty, the outgoing Host header is set to that value regardless of whether TLS-to-backend is enabled. When TLS is enabled, the same value is used as SNI, as before.Why
Today the proxy only overrides Host inside the TLS branch. Backends served on plain HTTP that validate Host or auto-redirect to a canonical hostname (very common with internal admin panels and corporate apps) cannot be reached through a Web Endpoint, because they receive
Host: <address>.<endpoints_domain>and respond with a302to their internal canonical hostname, which is not publicly resolvable. Thetls.domainfield already captures the value such backends expect; treating it as a Host hint independent of TLS makes that case work.Behavior matrix
tls.enabledtls.domaintruetls.domain(unchanged)tls.domain(unchanged)falsetls.domain(new)false<address>.<endpoints_domain>(unchanged)trueVerification
Validated end-to-end against a local stack with a Python backend on
127.0.0.1:9080(plain HTTP) that returns200only whenHost: app.local, otherwise302 Location: https://app.local/.... Three endpoints created viaPOST /api/web-endpoints:tls.enabledtls.domainfalseapp.local302 Location: https://app.local(host override never ran)200 OK, backend logsHost: app.localtrueapp.local200 OK(already fixed by #6320)200 OK(preserved)false302 Location: https://app.local(default Host caused canonical redirect)302 Location: https://app.localNotes
TLS Domainfield unless theEnable TLStoggle is on, and the create payload only includestls.domainwhentls.enabled=true. A UI/UX follow-up issue is filed separately to allow settingtls.domainindependent of TLS, including renaming the field to reflect its expanded role.