WindowsAppSDK icon indicating copy to clipboard operation
WindowsAppSDK copied to clipboard

Network capabilities "internetClientServer" & "privateNetworkClientServer" takes no effect

Open zhuxb711 opened this issue 2 years ago • 12 comments

Describe the bug

internetClientServer & privateNetworkClientServer would create the firewall rules but it takes no effect. Any inbound connection would not reach the application even the application have internetClientServer & privateNetworkClientServer capabilities.

Currently in Windows App SDK, to make the inbound connection works, there are two configuration needs to config.

  1. You must create the firewall rules and open the port by yourself
  2. You must create a new rule in HttpUrlAcl so that we could listen to the localhost with HttpListener

However, those steps above needs admin privileges, which makes a bad user experience. And would not be able to remove the rules when the user uninstall the application.

I have already tested on UWP application, it works well, without any firewall rules or HttpUrlAcl rules, just simple and easy, I don't know why the Windows App SDK have different behavior.

Steps to reproduce the bug

In Windows App SDK:

  1. Create HttpListener
  2. Would not accept any inbound connection
  3. Add HttpUrlAcl Rules and Firewall Rules (Elevated)
  4. Accept the connection from HttpListener

In UWP:

  1. Create HttlListener
  2. Accept inbound connection directly without any configuration

Expected behavior

Behavior same as UWP without any configuration

Screenshots

None

NuGet package version

Windows App SDK 1.4.1: 1.4.230913002

Packaging type

Packaged (MSIX)

Windows version

Windows 11 version 22H2 (22621, 2022 Update)

IDE

Visual Studio 2022

Additional context

Add firewall rule also takes no effect.

        <desktop2:Extension Category="windows.firewallRules">
            <desktop2:FirewallRules Executable="AAA\AAA.exe">
                <desktop2:Rule Direction="in" IPProtocol="TCP" Profile="all" LocalPortMax="16384" LocalPortMin="16384"/>
            </desktop2:FirewallRules>
        </desktop2:Extension>

zhuxb711 avatar Oct 10 '23 16:10 zhuxb711

Forgive me if I am blind, but I don't see where this is explicitly related to the Windows App SDK. To explain what I mean, suppose I create a Windows Forms application.

Screenshot 2023-10-11 174023

This project allows you to use the System.Net.HttpListener class. To this solution, suppose I add an application packaging project.

Screenshot 2023-10-11 174200

I now have a packaged project that can use HttpListener but doesn't reference the Windows App SDK.

Screenshot 2023-10-11 174409

You can then use the packaging project to create the MSIX packages and even an MSIX bundle.

Screenshot 2023-10-11 175241

Screenshot 2023-10-11 175255

So unless there is something more related to the Windows App SDK here, this is more of a Windows problem. I appreciate that you may have first encountered application packaging in relation to the Windows App SDK, but application packaging is a Windows technology. It is better to report this using the Feedback Hub to report this.

DarranRowe avatar Oct 11 '23 17:10 DarranRowe

@DarranRowe This issue related to Windows App SDK because it would create the firewall rules if you declared *ClientServer capabilities. However, it would not make my application to capture the connection even those firewall rules were set to accept all the inbound connection in all the ports. On UWP application, it would create the similar firewall rules and that takes effect.

On the other side, UWP application do not need to config the HttpUrlAcl in netsh but Windows App SDK needs that, Since Windows App SDK inherit from the UWP tech, I think that should be a bug in Windows App SDK.

zhuxb711 avatar Oct 12 '23 02:10 zhuxb711

@DarranRowe

Create an application that use HttpListener in Windows App SDK with *ClientServer capabilities. You would find that the application would never accept the inbound connection from LAN unless you create the firewall rules and HttpUrlAcl by yourself.

Create an application that use HttpListener in UWP with *ClientServer capabilities. HttpListener would be able to accept the inbound connection from LAN directly.

zhuxb711 avatar Oct 12 '23 02:10 zhuxb711

@zhuxb711

The point is that I can do everything you stated without referencing the Windows App SDK. You do not need to use the Windows App SDK to package a project, declare those capabilities or even use the HttpListener and HttpUrlAcl classes. I even gave screenshot and gave a description as to how you could set up a C# Windows Forms application to work in the exact same way. All of this without referencing the Windows App SDK.

DarranRowe avatar Oct 12 '23 14:10 DarranRowe

@DarranRowe That's why I created this issue. Yes you don't have to use Windows App SDK, but what I need is to use HttpListener in my Windows App SDK project! And that behavior different from UWP. And your solution is giving up Windows App SDK and use winform...

