-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
HTTP/1.1 TLS Upgrade (RFC-2817) causes upgrade_failed #36305
Comments
cc @alyssawilk |
So Envoy doesn't support this feature by default, but I think you could in fact get it to work by configuring Envoy to accept this type of upgrade: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/http/upgrades |
I don't think the request here is to have TLS upgrades succeed, but to have Envoy ignore the upgrade request and continue with no upgrade and no error. |
What @ggreenway said, but just to add on, while i think the spec is ambiguous, i tested a few other proxies, and they all ignore it. The Apache HttpClient folks have closed the issue as "invalid" (which i disagree with). Given all this, I think de-facto we should ignore it. |
Ah, when it comes to issues of security I lean towards being strict, rather than possibly increasing attack surface. |
Sounds good, but how to have Envoy ignore the upgrade request? |
specify the upgrade type in upgrade configs: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/http/upgrades |
The current fix is to do the below at the HTTP Connection Manager, which will allow these requests to pass through
|
👋 team, we are a large consumer of Envoy proxy and have started to experience the production impact of this issue in our service mesh. I would like to kindly encourage the Envoy team to prioritise formulating a position on this issue (plans to fix it, if any, how, and maybe a rough ETA), as it will help many users devise the appropriate guardrails in their enterprise workloads. 🙇 |
I know this was originally filed as a bug, but given the ambiguity of the spec (and that allowing upgrades by default has negative security implications) I think it's a feature request. Unfortunately Envoy is supported on a volunteer basis - we don't have a core team dedicated to features, so any additions to Envoy are contributed by the companies that desire those features. If your service mesh is negatively impacted we encourage you to become envoy contributors so you can address it! |
I don't see how the spec is ambiguous. It says the server should either accept the upgrade request or decline it by ignoring it. If Envoy does not do this it is clearly incompatible with RFC-2817. For me it sounds like a bug, not a feature. |
@alyssawilk, could you assist potential contributors by providing guidance on how the Envoy configuration should look if we want to add an option to ignore (specific?) upgrade requests? Alternatively, could you direct us to someone who can help? This would greatly clarify the effort needed to contribute a fix for this issue. |
@chlunde I'd suggest extending the UpgradeConfigs with a passthrough option. |
I think the best option for ignoring an upgrade request is to strip the upgrade header before sending the request to the upstream, so that there can't be any confusion between envoy and the upstream about whether an upgrade is happening or not. We can add configuration for this to UpgradeConfig to ignore specific upgrade types, or we could consider adding an option to ignore any unknown upgrade. |
I'm looking at https://www.rfc-editor.org/rfc/rfc2817#section-5 and trying to understand if a passthrough option makes sense in this context?
|
I'm working on a fix for this right now. If I don't have time to finish it, I'll at least post a draft PR that someone can take and finish this. |
Fixes envoyproxy#36305 Signed-off-by: Greg Greenway <[email protected]>
Since I was tagged in #37150 and replied there, I'm adding the same context here: There's an important distinction between HTTP versions here:
They behave differently: in particular, in HTTP/1.1 the server can "ignore" the Upgrade and still send a successful HTTP/1.1 response without upgrading to a different protocol. In HTTP/2 and 3 however, that is not possible. If the server does not wish to use the other protocol, it has no choice but to reject the request. This gets particularly tricky because Envoy normalizes every Extended CONNECT internally to look like Upgrade. So the information of whether ignoring is allowed or not gets somewhat hard to track down inside Envoy. I worry that allowing Envoy to ignore upgrades will cause protocol confusion or request smuggling attacks, unless there are strong safeguards in place to ensure that this cannot happen in HTTP/2 or HTTP/3. |
Would it be a good idea to also propose that RFC 2817 optional client initiated upgrade mechanism be deprecated? Does anyone here have the resources to do so and think it is a good idea? https://github.com/httpwg/http-core/blob/main/CONTRIBUTING.md#proposing-new-work I believe it has several security implications that make it problematic in modern contexts. Some examples of issues:
What does it help for?A misconfigured client and a passive eavesdroppers. AlternativesHSTS, HTTPS Everywhere, rejecting HTTP requests, automatic redirects from HTTP to HTTPS, and simply initiating requests on port https/port 443 instead of 80 by default |
@chlunde I totally agree with your intent here - upgrading to TLS is incredibly insecure, and clients should instead always connect directly over HTTPS. Unfortunately, RFC 2817 is still used in the real-world by the Internet Printing Protocol, see Section 8.2 of RFC 8010. So it doesn't make sense to mark RFC 2817 as obsolete. Even if it should be avoided in almost all cases. That said, deprecating the feature from Envoy is a different question, but I don't know if anyone is using it. |
We don't have any intention to make TLS upgrades work; I'm just trying to make Envoy ignore those upgrade requests instead of failing requests, to increase compatibility with clients (such as https://issues.apache.org/jira/browse/HTTPCLIENT-2344) which insist on using this upgrade type. |
I see. Thanks for the context! |
The approach in #37150 didn't work due to how the http1 codec changes behavior when it thinks its handling an upgrade. A fix for this would probably have to be in the http1 codec_impl, but that doesn't have access to the configured upgrades which are processed later, so it would probably need to be a change that specifically ignores TLS upgrades, similar to how we ignore h2c upgrades now. |
I'm out of time to address this; I'll leave this to someone else. Here's a rough patch that could fix this for TLS upgrades specifically, but I don't like hard-coding another upgrade type to ignore; configuration would be better.
|
The same goes for my org! Is envoy team actively looking for a workaround? |
I don't believe anyone is currently working on this. |
@ggreenway thank you, I'll try to find somebody to work on it |
/cc @krinkinmu @grnmeira @Stevenjin8 do any of you have bandwidth to look into this? |
@keithmattix I don't have time at the moment and will look at this on Friday and see what I can do. |
Hey, we've got someone working on this at the moment and he has a working prototype we think. Let's see where he gets to, to save duplicated effort? |
Hi, I've extended @ggreenway 's codec approach to make it configurable and remain as a rejection by default #37642 |
Title: HTTP/1.1 TLS Upgrade (RFC-2817) causes upgrade_failed
Description:
RFC-2817 specifies two ways for a client to indicate an optional TLS upgrade in HTTP/1.1. The first is via a CONNECT and the second is by sending the
Connection: upgrade
header and anUpgrade
header field with the upgrade protocols. However, sending this to Envoy currently will cause a 403 withupgrade_failed
.Notably the RFC states:
This is a little bit ambiguous, but my reading is that the options are to either ignore it or to upgrade, but rejecting the request entirely isn't an option.
RFC-9110 gives us the same ambiguity:
The envoy source tells us why it might be rejecting the upgrade entirely:
Repro steps:
Make a request over plaintext HTTP/1.1 with
'Connection: Upgrade'
and'Upgrade: TLS/1.3'
headers setThis came up because Apache HttpComponents HttpClient added RFC-2817 headers as default in 5.4 (apache/httpcomponents-client#542). This was released as GA this past week, so should start to hit people as they upgrade.
The bigger issue is the default behavior of HttpClient. I have filed an issue there https://issues.apache.org/jira/browse/HTTPCLIENT-2344. However, we should consider whether we are being spec compliant vs the conservative approach to rejecting these requests.
The text was updated successfully, but these errors were encountered: