codec: Raise max_request_headers_kb limit to 96 KiB#5859
codec: Raise max_request_headers_kb limit to 96 KiB#5859alyssawilk merged 42 commits intoenvoyproxy:masterfrom
Conversation
Signed-off-by: Auni Ahsan <auni@google.com>
Signed-off-by: Auni Ahsan <auni@google.com>
Signed-off-by: Auni Ahsan <auni@google.com>
|
What's missing this PR is an actual runtime call of |
Signed-off-by: Auni Ahsan <auni@google.com>
|
Hey Auni, as discussed offline, ping me when CI is happy? /wait |
|
Hi! I need some input on how to resolve this. Essentially, my test is failing because the nghttp2 library max request headers check, which I now manually configure, trips differently from the existing codec check. The codec check at codec_impl.cc:563 will check if the headers exceed the limit and reset the stream if so, while the nghttp2 library check will just flat-out close the stream. How should I resolve this? Two ideas:
Thoughts? |
|
Ahh, some more details. The library check triggers before any header bytes are dispatched to the library, so server_callbacks_.newStream() is never called (and so it's never reset, which is why my test fails). So yeah again, I could configure the library check up high as I suggested to never get hit, or we could decide that behaviour is useful. |
Signed-off-by: Auni Ahsan <auni@google.com>
|
OK so I went with an arbitrarily hard-coded nghttp2 max-header-len setting of 100kb. This can be easily changed or be configurable later, but this changes no envoy behaviour. (Both before and after this PR, the nghttp2 max check will not ever be triggered.) |
Signed-off-by: Auni Ahsan <auni@google.com>
|
/retest |
|
🔨 rebuilding |
alyssawilk
left a comment
There was a problem hiding this comment.
Thanks for continuing to plug away at these!
| // of kept alive HTTP/2 connections. | ||
| nghttp2_option_set_no_closed_streams(options_, 1); | ||
| nghttp2_option_set_no_auto_window_update(options_, 1); | ||
| nghttp2_option_set_max_send_header_block_length(options_, |
There was a problem hiding this comment.
Isn't this the setting for the size of an individual header frame? I think we want to change the total allowed headers, not the per-frame limits.
There was a problem hiding this comment.
IIRC this is not very well named, but I think this does actually set the header send limit, and the library will chunk it into frames using continuation frames if necessary. @auni53 to check me here.
There was a problem hiding this comment.
Could be. I'm not seeing any other size-related fields to tweak. I'd checked
https://nghttp2.org/documentation/nghttp2_option_set_max_send_header_block_length.html
"This option sets the maximum length of header block (a set of header fields per one HEADERS frame) to send. "
It was the "per one HEADERS frame" that got me thinking it might be the wrong field.
in code it's used in prep_frame which I thought was after the chunking but I could easily be misremembering. I'm happy to let Auni do the code sleuthing though :-)
There was a problem hiding this comment.
Yeeee, I'm pretty certain this is the right call. Also because I did this TDD-style and the testing behaviour checks out.
| request_encoder_->encodeHeaders(request_headers, true); | ||
| } | ||
|
|
||
| TEST_P(Http2CodecImplTest, TestSingleLargeHeadersWayOverDefaultCodecLimit) { |
There was a problem hiding this comment.
If your goal is to test an unexpectedly large header frame, you could have several keys with fairly long strings.
It makes sense to both limit the size of overall headers as well as the size of any individual header, and I think rejecting a single header key or value of 65536 bytes is totally reasonable :-)
There was a problem hiding this comment.
Already had a test with several long strings! But I rearranged/reworded this stuff. Discussed offline, and I'm going to turn up this test to fail on single-large-header and document the nghttp2 limit in the max_request_headers_kb api.
mattklein123
left a comment
There was a problem hiding this comment.
Thanks for working on this, some comments/questions.
/wait
| // of kept alive HTTP/2 connections. | ||
| nghttp2_option_set_no_closed_streams(options_, 1); | ||
| nghttp2_option_set_no_auto_window_update(options_, 1); | ||
| nghttp2_option_set_max_send_header_block_length(options_, |
There was a problem hiding this comment.
IIRC this is not very well named, but I think this does actually set the header send limit, and the library will chunk it into frames using continuation frames if necessary. @auni53 to check me here.
Signed-off-by: Auni Ahsan <auni@google.com>
Signed-off-by: Auni Ahsan <auni@google.com>
Signed-off-by: Auni Ahsan <auni@google.com>
Signed-off-by: Auni Ahsan <auni@google.com>
This reverts commit 999b247. Signed-off-by: Auni Ahsan <auni@google.com>
|
Hi @mattklein123, working on some changes to this. I'm having an issue with the http codec configuration I could use some input on. Basically, to set the http parser limits you need to call http_parser_set_max_header_size(x). What I'm finding from my testing is that this setting persists across test runs, i.e. making that call in one http1/codec_impl test affects the success of a different test. I had thought previously that each envoy codec would be instantiating its http parser separately, but it looks like these settings are global. Does that make sense? |
Signed-off-by: Auni Ahsan <auni@google.com>
|
Oky I changed the ClientConnectionImpl max response headers from a default parameter to a class constant, added a test for large response headers rejection, and tweaked the API comment. |
Signed-off-by: Auni Ahsan <auni@google.com>
Signed-off-by: Auni Ahsan <auni@google.com>
|
Ok, updated with Matt's suggestion on the API commenting + added a note on nghttp2 to the test file. I got a mysql_integration_test failure, hoping that was a flake bc idk how I'd have touched that; will look further into it if that persists. |
|
Yep, that's a known and fixed flake. If you merge master you'll pick up the fix |
Signed-off-by: Auni Ahsan <auni@google.com>
mattklein123
left a comment
There was a problem hiding this comment.
Thank you LGTM assuming it passes @alyssawilk muster!
alyssawilk
left a comment
There was a problem hiding this comment.
Looking great - just a few more minor nits from me and you should be good to go.
| header_parsing_state_ = HeaderParsingState::Value; | ||
| current_header_value_.append(data, length); | ||
|
|
||
| uint32_t total = |
| // Set true between receiving 100-Continue headers and receiving the spurious onMessageComplete. | ||
| bool ignore_message_complete_for_100_continue_{}; | ||
|
|
||
| // The default limit of 80 KiB is the vanilla http_parser behaviour. |
There was a problem hiding this comment.
The default limit is 80Kb (Kilobytes) not KiB (Kibibytes), no?
There was a problem hiding this comment.
Wow, I forgot kibibytes were a thing. In any case, I checked http_parser.h:63, looks like it's indeed KiB.
There was a problem hiding this comment.
Oh jeez, trusted the http_parser issue which was incorrect - looks like they were saying KB when they meant KiB. You can ignore this one.
bazel/external/http-parser.BUILD
Outdated
| "http_parser.h", | ||
| ], | ||
| hdrs = ["http_parser.h"], | ||
| copts = ["-DHTTP_MAX_HEADER_SIZE=0x7fffffff"], |
There was a problem hiding this comment.
Actually sorry, on second thought I'm having a moment of paranoia. We don't have anywhere else in the Envoy code base where we use http_parser so this is 100% OK today but what do we think of adding a limit just in case? If we added a 200KB limit or some such it'd be very safely above our window such that we should never hit the http_parser limits in the codec, without allowing total infinite memory if someone else uses http parser.
Thoughts?
|
|
||
| // The max send header block length is configured to an arbitrarily high number so as to never | ||
| // trigger the check within nghttp2, as we check request headers length in codec_impl::saveHeader. | ||
| nghttp2_option_set_max_send_header_block_length(options_, 0x7fffffff); |
|
/retest |
|
🔨 rebuilding |
Bump up max configurable max_request_headers_kb to 96 KiB. Add a check to http1/codec_impl.cc for headers size. Raise the default library limits in http_parser nghttp2 so we'll rely on our own codec check. Risk Level: Medium. Testing: Moved all the large request headers tests to ProtocolIntegrationTest. Part of envoyproxy#5626. Signed-off-by: Auni Ahsan <auni@google.com> Signed-off-by: Fred Douglas <fredlas@google.com>
…iB (#15921) Commit Message: Raise max configurable max_request_headers_kb limit to 8192 KiB (8MiB) from 96 KiB in http connection manager protobuf. Additional Description: Added/Updated relevant unit tests and integration tests. This change will allow increasing max_request_headers_kb to 8MiB from http connection manager's configuration. The change is mainly updating the limit in a validation check in the protobuf. Also, the old (merged) PR #5859 is read, no nghttp2 library-related issues are observed on raising the max_request_headers_kb beyond 96 KiB. Risk Level: Low Testing: Unit, Integration, Manual Docs Changes: Inline in proto file. Signed-off-by: Anirudha Singh <ps.anirudha@gmail.com>
…iB (envoyproxy#15921) Commit Message: Raise max configurable max_request_headers_kb limit to 8192 KiB (8MiB) from 96 KiB in http connection manager protobuf. Additional Description: Added/Updated relevant unit tests and integration tests. This change will allow increasing max_request_headers_kb to 8MiB from http connection manager's configuration. The change is mainly updating the limit in a validation check in the protobuf. Also, the old (merged) PR envoyproxy#5859 is read, no nghttp2 library-related issues are observed on raising the max_request_headers_kb beyond 96 KiB. Risk Level: Low Testing: Unit, Integration, Manual Docs Changes: Inline in proto file. Signed-off-by: Anirudha Singh <ps.anirudha@gmail.com> Signed-off-by: Gokul Nair <gnair@twitter.com>
|
@mattklein123 @alyssawilk Sorry to tag on a old issue. Since it has context - Couple of questions
|
|
cc @RyanTheOptimist @yanavlasov @KBaichoo also on ^ |
|
@ramaraochavali Can you file an issue about there were we can discuss the details? I think that's probably better than a 4 year old already committed PR :) Please feel free to link to this PR or any related issues there. |
|
@RyanTheOptimist created #26690 |
Signed-off-by: Auni Ahsan auni@google.com
Bump up max configurable
max_request_headers_kbto 96 KiB.Add a check to http1/codec_impl.cc for headers size.
Raise the default library limits in http_parser (at compilation) and nghttp2 (at options) to 0x7fffffff, so we'll rely on our own codec check.
Risk Level: Medium.
Testing: Moved all the large request headers tests to ProtocolIntegrationTest.
Part of #5626.