zhuxb711 avatar Oct 12 '23 16:10 zhuxb711

@DarranRowe Sorry for not stating the obvious, I now have a Windows App SDK project and then I ran into this problem, that's why I'm reporting it, so changing to WinForm is not an option.

zhuxb711 avatar Oct 12 '23 16:10 zhuxb711

I did not provide a solution. I provided evidence that it is possible to do what you are doing completely independently of the Windows App SDK. Additionally, if it is failing with the Windows App SDK referenced in an application, the above evidence is also expected to fail too. When reporting a bug, if the bug is in one technology, (in this case the packaged environment as which is part of Windows), it is always better to report the bug to the correct team, regardless of where you want to use it. Even if you are trying to leverage the packaging technology in a WinUI 3 application, it is still a problem with the packaging environment. Reporting it to either the Windows App SDK team or even the WinUI 3 team will not really do any good because they don't work with the problematic code and they may not even have access to it. As I stated at the bottom of my original post:

... but application packaging is a Windows technology. It is better to report this using the Feedback Hub to report this.

Yes, I copied it with the mistake I forgot to correct. The evidence I posted above was never a solution. I never even hinted at using a Windows Forms application. I provided some evidence of this being a Windows problem and provided some information on a more suitable place for reporting problems of this kind.

DarranRowe avatar Oct 12 '23 16:10 DarranRowe

@DarranRowe I got it. However, since my uwp application with msix packaged works well without any configuration. That why I thought the root cause should be in Windows App SDK.

If that's the bug on Windows, uwp application should also affected.

zhuxb711 avatar Oct 12 '23 16:10 zhuxb711

Unfortunately, packages are not made equally. The documentation for the Application element describes things in detail. Basically, if the EntryPoint attribute has a value which corresponds to a WinRT runtime class, Windows will see the application as a WinRT/UWP type. It will then assume the WinRT/UWP app behaviours. If this attribute is either windows.fullTrustApplication or windows.partialTrustApplication, then Windows will see the application as a desktop application and assume those behaviours. There are behavioural differences between the two, starting from the fact that the Core classes will be available in WinRT/UWP apps but not in desktop applications. It diverges even more from there. Suppose my desktop application is set to a full trust application. That can be done by setting the EntryPoint attribute to windows.fullTrustApplication. This is default for WinUI 3 applications by the way.

Screenshot 2023-10-13 120850

Reading the information from the process token, the process' integrity level is medium and it isn't running in an app container. This is very different from the WinRT default of low integrity and running in an app container. However, the process does have a package identity.

It is possible to make a packaged desktop application run with low integrity and inside an app container.

Screenshot 2023-10-13 121349

This can be done by setting the EntryPoint attribute to windows.partialTrustApplication.

<Application Id="App" Executable="Meh.exe" EntryPoint="Windows.PartialTrustApplication">

This has provable behavioural differences in an application. One of the most annoying problems is that the UWP pickers don't work if the application is a desktop application running in an app container. The picker code detects the app container and assumes that it is running in a WinRT/UWP application and just never lets you use IInitializeWithWindow. There is logically a potential difference here, if the application is running in an app container, Windows will use a broker to do all of the work. If the application isn't running in an app container then it will do all of the work directly. It is this direct work which is the problem since it could be bypassing a few things. You could be hitting another bug in that it isn't properly applying the firewall rules for the full trust application.

One potential thing to test is making your application run in an app container to see if the internetClientServer and privateNetworkClientServer capabilities work in that case. If you are using the single project WinUI 3 project type, just edit the EntryPoint attribute from $targetentrypoint$ to windows.partialTrustApplication. Make sure the Package.appxmanifest file has the PhoneIdentity element since it is needed. The newer WinUI 3 project templates have this, but it was missing from the older WinUI 3 project templates. As an example:

<Package
  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
  xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
  xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
  IgnorableNamespaces="uap rescap">

  <Identity Name="bff4abc0-abcb-4ba4-987a-1eda037f90f2" Publisher="CN=Darran" Version="1.0.0.0" />

  <mp:PhoneIdentity PhoneProductId="bff4abc0-abcb-4ba4-987a-1eda037f90f2" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
...
</Package>

If you have a multiple project layout, you can do this by selecting the referenced project in the .wapproj project and then setting the trust level in the properties.

Screenshot 2023-10-13 124000

Screenshot 2023-10-13 124018

But yes, packaging applications can be complex.

As an aside, I simplified things in relation to windows.fullTrustApplication/windows.partialTrustApplication and WinRT/UWP application behaviours. The documentation for the Application element goes into more detail, including the presence of the uap10:RuntimeBehavior and uap10:TrustLevel attributes.

