-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
http3: respecting header number limits #15970
Conversation
Signed-off-by: Alyssa Wilk <[email protected]>
Signed-off-by: Alyssa Wilk <[email protected]>
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.
Thanks for fixing more tests! A few thoughts on the details.
@@ -1600,7 +1600,6 @@ TEST_P(DownstreamProtocolIntegrationTest, ManyRequestHeadersAccepted) { | |||
TEST_P(DownstreamProtocolIntegrationTest, ManyRequestTrailersRejected) { | |||
// QUICHE doesn't limit number of headers. | |||
EXCLUDE_DOWNSTREAM_HTTP3 |
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.
The upstream http3 test failure is irrelevant to this fix right? I doubt current fix works for trailers.
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.
Ah yeah, I should fix that.
@@ -47,12 +47,10 @@ TEST_P(Http2UpstreamIntegrationTest, RouterHeaderOnlyRequestAndResponseNoBuffer) | |||
} | |||
|
|||
TEST_P(Http2UpstreamIntegrationTest, RouterUpstreamDisconnectBeforeRequestcomplete) { | |||
EXCLUDE_UPSTREAM_HTTP3; // Close loop. |
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.
How are these tests related to max headers count?
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.
They're not, I was just enabling excluded tests until I found ones that didn't work =P
static constexpr absl::string_view invalid_underscore = "http3.unexpected_underscore"; | ||
static constexpr absl::string_view too_many_http_headers = "http3.too_many_http_headers"; |
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.
Maybe add/reuse those already defined in Http3ResponseCodeDetailValues? You may need to move it around.
Http::HeaderUtility::HeaderValidationResult result = | ||
validator.validateHeader(entry.first, entry.second); | ||
switch (result) { | ||
case Http::HeaderUtility::HeaderValidationResult::REJECT: | ||
details = invalid_underscore; |
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.
This details is already assigned in server stream's validateHeader().
HeaderValidator& validator) { | ||
std::unique_ptr<T> | ||
quicHeadersToEnvoyHeaders(const quic::QuicHeaderList& header_list, HeaderValidator& validator, | ||
uint32_t max_headers_allowed, absl::string_view& details) { |
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.
Is it because QuicHeaderList doesn't expose size() interface that we need max_headers_allowed to be passed into this function?
I slightly prefer checking it in QUICHE and have something like OnHeadersTooLarge() or simply add QuicHeaderList::size() instead of iterating over the header list again.
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.
100% prefer checking in QUICHE and rejecting early, vs rejecting late in the game, but I think this is still better than nothing because it protects Envoy filters against too many headers. What do you think about landing this as-is and moving where we enforce once someone on quic-dev adds the knob we'd need?
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.
SGTM.
if (headers == nullptr) { | ||
onStreamError(close_connection_upon_invalid_header_); | ||
onStreamError(close_connection_upon_invalid_header_, quic::QUIC_STREAM_INTERNAL_ERROR); |
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.
This is not negotiated in initial SETTINGS. I think it should be QUIC_BAD_APPLICATION_PAYLOAD or at least something else other than QUIC_STREAM_INTERNAL_ERROR?
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.
Ah, so the quiche code maps bad application payload to Http::StreamResetReason::ProtocolError which is only for spec violations. We differentiate between envoy rejecting something which it is configured to reject from actual standards violantion by response code (503/502) so we need to have a different code for header limit checks. I don't care which but it has to translate to something which isn't an Envoy ProtocolError
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.
How about QUIC_STREAM_EXCESSIVE_LOAD ?
Signed-off-by: Alyssa Wilk <[email protected]>
Signed-off-by: Alyssa Wilk <[email protected]>
Signed-off-by: Alyssa Wilk <[email protected]>
Signed-off-by: Alyssa Wilk <[email protected]>
Signed-off-by: Alyssa Wilk <[email protected]>
Signed-off-by: Alyssa Wilk <[email protected]>
HeaderValidator& validator) { | ||
std::unique_ptr<T> | ||
quicHeadersToEnvoyHeaders(const quic::QuicHeaderList& header_list, HeaderValidator& validator, | ||
uint32_t max_headers_allowed, absl::string_view& details) { |
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.
SGTM.
if (headers == nullptr) { | ||
onStreamError(close_connection_upon_invalid_header_); | ||
onStreamError(close_connection_upon_invalid_header_, quic::QUIC_STREAM_INTERNAL_ERROR); |
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.
How about QUIC_STREAM_EXCESSIVE_LOAD ?
if (received_trailers().size() > filterManagerConnection()->maxIncomingHeadersCount()) { | ||
details_ = Http3ResponseCodeDetailValues::too_many_trailers; | ||
onStreamError(close_connection_upon_invalid_header_); | ||
return; | ||
} |
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.
Same for client stream?
@@ -1622,13 +1617,12 @@ TEST_P(DownstreamProtocolIntegrationTest, ManyRequestTrailersRejected) { | |||
EXPECT_TRUE(response->complete()); | |||
EXPECT_EQ("431", response->headers().getStatusValue()); | |||
} else { | |||
ASSERT_TRUE(response->waitForReset()); |
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.
should this be reverted?
Signed-off-by: Alyssa Wilk <[email protected]>
Signed-off-by: Alyssa Wilk <[email protected]>
Signed-off-by: Alyssa Wilk <[email protected]>
Signed-off-by: Alyssa Wilk <[email protected]>
Signed-off-by: Alyssa Wilk <[email protected]>
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.
Seems right to me, just one tiny nit
static constexpr absl::string_view remote_refused = "http3.remote_refuse"; | ||
// The peer reset the stream. | ||
static constexpr absl::string_view remote_reset = "http3.remote_reset"; | ||
// Too many trailers were sent |
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.
period
Signed-off-by: Alyssa Wilk <[email protected]>
Looks like an asan flake in a new test |
Signed-off-by: Alyssa Wilk <[email protected]>
Signed-off-by: Alyssa Wilk <[email protected]>
Signed-off-by: Alyssa Wilk <[email protected]>
woot! period added, merge conflicts sorted, test flake fixed :-) |
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.
Thanks!
Respecting upstream and downstream caps on number of headers for HTTP/3 Risk Level: n/a (http/3) Testing: turned up integration tests Docs Changes: n/a Release Notes: n/a envoyproxy#14829 among others. Signed-off-by: Alyssa Wilk <[email protected]> Signed-off-by: Gokul Nair <[email protected]>
Respecting upstream and downstream caps on number of headers for HTTP/3 Risk Level: n/a (http/3) Testing: turned up integration tests Docs Changes: n/a Release Notes: n/a envoyproxy#14829 among others. Signed-off-by: Alyssa Wilk <[email protected]> Signed-off-by: Gokul Nair <[email protected]>
Respecting upstream and downstream caps on number of headers for HTTP/3 Risk Level: n/a (http/3) Testing: turned up integration tests Docs Changes: n/a Release Notes: n/a envoyproxy#14829 among others. Signed-off-by: Alyssa Wilk <[email protected]> Signed-off-by: Gokul Nair <[email protected]>
Respecting upstream and downstream caps on number of headers for HTTP/3
Risk Level: n/a (http/3)
Testing: turned up integration tests
Docs Changes: n/a
Release Notes: n/a
#14829 among others.