-
Notifications
You must be signed in to change notification settings - Fork 10k
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
Detect HTTP/1.1 on HTTP/2 connection #39358
Conversation
Could we accomplish most of this by adding more content to Http2ErrorInvalidPreface without doing the additional checks? How much does it matter which specific version we detected? We could make multiple recommendations in the same error message. A lot of the people that run into this aren't even looking at the server logs, they only notice a connection abort on the client. If we detected HTTP/1.x would it be possible to send back a hard coded 400 response before aborting the connection? |
/azp run |
Needs a full re-run given #39361. |
Azure Pipelines successfully started running 3 pipeline(s). |
Is sending back HTTP/1.1 on a HTTP/2 connection be legal? Sure, the client is wrong, but do two wrongs make a right? Changing the server response is a much bigger piece of work. To do that I think this would need to be completely robust (i.e. when detecting the error, read additional content until either the end of the line or max request line length is reached). Then send a valid HTTP/1.1 response. That's a lot more work. Agree that returning an error to the client would help more people, but this is a start. |
But it's not an HTTP/2 connection, is it? This check says the client is trying to do HTTP/1.x. The server hoped for HTTP/2 but didn't get it. The goal is to respond in a way the client will understand. |
Ok. I want to understand what is the ideal solution. It is more work than I expected to do so I want to make sure it is done right the first time and I don't spend time doing something that people don't want. Proposal:
|
Sounds right. The other case to consider in this code path is |
@Tratcher Updated. Needs tests and cache the hardcoded response. Otherwise, is this what you had in mind? |
src/Servers/Kestrel/Core/src/Internal/Infrastructure/KestrelTrace.cs
Outdated
Show resolved
Hide resolved
Exactly, it gives us a chance to tell the client what they did wrong without them having to go dig through the server logs. |
Co-authored-by: Chris Ross <chrross@microsoft.com>
Why isn't a connection error thrown from matching the preface if the reader ends before reading up to the preface length? In that case Is that against the spec - https://httpwg.org/specs/rfc7540.html#rfc.section.3.5 - Bug? I updated |
If the reader ends then the connection is likely already closed. It's also common for port scanners to connect but not send any data. Neither case requires a response, or an exception log. |
Ok. FYI today the server returns a GOAWAY frame with NO_ERROR. If you think nothing should be sent then that would be a change. I'm going to leave current behavior as-is and update my tests in this area. |
Have you tried it with HttpClient to make sure it works as expected? |
Yes, but manually. Not in an integration test. I'll see if I can add one. |
|
||
if (state.HasFlag(ReadPrefaceState.Http1x)) | ||
{ | ||
if (ParseHttp1x(readableBuffer, out var detectedVersion)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: It's not super obvious from the name that ParseHttp1x
returns true
when the MaxRequestLineSize
is exceeded before an \r
could be found. Maybe ParseHttp1x
should just update the ReadPrefaceState
or return its own tri-state enum.
Addresses #14884
What do we think? It's not perfect, but it should be a lot more informative in most cases. And extra work only happens if request is already been rejected so has no perf impact. Will add unit tests if this idea has merit.
Also, we can do something similar for HTTP/1.1 (on invalid request line, check if the content is an HTTP/2 connection preface)