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

Support Virtual Host Based Routing for Non-SNI HTTPS Clients #1503

Closed
anujw opened this issue Sep 15, 2019 · 13 comments · Fixed by #2477
Closed

Support Virtual Host Based Routing for Non-SNI HTTPS Clients #1503

anujw opened this issue Sep 15, 2019 · 13 comments · Fixed by #2477
Assignees
Labels
blocked/needs-design Categorizes the issue or PR as blocked because it needs a design document. blocked/needs-product Categorizes the issue or PR as blocked because it needs a decision from product management.
Milestone

Comments

@anujw
Copy link

anujw commented Sep 15, 2019

We need to do virtual host based routing, so that the TLS request is routed to the appropriate service, based on the hostname specified in the HTTPS’s “HOST” header. As HOST Header is encrypted during TLS handshake, it can’t be used for virtual host based routing unless client sends HTTPS request specifying hostname using the SNI or the request is first decrypted using a default TLS certificate.
Here’s the problem, we need to support clients which may not be using SNI. So, when a HTTPS request is coming, Contour needs to first decrypt the request using a default TLS certificate and then based on the HOST header, route it to appropriate service. As of now, Contour only provides certificate at virtual host level in an IngressRoute and there is no way to define a default TLS certificate in Contour . Many Ingress controllers allow you to specify the default TLS cert but Contour doesn’t support it. The solution provided in #410 i.e. certificate delegation can't be used in this case.

@davecheney
Copy link
Contributor

Thank you for raising this issue. At the moment Contour doesn't have the notion of a default, or fallback certificate. Probably the way to do this is to specify on the command line or a config file a "default ingress" object. That is, an ingress, ingressroute, or httpproxy record defined by the administrator as the object which requests are routed too if they do not match any other virtualhost.

@davecheney davecheney added this to the Backlog milestone Sep 16, 2019
@davecheney davecheney added blocked/needs-product Categorizes the issue or PR as blocked because it needs a decision from product management. blocked/needs-design Categorizes the issue or PR as blocked because it needs a design document. labels Sep 16, 2019
@anujw
Copy link
Author

anujw commented Sep 16, 2019

@davecheney We need to use default TLS certificate in both the cases mentioned below:

  1. When SNI is not used by HTTPS client
  2. When SNI is used, but server name doesn't match any of the virtual hosts specified in Ingress routes.

@moderation
Copy link

We have hit the same issue with having an F5 based GTM (Global Traffic Manager) (now branded as Big-IP DNS) trying to perform healthchecks against Contour. The F5 doesn't send any SNI information (people have been asking F5 to support SNI healthchecks / monitors since 2014). Contour terminates the TLS calls and the healthchecks fail. Our NGINX ingress does support fallback to a default cert so this interaction works. @alexbrand @sudeeptoroy

So +1 on a fallback or default ojbect.

@moderation
Copy link

  • NGINX - Default SSL Certificate. This is the behavior we would like to have with Contour
  • Envoy supports multiple downstream certificates - Certificate selection. This may be the Envoy way to implement this but need to test

@shabx shabx added the ZD3850 label Oct 24, 2019
@davecheney
Copy link
Contributor

Here are some raw notes on how this feature could be implemented:

Currently we generate a list of filter chains on the port 443 listener, each filter chain entry has a match condition for the expected hostname and allows envoy to select the right certificate to handle the handshake (this is SNI). If envoy gets to the bottom of the list without any filter chains matches firing, no handshake (I'm assuming envoy just closes the connection).

We can add to this list a final filter chain entry that does not have any match conditions (the details are unimportant), envoy matches filter chains from most specific to least so effectively this filter chain will match if no other chain matches. Any TLS handshake that doesn't match a more specific filter chain will be offered the certificate attached to this final filter chain.

The certificate to be offered is a contour wide setting, not per virtualhost, so the configuration should go into a cli flag or the contour config file, I'm thinking something like

contour serve --fallback-certificate=namespace/name

The open questions I have are

  • This is a global option, like --root-namespaces, or --ingress-class-name. If the fallback certificate is supplied should there be an option for individual virtualhosts to opt in to being available via the fallback certificate or does enabling the fallback certificate make all virutalhosts reachable via the fallback certificate. This is important to answer as the fallback certificate may have different TLS properties to the SNI selected certificate.
  • How does this interact with client certificate authentication Client certificate validation (mTLS) design proposal #1233 ? Arguably if an specific virtualhost requires the client to validate itself with a certificate for the request to be forwarded on to the k8s service, it should not be possible to circumvent this by send a non TLS handshake to envoy to negotiate against the fallback certificate.

@tsaarni
Copy link
Member

tsaarni commented Jan 7, 2020

Yes exactly: the filter chain that would act as fallback cannot expose all virtual hosts just blindly since that would make it possible for client to circumvent client authentication - client would do this by not setting SNI header in TLS handshake.

Better alternatives could be:

  1. have individual virtualhosts opt-in for fallback, like you wrote
  2. expose only those virtualhosts that do not have specific TLS configuration currently

Here (2) would limit single virtualhost to be exposed only under single server certificate at any time: if virtualhost is declared with HTTPProxy.spec.virtualhost.tls, it would never be exposed by a filter chain with fallback TLS settings. This could make it bit easier for user to reason how each virtualhost is protected by TLS. But I wonder could this be too restrictive in some cases?

@jpeach
Copy link
Contributor

jpeach commented Feb 12, 2020

xref kubernetes-sigs/gateway-api#72

@stevesloka
Copy link
Member

So it seems like the work steps here are to:

  1. Add a new argument to contour serve named --fallback-certificate and takes a reference to a secret that is namespaced with name (e.g. namespace/name)
  2. A new field added to HTTPProxy.Spec.VirtualHost.TLS named FallbackCertificateEnabled to allow virtual hosts to opt into this functionality.

My only question is around the new arg, is a single certificate good enough? Should that be expanded to allow certain vhosts to use different fallback certificates? So this field would be a set and not a single namespace/secret. Maybe I have two teams, and they each manage their own certificates, so a single cert would be too limiting. This, however, would require the field on the vhost to specify the matching secret as we do for certificate delegation.

@jpeach
Copy link
Contributor

jpeach commented Feb 24, 2020

Add a new argument to contour serve named --fallback-certificate and takes a reference to a secret that is namespaced with name (e.g. namespace/name)

I think it would be better to configure this in the cluster in some way (at least in the Contour config file). It is possible we will need to serve different fallbacks to different client IP ranges or restrict fallback by client IP, so we will need to think about how to leave some configuration wiggle room.

A new field added to HTTPProxy.Spec.VirtualHost.TLS named FallbackCertificateEnabled to allow virtual hosts to opt into this functionality.

+1 on requiring an explicit opt-in.

Should that be expanded to allow certain vhosts to use different fallback certificates?

I agree that there's scope for additional configuration here. As you point out, one dimension is whether we want to restrict vhosts to specific fallback certificates; another is how we choose which certificate to serve to a client; a final dimension is whether we have any HTTP access control on clients that are using this certificate.

@stevesloka
Copy link
Member

I'm going to write up a design doc on this. I think it will help the discussion.

@youngnick
Copy link
Member

I agree a design doc for this would be helpful.

@sudeeptoroy
Copy link
Contributor

yes, configuring at global or namespace scope plus opt-in would be great.
Also would it take care of workloads using tlspassthrough?

@davecheney
Copy link
Contributor

Supporting tls passthrough will continue to require SNI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocked/needs-design Categorizes the issue or PR as blocked because it needs a design document. blocked/needs-product Categorizes the issue or PR as blocked because it needs a decision from product management.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants