Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Terminated Listener SNI and hostname matching #2417

Open
youngnick opened this issue Sep 21, 2023 · 10 comments
Open

Terminated Listener SNI and hostname matching #2417

youngnick opened this issue Sep 21, 2023 · 10 comments
Labels
kind/bug Categorizes issue or PR as related to a bug. lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. triage/needs-information Indicates an issue needs more information in order to work on it.

Comments

@youngnick
Copy link
Contributor

Another issue to have come out of the discussion on #2288 is that of how hostname matches are performed when traffic matchin on HTTPRoutes when those HTTPRoutes are attached to a Listener that is terminating HTTPS.

When that is happening, there are at least two places where the hostname can be matched - the SNI (Server Name Indicator) that's used as part of the TLS negotiation, and the Host: header that's handled as part of the HTTP request.

It's both not immediately obvious and critically important for TLS security that Gateway API implementations enforce that the SNI and the Host header match, using the usual hostname matching rules.

This is really important once we add external client certificate validation (as in #2273). If we don't mandate that the SNI and Host header match, then it's possible to bypass client certificate validation by adding another hostname to the same Gateway implementation, using that as the SNI, and then specifying the secure hostname as the Host header.

An example:
We have a secure listener on secure.example.com - this Listener requires a client certificate to authenticate external clients, and uses a HTTPRoute that forwards to the secure backend.

However, if I also add an insecure.example.com Listener that also requires TLS, but when performing the actual HTTP request, we send an SNI of insecure.example.com and a Host header of secure.example.com, then it's possible to bypass the client certificate requirement, through no fault of the owner of the secure backend.

To address this, I propose the following rules:

(in this part, for simplicity, I'm only going to discuss as though the hostname is set as the Listener level, but remember that there is a hostname-matching part of HTTPRoute attachment that can complicate this further).

That is:

  • if the Listener hostname is precise - cafe.example.com, then both the SNI and Host header must be equal to cafe.example.com.
  • If the Listener hostname is precise - *.example.com, then both the SNI and Host header must still be the same value. For example, both cafe.example.com and storeroom.example.com are valid matches, but in either case, both the SNI and Host header must be set to the same value.

If the SNI and Host header are not exactly equal, then the request must be rejected (the exact error code I'm not sure on at the moment, but probably something in the 4xx range, since it's a property of the user request.)

@youngnick youngnick added the kind/bug Categorizes issue or PR as related to a bug. label Sep 21, 2023
@sunjayBhatia
Copy link
Member

nit: If the Listener hostname is precisea wildcard domain - *.example.com

@shaneutt shaneutt added the needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. label Sep 21, 2023
@robscott
Copy link
Member

Thanks for writing this up @youngnick! My concern here is that I think the proposed behavior here may not be broadly implementable. I agree that we need to be very careful to avoid surprises like domain fronting. The more I think about this, the more I wonder if the proposed resolution to #2416 would also resolve this.

Since we already have this guidance that requires Routes attached to listeners to have a matching hostname when one is specified, this would ensure that at least domain fronting would not result in different routing behavior:

// For HTTPRoute and TLSRoute resources, there is an interaction with the
// `spec.hostnames` array. When both listener and route specify hostnames,
// there MUST be an intersection between the values for a Route to be
// accepted. For more information, refer to the Route specific Hostnames
// documentation.

This could still be problematic when the request matches the backend with an unexpected host header, but I think that's a significantly smaller problem than for example bypassing client cert validation or being routed to an unexpected backend.

@howardjohn
Copy link
Contributor

This will need to take into account 421 status code and certificates as well. SNI and Host headers are not the only variables.

"Gateway API implementations enforce that the SNI and the Host header match" (without more nuance) is not complying with HTTP2 specification and will break browsers. On the meeting you mentioned this as well, just want to make sure we take this into account.

@shaneutt shaneutt added triage/needs-information Indicates an issue needs more information in order to work on it. and removed needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. labels Oct 9, 2023
@k8s-triage-robot
Copy link

The Kubernetes project currently lacks enough contributors to adequately respond to all issues.

This bot triages un-triaged issues according to the following rules:

  • After 90d of inactivity, lifecycle/stale is applied
  • After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied
  • After 30d of inactivity since lifecycle/rotten was applied, the issue is closed

You can:

  • Mark this issue as fresh with /remove-lifecycle stale
  • Close this issue with /close
  • Offer to help out with Issue Triage

Please send feedback to sig-contributor-experience at kubernetes/community.

/lifecycle stale

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Jan 30, 2024
@youngnick
Copy link
Contributor Author

Still need to get to this at some point.

/remove-lifecycle stale

@k8s-ci-robot k8s-ci-robot removed the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Jan 30, 2024
@k8s-triage-robot
Copy link

The Kubernetes project currently lacks enough contributors to adequately respond to all issues.

This bot triages un-triaged issues according to the following rules:

  • After 90d of inactivity, lifecycle/stale is applied
  • After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied
  • After 30d of inactivity since lifecycle/rotten was applied, the issue is closed

You can:

  • Mark this issue as fresh with /remove-lifecycle stale
  • Close this issue with /close
  • Offer to help out with Issue Triage

Please send feedback to sig-contributor-experience at kubernetes/community.

/lifecycle stale

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Apr 29, 2024
@youngnick
Copy link
Contributor Author

Still needs to be done.

/remove-lifecycle stale

@k8s-ci-robot k8s-ci-robot removed the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label May 1, 2024
@k8s-triage-robot
Copy link

The Kubernetes project currently lacks enough contributors to adequately respond to all issues.

This bot triages un-triaged issues according to the following rules:

  • After 90d of inactivity, lifecycle/stale is applied
  • After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied
  • After 30d of inactivity since lifecycle/rotten was applied, the issue is closed

You can:

  • Mark this issue as fresh with /remove-lifecycle stale
  • Close this issue with /close
  • Offer to help out with Issue Triage

Please send feedback to sig-contributor-experience at kubernetes/community.

/lifecycle stale

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Jul 30, 2024
@youngnick
Copy link
Contributor Author

still in there.

/remove-lifecycle stale

@k8s-ci-robot k8s-ci-robot removed the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Aug 9, 2024
@k8s-triage-robot
Copy link

The Kubernetes project currently lacks enough contributors to adequately respond to all issues.

This bot triages un-triaged issues according to the following rules:

  • After 90d of inactivity, lifecycle/stale is applied
  • After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied
  • After 30d of inactivity since lifecycle/rotten was applied, the issue is closed

You can:

  • Mark this issue as fresh with /remove-lifecycle stale
  • Close this issue with /close
  • Offer to help out with Issue Triage

Please send feedback to sig-contributor-experience at kubernetes/community.

/lifecycle stale

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Nov 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Categorizes issue or PR as related to a bug. lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. triage/needs-information Indicates an issue needs more information in order to work on it.
Projects
None yet
Development

No branches or pull requests

7 participants