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

[kind/api-change] Allow wildcard suffix in hostnames #3644

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

simonfelding
Copy link

@simonfelding simonfelding commented Feb 27, 2025

What type of PR is this?
/kind gep

What this PR does / why we need it:
It adds support for wildcard suffixes in addition to wildcard prefixes in the Hostname type.
It is fully backwards-compatible.

Which issue(s) this PR fixes:

Fixes #3643

Does this PR introduce a user-facing change?:

Added support for wildcard suffixes in hostnames (like example.*)

@k8s-ci-robot k8s-ci-robot added the do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. label Feb 27, 2025
Copy link

linux-foundation-easycla bot commented Feb 27, 2025

CLA Signed

The committers listed above are authorized under a signed CLA.

@k8s-ci-robot k8s-ci-robot added the cncf-cla: no Indicates the PR's author has not signed the CNCF CLA. label Feb 27, 2025
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: simonfelding
Once this PR has been reviewed and has the lgtm label, please assign aojea for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot
Copy link
Contributor

Welcome @simonfelding!

It looks like this is your first PR to kubernetes-sigs/gateway-api 🎉. Please refer to our pull request process documentation to help your PR have a smooth ride to approval.

You will be prompted by a bot to use commands during the review process. Do not be afraid to follow the prompts! It is okay to experiment. Here is the bot commands documentation.

You can also check if kubernetes-sigs/gateway-api has its own contribution guidelines.

You may want to refer to our testing guide if you run into trouble with your tests not passing.

If you are having difficulty getting your pull request seen, please follow the recommended escalation practices. Also, for tips and tricks in the contribution process you may want to read the Kubernetes contributor cheat sheet. We want to make sure your contribution gets all the attention it needs!

Thank you, and welcome to Kubernetes. 😃

@k8s-ci-robot k8s-ci-robot added size/XS Denotes a PR that changes 0-9 lines, ignoring generated files. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Feb 27, 2025
@k8s-ci-robot
Copy link
Contributor

Hi @simonfelding. Thanks for your PR.

I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@k8s-ci-robot k8s-ci-robot added release-note Denotes a PR that will be considered when it comes time to generate release notes. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. and removed do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. cncf-cla: no Indicates the PR's author has not signed the CNCF CLA. labels Feb 27, 2025
Copy link
Contributor

@howardjohn howardjohn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs a lot more discussion around interactions with RFCs, implementation, and between objects.

For example, what is the semantics for matching between a listener hostname suffix match with a HTTPRoute hostname prefix match?

Which implementations can support this today? I am fairly sure envoy does not support suffix SNI matching.

This also has tricky impacts on certs which only support a prefix wildcard.

Further, most suffix match use cases I would imagine are a string suffix match. All wildcards in the API today are a single label wildcard match. So grafana.* would not match grafana.example.com which probably makes the use case not met.

@simonfelding
Copy link
Author

simonfelding commented Feb 27, 2025

@howardjohn Totally agree it needs careful review and discussion of interactions! I haven't been able to think of any that aren't already supported in the major implementations, nginx for example, but there might be something I can't come up with.

Envoy also supports it and it sounds like the developers have already thought these issues through: (Wildcard hosts are supported in the suffix or prefix form).

The top level element in the routing configuration is a virtual host. Each virtual host has a logical name as well as a set of domains that get routed to it based on the incoming request’s host header. This allows a single listener to service multiple top level domain path trees. Once a virtual host is selected based on the domain, the routes are processed in order to see which upstream cluster to route to or whether to perform a redirect.

domains
(repeated string, REQUIRED) A list of domains (host/authority header) that will be matched to this virtual host. Wildcard hosts are supported in the suffix or prefix form.

Domain search order:

  1. Exact domain names: www.foo.com.
  2. Suffix domain wildcards: *.foo.com or *-bar.foo.com.
  3. Prefix domain wildcards: foo.* or foo-*.
  4. Special wildcard * matching any domain.

