镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Support Windows 10 for System.Net.Quic #101200

Closed

Description

@StephenCleary

I would love to see Win10 support added to System.Net.Quic OOTB.

I can see this happening one of two ways:

  1. The SChannel updates in Win11 can be backported to Win10 and released to that OS.
  2. msquic can use OpenSSL by default on all platforms rather than using SChannel on some.

Regardless of the solution specifics, my goal is including Win10 support in the default System.Net.Quic NuGet.

Activity

  1. dotnet-policy-service commented on Apr 17, 2024

    @dotnet-policy-service
    Contributor

    Tagging subscribers to this area: @dotnet/ncl
    See info in area-owners.md if you want to be subscribed.

  2. added this to the Future milestone on Apr 23, 2024
  3. added
    enhancementProduct code improvement that does NOT require public API changes/additions
    and removed
    untriagedNew issue has not been triaged by the area owner
    on Apr 23, 2024
  4. rzikm commented on May 3, 2024

    @rzikm
    Member

    The SChannel updates in Win11 can be backported to Win10 and released to that OS.

    That is a request that would have to go to SChannel team, but I don't think they will be willing to backport these changes.

    msquic can use OpenSSL by default on all platforms rather than using SChannel on some.

    MsQuic team already publishes both SChannel and OpenSSL-based build of MsQuic, while not "out of the box", you can run System.Net.Quic on Windows 10 already by replacing the msquic.dll in the published application with the OpenSSL-based one.

    I raised a (no-merge) PR which replaces the msquic used by runtime by OpenSSL-MsQuic #101849. The tests are all passing except one test which tests that we throw correct diagnostic exception for a scenario which is not possible with Schannel. So at least on paper there is nothing technical preventig us from switching.

    That being said, switching to OpenSSL-MsQuic for public .NET releases may be problematic. It would probably be best to follow the model we use in Linux, where .NET does not ship with msquic.so, but expects it to be installed by a package manager. This way the user can install the appropriate version (OpenSSL vs Schannel) for the Windows version and have potentially quicker access to MsQuic updates than monthly .NET servicing.

  5. StephenCleary commented on May 18, 2024

    @StephenCleary
    ContributorAuthor

    I cloned this repo and tried out building my own System.Net.Quic NuGet library, but it wasn't really clear how to do that. If I can make the same modifications and build my own NuGet package, that would be fine; but I'd want to run it on the stock runtime.

    I also checked the official net9.0 supported OSes, and Win10 is definitely in the list (as I would expect). If it were just a matter of supporting HTTP/3 when possible and falling back to HTTP/2, this current situation would be fine. But if QUIC itself (i.e., System.Net.Quic) is considered part of the runtime proper, then I'd expect QUIC support on all platforms the runtime supports. Again, IMO.

    Now that I've typed all this out, it occurs to me that I could create my own Custom.System.Net.Quic by modifying the NuGet library itself (specifically, its dependencies) rather than attempting a proper fork. Would you say that's a viable path forward? It would assume the msquic API is binary-identical for both backends. And I'm also assuming there wouldn't be an issue with running the Custom.System.Net.Quic on a runtime that might be different than the one it was originally built with.

  6. rzikm commented on May 20, 2024

    @rzikm
    Member

    But if QUIC itself (i.e., System.Net.Quic) is considered part of the runtime proper, then I'd expect QUIC support on all platforms the runtime supports. Again, IMO.

    That would certainly be ideal, but sometimes there are platform gaps which make it difficult to have all features working on all platforms. To give few another example, TLS1.3 is not supported on OSX (#1979), and, neither is System.Net.Quic (because MsQuic does not officially support OSX yet I think).

    Now that I've typed all this out, it occurs to me that I could create my own Custom.System.Net.Quic by modifying the NuGet library itself (specifically, its dependencies) rather than attempting a proper fork. Would you say that's a viable path forward? It would assume the msquic API is binary-identical for both backends. And I'm also assuming there wouldn't be an issue with running the Custom.System.Net.Quic on a runtime that might be different than the one it was originally built with.

    You can take the source code for System.Net.Quic and compile your own library, but this will not replace the built-in System.Net.Quic.* types, existing libraries (like ASP.NET Core) will still be using the System.Net.Quic.* types they were compiled against.

    Maybe, you could just reference the MsQuic-OpenSSL NuGet and have it overwrite the msquic.dll on publish using something like

        <PackageReference Include="Microsoft.Native.Quic.MsQuic.OpenSSL"
                          Version="$(MicrosoftNativeQuicMsQuicOpenSSLVersion)"
                          PrivateAssets="all"
                          GeneratePathProperty="true" />
    
        <NativeBinPlaceItem Include="$(PkgMicrosoft_Native_Quic_MsQuic_OpenSSL)\build\native\bin\$(TargetArchitecture)\*" />

    this will not work during normal development, as we search for the msquic.dll in the same directory as System.Net.Quic.dll (on windows), but this could work for self-contained deployments.

  7. StephenCleary commented on May 21, 2024

    @StephenCleary
    ContributorAuthor

    this will not replace the built-in System.Net.Quic.* types, existing libraries (like ASP.NET Core) will still be using the System.Net.Quic.* types they were compiled against.

    I'm fine with that.

    Perhaps I should have started with my goal. I want to write an app that:

    • Uses its own custom protocol over QUIC (nothing to do with HTTP).
    • Runs on Windows 10.

    Ideally, I'd like to enable this same ability for other apps, too, so it would be even better if I can write a library that:

    • Provides the same API as System.Net.Quic.
    • Runs on Windows 10.

    Hence my current thinking:

    1. Figure out how to transform System.Net.Quic.nuget into Something.System.Net.Quic.nuget.
    2. Wire this up to monitor the NuGet feed and auto-publish (this part I already know how to do).
    3. Write my app using Something.System.Net.Quic.nuget.
  8. rzikm commented on Jun 11, 2024

    @rzikm
    Member

    We have discussed this within the team, we could alter the loading code for msquic.dll so that it would first look for msquic.dll next to the entry assembly (and on windows only).

    This should allow you to reference Microsoft.Native.Quic.MsQuic.OpenSSL and have the build process place it's binaries to the output directory (using something similar to the xml snippet in my earlier comment).

    The change I am proposing would make it work for both development workflows (I tested that dotnet run loads the dll, did not test in Visual Studio) and published apps.

    Is this something that would work for you, @StephenCleary? while not OOB, it would only require a couple of lines in the csproj file of the application. This would be for .NET 9.0+ only, I don't see us backporting this to older releases.

  9. StephenCleary commented on Jun 11, 2024

    @StephenCleary
    ContributorAuthor

    I think that would work fine, thanks!

  10. self-assigned this
    on Jun 11, 2024
  11. ethindp commented on Mar 28, 2025

    @ethindp

    What is the status on this? Chiming in here because I'm writing an app that will hopefully use QUIC, but even if I include the OpenSSL MSQuic library it still refuses to load it and IsSupported on both listener and connection return false. I've done some digging and it looks like it does this because it checks to see if the windows version is a windows 11 version and assumes SChannel all the time.

  12. rzikm commented on Mar 31, 2025

    @rzikm
    Member

    I've done some digging and it looks like it does this because it checks to see if the windows version is a windows 11 version and assumes SChannel all the time.

    The actual code uses the MsQuic API to check which TLS backend the library was compiled with

    // Assume SChannel is being used on windows and query for the actual provider from the library if querying is supported
    QUIC_TLS_PROVIDER provider = OperatingSystem.IsWindows() ? QUIC_TLS_PROVIDER.SCHANNEL : QUIC_TLS_PROVIDER.OPENSSL;
    paramSize = sizeof(QUIC_TLS_PROVIDER);
    apiTable->GetParam(null, QUIC_PARAM_GLOBAL_TLS_PROVIDER, &paramSize, &provider);
    UsesSChannelBackend = provider == QUIC_TLS_PROVIDER.SCHANNEL;

    The SChannel assumption on Windows is historical, because the API to query the backend was added is more recent. The Windows version is checked only if we detect SChannel-based MsQuic. This was done specifically to enable folks to use OpenSSL-based MsQuic. Currently, the only scenario which works is doing a self-contained publish of the app and overwriting the msquic.dll in the build output.

    The closed PR linked to this issue was supposed to add opt-in mechanism so that it would also work in development and framework-dependent publish on Windows 10. I think it should be easy to revive it and drag over the finish line.

  13. ethindp commented on Mar 31, 2025

    @ethindp

    @rzikm Would referencing a package like Microsoft.Native.Quic.MsQuic.OpenSSL work for overriding it? It doesn't seem to from my tests. Would be nice if the Schannel support was just backported to Windows 10, but I don't feel like that'll ever happen.

  14. rzikm commented on Apr 1, 2025

    @rzikm
    Member

    Would referencing a package like Microsoft.Native.Quic.MsQuic.OpenSSL work for overriding it?

    @ethindp

    Referencing is not enough, since the package contains native code dlls you need to jump through additional hoops to get the dll to a place where it would be looked for. #103351 has examples:

      <ItemGroup>
        <PackageReference Include="Microsoft.Native.Quic.MsQuic.OpenSSL"
                          Version="2.3.5"
                          PrivateAssets="all"
                          GeneratePathProperty="true" />
    
        <RuntimeHostConfigurationOption Include="System.Net.Quic.AppLocalMsQuic" Value="true" />
      </ItemGroup>
    
      <Target Name="CopyCustomContent" AfterTargets="AfterBuild">
        <Copy SourceFiles="$(PkgMicrosoft_Native_Quic_MsQuic_OpenSSL)\build\native\bin\x64\msquic.dll" DestinationFolder="$(OutDir)" />
      </Target>
      <Target Name="CopyCustomContentOnPublish" AfterTargets="Publish">
        <Copy SourceFiles="$(PkgMicrosoft_Native_Quic_MsQuic_OpenSSL)\build\native\bin\x64\msquic.dll" DestinationFolder="$(PublishDir)" />
      </Target>
    
    

    in .NET 9, only the CopyCustomContentOnPublish task is relevant, as overwriting in self-contained publish is the only functioning scenario. The RuntimeHostConfigurationOption also does nothing in .NET 9.

  15. ethindp commented on Apr 2, 2025

    @ethindp

    @rzikm I tried the example you gave and it still returns false for IsSupported which is very odd.

  16. rzikm commented on Apr 3, 2025

    @rzikm
    Member

    I don't have a Windows 10 machine to test this on, but replacing the binary seems to work fine.

    Putting the above snippet to csproj, and following program

    Type msQuicApiType = typeof(QuicConnection).Assembly.GetTypes().First(t => t.Name.Contains("MsQuicApi"));
    BindingFlags bindingFlags = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetProperty;
    string version = (string)msQuicApiType.InvokeMember("MsQuicLibraryVersion", bindingFlags, null, null, null)!;
    object backend = (bool)msQuicApiType.InvokeMember("UsesSChannelBackend", bindingFlags, null, null, null)! ? "SChannel" : "OpenSSL";
    
    System.Console.WriteLine($"MsQuic version: {version} (backend: {backend})");
    System.Console.WriteLine($"QuicConnection.IsSupported: {QuicConnection.IsSupported}");

    I get:

    ❯ dotnet run
    Using launch settings from C:\source\DotnetSandbox\Properties\launchSettings.json...
    MsQuic version: msquic.dll 2.4.3.515734 (839a2fbde9a2cecdcf0c41649037fa091cbb0e06) (backend: SChannel)
    QuicConnection.IsSupported: True
    ❯ dotnet publish --self-contained -r win-x64
    Restore complete (5.9s)
      DotnetSandbox succeeded (3.2s) → bin\Release\net9.0\win-x64\publish\
    
    Build succeeded in 10.5s
    ❯ .\bin\Release\net9.0\win-x64\publish\DotnetSandbox.exe      
    MsQuic version: msquic.dll 2.3.5.465110 (933f7b79949bc588945672396d70b661143bb8f0) (backend: OpenSSL)
    QuicConnection.IsSupported: True
    

    To get the desired result, you need to overwrite the MsQuic.dll that the app would normally load, so unless you want to modify the system-wide installation of .NET, you need publish the app as self-contained and overwrite the MsQuic.dll in the publish output (that is what the Copy tasks in csproj achieve).

  17. locked and limited conversation to collaborators on May 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area-System.Net.QuicenhancementProduct code improvement that does NOT require public API changes/additions

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions