You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
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.
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
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.
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:
Figure out how to transform System.Net.Quic.nuget into Something.System.Net.Quic.nuget.
Wire this up to monitor the NuGet feed and auto-publish (this part I already know how to do).
Write my app using Something.System.Net.Quic.nuget.
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.
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.
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
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.
@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.
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:
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.
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).
Activity
dotnet-policy-service commentedon Apr 17, 2024
Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.
rzikm commentedon May 3, 2024
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 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.
StephenCleary commentedon May 18, 2024
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.
rzikm commentedon May 20, 2024
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).
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
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.
StephenCleary commentedon May 21, 2024
I'm fine with that.
Perhaps I should have started with my goal. I want to write an app that:
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:
Hence my current thinking:
System.Net.Quic.nugetintoSomething.System.Net.Quic.nuget.Something.System.Net.Quic.nuget.rzikm commentedon Jun 11, 2024
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.OpenSSLand 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 runloads 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.
StephenCleary commentedon Jun 11, 2024
I think that would work fine, thanks!
ethindp commentedon Mar 28, 2025
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
IsSupportedon 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.rzikm commentedon Mar 31, 2025
The actual code uses the MsQuic API to check which TLS backend the library was compiled with
runtime/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs
Lines 191 to 195 in 98049e5
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.
ethindp commentedon Mar 31, 2025
@rzikm Would referencing a package like
Microsoft.Native.Quic.MsQuic.OpenSSLwork 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.rzikm commentedon Apr 1, 2025
@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:
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.
ethindp commentedon Apr 2, 2025
@rzikm I tried the example you gave and it still returns false for
IsSupportedwhich is very odd.rzikm commentedon Apr 3, 2025
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
I get:
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).