Extensions: Network filter to forward SNI from the downstream TLS connection to the upstream TLS connection#4334
Conversation
Signed-off-by: Vadim Eisenberg <vadime@il.ibm.com>
api/envoy/api/v2/auth/cert.proto
Outdated
| // | ||
| // TLS renegotiation is considered insecure and shouldn't be used unless absolutely necessary. | ||
| bool allow_renegotiation = 3; | ||
| bool allow_renegotiation = 4; |
There was a problem hiding this comment.
Is changing the option number for an existing command a breaking change? Can the new option be 4 instead?
There was a problem hiding this comment.
Right, please don't change field number, use 4 in new field.
api/envoy/api/v2/auth/cert.proto
Outdated
| // If true, the SNI from the downstream connection is forwarded to the upstream connection. | ||
| // | ||
| // TODO: handle oneof with the sni | ||
| bool forward_original_sni = 3; |
There was a problem hiding this comment.
why do you need an option for this? why can't you always forward the downstream SNI if there is no SNI value specified in the cluster?
There was a problem hiding this comment.
This is what @lizan wanted #4076 (comment)
Add explicit field forward_original_sni would be better than defaulting to forward.
I proposed:
Change tcp_proxy to set the SNI of the upstream connection in case the cluster's tls context does not have sni field.
There was a problem hiding this comment.
Let's be explicit between forward downstream SNI vs no SNI. You should be able to use oneof without breaking wire format.
api/envoy/api/v2/auth/cert.proto
Outdated
| // If true, the SNI from the downstream connection is forwarded to the upstream connection. | ||
| // | ||
| // TODO: handle oneof with the sni | ||
| bool forward_original_sni = 3; |
There was a problem hiding this comment.
Let's be explicit between forward downstream SNI vs no SNI. You should be able to use oneof without breaking wire format.
api/envoy/api/v2/auth/cert.proto
Outdated
| // | ||
| // TLS renegotiation is considered insecure and shouldn't be used unless absolutely necessary. | ||
| bool allow_renegotiation = 3; | ||
| bool allow_renegotiation = 4; |
There was a problem hiding this comment.
Right, please don't change field number, use 4 in new field.
Signed-off-by: Vadim Eisenberg <vadime@il.ibm.com>
|
@lizan I have fixed the API (this is just the beginning of the PR), do you know how should I specify that only one of the options, |
rshriram
left a comment
There was a problem hiding this comment.
So here is my rationale:
no incoming SNI and cluster has SNI - send cluster SNI
Has incoming SNI and no cluster SNI - send incoming SNI
Has incoming SNI and has cluster SNI (set through destinationRule for eg) : we have choices - ignore incoming SNI and use cluster SNI or ignore cluster SNI and use incoming SNI
Both of these scenarios are useful. When we setup Envoy as a plain pass through proxy like egress gateway, we want the inbound SNI to be forwarded if present, else use the SNI set in the cluster
So that the envoy on the other cluster that’s receiving traffic will have some SNI to route on.
From that point of view, this field should not be a one of. It should be independent and during upstream connection, we evaluate the cases above.
"No incoming SNI" - do you mean the SNI was not received from the downstream connection? So the decision which SNI to send must be determined dynamically, correct? So it should depend on three variables, So the algorithm is: Did I understand you correct? |
|
What configurations do we expect this to work in? I think this only makes sense with tcp_proxy, because it has 1:1 downstream-connection:upstream-connection relationship. For http, if you had multiple requests from different downstream connections, with different SNI values, going over the same upstream connection, it isn't clear what the behavior should be. If it only works with tcp_proxy, I'm not sure this is the right place for the configuration to live. |
|
@ggreenway Good point in So @lizan, what do you think? Should I add this flag as a parameter to the |
|
@ggreenway why isn't this valid for http as well? The SNI is outside of the HTTP semantics. It doesn't matter if we have a Mx1 or 1x1 right? the contract here is that if there is an SNI for the inbound connection that caused this cluster to be used, then use that SNI (if allowed). I am assuming that you can get a handle over the connection on which a request arrived, for HTTP and TCP alike. |
|
I think it doesn't make sense because for HTTP we're doing request proxying not connection proxying, and the SNI value is a connection property. So you're taking a value from the first downstream request, and applying it to N upstream requests. |
|
In HTTP (or any other supported Nx1 proxy L7 protocol) the connection pool can be based on upstream SNI. I think it makes sense to send all request from downstream connections with same SNI to same upstream connection. This doesn't have to be implemented initially, but please leave a comment. |
Signed-off-by: Vadim Eisenberg <vadime@il.ibm.com>
…ansportSocket() Signed-off-by: Vadim Eisenberg <vadime@il.ibm.com>
Agree. But the SNI here is not for routing. Its for policy enforcement, where the policy system might want to look at the SNI header and the HTTP authority to make a decision. |
That may be true in this use-case, but you don't know how it will be used elsewhere. I think if we want to do this for HTTP, @lizan's suggestion is the right way to do it. |
Signed-off-by: Vadim Eisenberg <vadime@il.ibm.com>
|
This pull request has been automatically marked as stale because it has not had activity in the last 7 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
|
This pull request has been automatically closed because it has not had activity in the last 14 days. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
This reverts commit f90f771. Signed-off-by: Vadim Eisenberg <vadime@il.ibm.com>
Signed-off-by: Vadim Eisenberg <vadime@il.ibm.com>
Signed-off-by: Vadim Eisenberg <vadime@il.ibm.com>
…test Signed-off-by: Vadim Eisenberg <vadime@il.ibm.com>
Signed-off-by: Vadim Eisenberg <vadime@il.ibm.com>
Signed-off-by: Vadim Eisenberg <vadime@il.ibm.com>
Signed-off-by: Vadim Eisenberg <vadime@il.ibm.com>
…ning if statement since it should be dependant on context or downstream connection Signed-off-by: Vadim Eisenberg <vadime@il.ibm.com>
Signed-off-by: Vadim Eisenberg <vadime@il.ibm.com>
Signed-off-by: Vadim Eisenberg <vadime@il.ibm.com>
Signed-off-by: Vadim Eisenberg <vadime@il.ibm.com>
|
@lizan Could you please review this PR? I wrote several unit tests, please let me know if more tests are required. |
lizan
left a comment
There was a problem hiding this comment.
Looks great and in this is in a good direction.
Can you pull out the non-extension part to a separate PR? That will help the review process.
We might want to wrap override_server_name in some class (perhaps named TransportSocketOptions, and that can be embedded directly in FilterState, but I'd like to iterate that on the separate PR.
source/common/stream_info/BUILD
Outdated
| ], | ||
| ) | ||
|
|
||
| envoy_cc_library( |
There was a problem hiding this comment.
this should be under tcp_proxy, see what is done for PerConnectionCluster, also this should be named override_server_name, "forward" what the filter does and this key only intended for override.
There was a problem hiding this comment.
My intention was as follows:
The filter is not related directly to the TCP proxy. The filter specifies the intention that the SNI must be forwarded. Other filters, such as TCP proxy, can extract that information and forward the SNI.
So there are three different names here:
-
Forward Requested Server Name in the Stream Info, means that there is some requested server name, not necessarrily SNI, maybe requested server name from some other protocol, that must be forwarded to the upstream, not necessarily by tcp_proxy.
-
Forward Original SNI - the name of the filter, specifies the intention to forward the SNI, a specific kind of a server name
-
Override Server Name in tcp_proxy, cluster manager etc. it means that the server name of the upstream cluster must be overridden by that value. It does not specify that it is SNI and does not specify where this server name comes from.
This is why I put Forward Requested Server Name in the stream info and not in TCP proxy, to make this artifact independent from the TCP proxy.
CODEOWNERS
Outdated
| # sni_cluster extension | ||
| /*/extensions/filters/network/sni_cluster @rshriram @lizan | ||
| # extension | ||
| /*/extensions/filters/network/forward_original_sni @lizan |
There was a problem hiding this comment.
@lizan Sure, let me extract the non-extension part into a separate PR, I am in favor of separate PRs.
Signed-off-by: Vadim Eisenberg <vadime@il.ibm.com>
Signed-off-by: Vadim Eisenberg <vadime@il.ibm.com>
Signed-off-by: Vadim Eisenberg <vadime@il.ibm.com>
| Forward Original SNI | ||
| ========================= | ||
|
|
||
| The `forward_original_sni` is a network filter that instructs other filters, |
There was a problem hiding this comment.
given this explanation, I think this should be called use_downstream_sni .
The explanation also needs to be tweaked to state that when an inbound connection is using TLS, and the upstream cluster is using mTLS, this option will allow user to automatically set the SNI of upstream cluster to be the same as the downstream SNI.
There was a problem hiding this comment.
@rshriram Agreed, used_downstream_sni is more clear.
Regarding:
The explanation also needs to be tweaked to state that when an inbound connection is using TLS, and the upstream cluster is using mTLS, this option will allow user to automatically set the SNI of upstream cluster to be the same as the downstream SNI.
So why does the explanation not cover the case you are describing? If we can consider mTLS being a kind of TLS: a network filter that instructs other filters, such as tcp_proxy, to forward the SNI value from the downstream connection to the upstream connection
|
@lizan Since this has become an extension and this is very specific to Istio, why can't we move this to istio/proxy, just like the way we moved the tcp_cluster_rewrite to istio/proxy? |
+1, if this is Istio specific please move it. |
|
Yes I'm thinking of that too. the non-extension part (#4973) have to be done before that anyway. |
|
This pull request has been automatically marked as stale because it has not had activity in the last 7 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
|
This pull request has been automatically closed because it has not had activity in the last 14 days. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
|
@lizan Could you please reopen this PR? I would like to complete it for reference, and then I will close it and move it to istio/proxy. |
|
@vadimeisenbergibm feel free to open another PR, this one is already too heavy to open... |
Signed-off-by: Vadim Eisenberg vadime@il.ibm.com
Description: Add
forward_original_snifield to the upstream TLS Context. It will allow forwarding SNI from the downstream connection (extracted by the TLS inspector filter) to the upstream. One of the use cases described in #4076. This flag should be mutually exclusive with thesnifiled ofUpstreamTlsContext.Risk Level:Low
Testing: unit tests
Docs Changes: yes
Release Notes: yes
Related to #4076
Depends on #4973