DarranRowe avatar Oct 13 '23 11:10 DarranRowe

@DarranRowe Please try this example: HttpListenerTest.zip

Access denied threw on HttpListener.Start(). That's because the HttpUrlAcl rule blocked the application. However, it works fine in UWP application. After that you still required to add a new firewall rule.

zhuxb711 avatar Oct 14 '23 15:10 zhuxb711

I apologise for taking so long to reply to this, I have been rather busy. I also wanted to get to the heart of the matter, so I was testing sockets directly. When testing with the raw Windows Sockets, internetClientServer and privateNetworkClientServer were completely ignored. However, I had no issues when setting the firewall rules.

<?xml version="1.0" encoding="utf-8"?>

<Package
  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
  xmlns:desktop2="http://schemas.microsoft.com/appx/manifest/desktop/windows10/2"
  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
  xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10"
  xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
  IgnorableNamespaces="desktop2 uap uap10 rescap">

  <Identity
    Name="SockSrvTestPackage"
    Publisher="CN=Darran, O=Untrusted Software, S=Neath, C=GB"
    Version="1.0.0.0" />

  <Properties>
    <DisplayName>SockSrvTest</DisplayName>
    <PublisherDisplayName>Darran</PublisherDisplayName>
    <Logo>Images\StoreLogo.png</Logo>
  </Properties>

  <Dependencies>
    <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.22621.0" />
    <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.22621.0" />
    <PackageDependency Name="Microsoft.VCLibs.140.00.UWPDesktop" MinVersion="14.0.24217.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
    <!--
    <PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.30704.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
    -->
  </Dependencies>

  <Resources>
    <Resource Language="x-generate"/>
  </Resources>

  <Applications>
    <!--$targetnametoken$ expands to SockSrvTest\SockSrvTest-->
    <Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$">
      <uap:VisualElements DisplayName="Socket Server Test" Description="Socket Server Test" BackgroundColor="transparent" Square150x150Logo="Images\Square150x150Logo.png" Square44x44Logo="Images\Square44x44Logo.png">
        <uap:DefaultTile Wide310x150Logo="Images\Wide310x150Logo.png" />
        <uap:SplashScreen Image="Images\SplashScreen.png" />
      </uap:VisualElements>
    </Application>
  </Applications>

  <Extensions>
    <desktop2:Extension Category="windows.firewallRules">
      <!--$targetnametoken$ expands to SockSrvTest\SockSrvTest, so use this for the Executable attribute, with the extension appended-->
      <desktop2:FirewallRules Executable="SockSrvTest\SockSrvTest.exe">
        <desktop2:Rule Direction="in" IPProtocol="TCP" Profile="all" LocalPortMax="3827" LocalPortMin="3827"/>
      </desktop2:FirewallRules>
    </desktop2:Extension>
  </Extensions>

  <Capabilities>
    <rescap:Capability Name="runFullTrust" />
  </Capabilities>
</Package>

This was my full appxmanifest file, and the worst that I had to do was to properly make the Executable attribute line up with the server's executable. The executable name is my application's executable, so it should be modified to match your executable name and relative path.

Screenshot 2023-10-24 220319

All the code had to do was use the TCP protocol and port 3827, which I set as the inbound TCP port in the firewall rules, and it worked.

I also tried working with the Windows.Networking.Sockets UWP namespace. Again, the capabilities are ignored but the firewall rules work.

While this isn't directly working with HttpListener, HTTP is a protocol that works on top of sockets. So if the socket connects then HttpListener will also connect. So my suggestions are:

  1. Make sure the executable for the firewall entry matches the executable for the application.
  2. Make sure the port matches the port given in the HttpListener prefix.
  3. Since there is no information given in the documentation about what protocol it is using. Try adding a UDP rule too. QUIC uses UDP as a base.

DarranRowe avatar Oct 24 '23 21:10 DarranRowe

I'm facing the exact same issue in a corporate environment where user defined firewall rules are not allowed via group policy. Only admins can create rules that get then deployed to the various machines. For classic Win32 apps the admins would create firewall rules by using the path of the executable. For packaged apps the path to the exe cannot be used since is based on the app version (that would mean creating a rule for each app version...) and so the "for application package" functionality of windows firewall is used. image

This works great for UWP apps but is not for WindowsAppSDK applications.

The workaround suggested by @DarranRowe above is not feasible in this situation because user defined rules are ignored.

I really don't know how to handle or report this situation

HispidaBytes avatar Jun 04 '24 16:06 HispidaBytes