Note
The wildcard will not match the empty string. e.g. *-bar.foo.com will match baz-bar.foo.com but not -bar.foo.com. The longest wildcards match first. Only a single virtual host in the entire route configuration can match on *. A domain must be unique across all virtual hosts or the config will fail to load.

I don't think it has any interaction with certs? It's true that certs only match on a single wildcard subdomain; The gateway API already violates this by matching *.example.com with cringle.bingle.example.com if there is no better match. SNI is all about finding the right certificate for a given hostname before the cert is served and the TLS handshake begins.

Let's say a server has two virtual hosts, grafana.example.com and grafana.example.org. When a HTTPS request comes in, the client_hello stage is still unencrypted and contains the requested hostname.
In the case of Host: grafana.example.com and a HTTPRoute matching the exact hostname, it's obvious what cert to serve, in the case of Host: grafana.another.com, it should be rejected as there are no matching certs. In the case of Host: grafana.example.org, the principle of the best match should be followed, where a HTTPRoute with grafana.example.org and .*.example.org is a better match than grafana.*. This is how Envoy does it too. Either way, this decision is made before the cert is served.

@howardjohn
Copy link
Contributor

Envoy supports it for HTTP Host headers, but the API you are changing here impacts SNI where its not supported: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/listener/v3/listener_components.proto#config-listener-v3-filterchainmatch

@simonfelding
Copy link
Author

simonfelding commented Feb 27, 2025

It's not in the given examples in that document, but I don't see why it wouldn't work? SNI is just a simple string extracted from the client_hello.

I'm not deep enough in the envoy code to be sure, but from a superficial look at the code I can't see any validation that treats the SNI as a special type of hostname string that cannot be wildcard-matched like other hostnames can.

Nginx does it too:

When searching for a virtual server by name, if name matches more than one of the specified variants, e.g. both wildcard name and regular expression match, the first matching variant will be chosen, in the following order of precedence:

  1. exact name
  2. longest wildcard name starting with an asterisk, e.g. “*.example.org”
  3. longest wildcard name ending with an asterisk, e.g. “mail.*”
  4. first matching regular expression (in order of appearance in a configuration file)

The name is determined in the following order:

Virtual server selection
First, a connection is created in a default server context. Then, the server name can be determined in the following request processing stages, each involved in server configuration selection:

  1. during SSL handshake, in advance, according to SNI

  2. after processing the request line

  3. after processing the Host header field

  4. if the server name was not determined after processing the request line or from the Host header field, nginx will use the empty name as the server name.

At each of these stages, different server configurations can be applied.

I also know for sure that the Citrix Netscaler has no problem treating the client hello SNI string as any other string and making complex routing decisions based on that - prior to serving a cert.

tl;dr: SNI just means sending the hostname before the cert is served, which makes routing a TLS connected work like unencrypted HTTP. After hostname is matched with a server (by SNI or by Host header), a cert is served. I'm pretty confident this GEP does not impact SNI - it's only about whether or not we can allow a Gateway implementation to match a hostname to a string ending with a wildcard :)

@howardjohn
Copy link
Contributor

I'm not deep enough in the envoy code to be sure, but from a superficial look at the code I can't see any validation that treats the SNI as a special type of hostname string that cannot be wildcard-matched like other hostnames can.

https://github.com/envoyproxy/envoy/blob/8784289b97003c3b2a36824b4a810112d62b7bfa/source/common/listener_manager/filter_chain_manager_impl.cc#L121-L123

I'm pretty confident this GEP does not impact SNI

Its changing the valid set of matchers against SNI so it is.

@simonfelding
Copy link
Author

Dang, nice find. Youre right, Envoy does not support it right now because of that line. Deserves a PR to that as well :)

But anyway, why should the Gateway API decide whether or not the implementation can get the wildcard-suffixed hostname? I think it's pretty clear that nginx supports it for example, and it looks like to me that it's just a matter of a submitting a minor patch to make envoy support it too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XS Denotes a PR that changes 0-9 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support wildcard suffixes in addition to wildcard prefixes in spec.hostnames
3 participants