Kestrel WebTransport rejects RFC 9297 clients: H3_DATAGRAM uses draft codepoint 0xffd277 instead of 0x33

Open
#70,384 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
42/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
csharp

Research direction

Start with src/Servers/Kestrel/Core/src/Internal/Http3/Http3SettingType.cs, then trace how datagram settings and WebTransport request detection are handled in Http3Stream and WebTransportSession. Check the existing WebTransport follow-ups in #42788 for scope and tests. Done means RFC 9297 clients can negotiate datagrams and the accepted WebTransport version behavior is defined; the issue does not name specific tests.

Written by the indexing model from the issue text.

Description

area-networking feature-kestrel
Is there an existing issue for this?
  • I have searched the existing issues
Describe the bug

Kestrel's WebTransport accepts only the pre-RFC HTTP/3 datagram setting, so standards-compliant WebTransport clients other than Chrome cannot open a session.

Http3SettingType.H3Datagram is 0xffd277, the codepoint from draft-ietf-masque-h3-datagram:

https://github.com/dotnet/aspnetcore/blob/main/src/Servers/Kestrel/Core/src/Internal/Http3/Http3SettingType.cs

RFC 9297 (published 2022) assigns SETTINGS_H3_DATAGRAM = 0x33. A client that sends only 0x33, as RFC 9297 says, is read as having no datagram support. Http3Stream then fails the extended CONNECT:

HTTP/3 stream error (SettingsError): HTTP/3 datagrams negotiation mismatch. Client support: 'False'. Server support: 'True'.

Kestrel also advertises only 0xffd277, so RFC clients never see the server's datagram support either.

Chrome works only because it still sends both codepoints. The Rust wtransport crate (0.7.2) and other clients that follow RFC 9297 are rejected.

A related gate: a request is treated as WebTransport only when it carries sec-webtransport-http3-draft02: 1 (WebTransportSession.CurrentSupportedVersion). Later drafts of draft-ietf-webtrans-http3 removed that header in favour of SETTINGS_WT_MAX_SESSIONS and the WT-Available-Protocols / version negotiation. A client that targets a newer draft and omits the header gets IsWebTransportRequest == false, even when its settings match.

Expected Behavior
  • Kestrel advertises SETTINGS_H3_DATAGRAM = 0x33 (it may keep sending 0xffd277 as well for older clients).
  • Kestrel treats a peer as datagram-capable when either 0x33 or 0xffd277 is 1.
  • Ideally, the draft02 version header stops being the only path to IsWebTransportRequest, or the version that's accepted is documented and configurable.
Steps To Reproduce
  1. Linux with libmsquic 2.6.2, .NET SDK 11.0.100-rc.3.26522.148.
  2. Run a Kestrel host:
    • AppContext.SetSwitch("Microsoft.AspNetCore.Server.Kestrel.Experimental.WebTransportAndH3Datagrams", true)
    • WebApplication.CreateSlimBuilder() + builder.WebHost.UseQuic()
    • listen with HttpProtocols.Http1AndHttp2AndHttp3 on a fixed port with a self-signed ECDSA certificate (validity under 14 days)
    • app.Run(async ctx => await ctx.Features.Get<IHttpWebTransportFeature>()!.AcceptAsync(ctx.RequestAborted))
  3. Connect with wtransport 0.7.2, pinning the certificate hash with ClientConfig::builder().with_bind_default().with_server_certificate_hashes([...]), then Endpoint::client(cfg)?.connect("https://127.0.0.1:<port>/wt").
  4. The client gets ConnectionError(LocallyClosed). Kestrel trace logs show the H3_SETTINGS_ERROR above on the CONNECT stream.
  5. Patch the client to also send setting 0xffd277 = 1. The CONNECT now reaches the app but IsWebTransportRequest is false (the client gets SessionRejected).
  6. Also add the header sec-webtransport-http3-draft02: 1. The session is accepted, and bidirectional streams round-trip correctly.

So once the client imitates Chrome's legacy codepoints, the rest of Kestrel's WebTransport implementation interoperates fine. The only problems are the setting codepoint and the version header.

Exceptions (if any)
Microsoft.AspNetCore.Connections.ConnectionAbortedException: HTTP/3 stream error (SettingsError): HTTP/3 datagrams negotiation mismatch. Client support: 'False'. Server support: 'True'.
 ---> Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http3.Http3StreamErrorException: HTTP/3 stream error (SettingsError): HTTP/3 datagrams negotiation mismatch. Client support: 'False'. Server support: 'True'.
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http3.Http3Stream.ProcessHeadersFrameAsync[TContext](...)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http3.Http3Stream.ProcessRequestAsync[TContext](...)
.NET Version

11.0.100-rc.3.26522.148

Anything else?
  • Probably belongs with the WebTransport follow-ups in #42788.
  • A smaller trap we hit while testing: CreateSlimBuilder() does not register the QUIC transport. Without UseQuic(), an Http1AndHttp2AndHttp3 endpoint binds TCP only and logs no warning. A warning when HTTP/3 is requested but no multiplexed transport is registered would have saved us a lot of time.
Dominant language
C#
Stars
38.5k
Forks
11.6k
Avg merge
3d 1h
Merged PRs (30d)
289

Getting set up

Open in Codespaces

Starts the project's dev container in your browser, under your own GitHub account.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from dotnet/aspnetcore

All issues in dotnet/aspnetcore

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.