dotnet / dotnet/aspnetcore

Kestrel enforces non-default HTTP/2 limits before the Settings ack

Open
#17,842 3 comments 0 reactions 0 assignees View on GitHub
affected-very-few area-networking enhancement feature-kestrel HTTP2 severity-nice-to-have
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 10h
Merged PRs (30d)
281

Description

At the start of a h2 connection the client and server advertise their non-default settings to each other. However, the client can start sending requests before it receives the settings. The server is supposed to assume default settings until the client ack's the settings (with a timeout), but Kestrel does not, it assumes its own initial settings.

Kestrel has two settings it sets to lower than the default, SETTINGS_MAX_HEADER_LIST_SIZE and SETTINGS_MAX_CONCURRENT_STREAMS. The trouble with both of these settings is that the spec default is infinite, allowing infinite for either would be untenable, even for a short period of time.

The good thing about SETTINGS_MAX_CONCURRENT_STREAMS is that they're rejected with REFUSE_STREAM, meaning they're explicitly re-tryable, and HttpClient does retry them. The resets don't arrive until after the settings frame, so the retry will always happen with knowledge of the expected settings. The stream limit issue also contributes to https://github.com/aspnet/AspNetCore/issues/17484.

SETTINGS_MAX_HEADER_LIST_SIZE is less of a concern because the request is going to fail whether the client knows about the limit or not, there's no automated way to make the request smaller.

Having now written this up, I don't think kestrel has any alternatives in these scenarios. Temporary infinite limits are untenable and a client could run into the same issues even if we used more forgiving temporary non-infinite limits.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.