mullvad / mullvadvpn-app

The Mullvad VPN client app for desktop and mobile
https://mullvad.net/
GNU General Public License v3.0
4.66k stars 330 forks source link

[Feature Request] Split Tunneling Microsoft Store Apps #2822

Open Hantersob opened 3 years ago

Hantersob commented 3 years ago

Hey there,

I tried your new split tunneling feature (ver. 2021.4-beta1) and it worked very well, expect windows apps from the Microsoft Store like Amazon Prime Video or Netflix. Could you please add them, that would be very helpfull.

anon97945 commented 3 years ago

This feature is realy needed, since MullvadVPN does not work with Amazon Prime Video or Netflix.. dont want to close the whole VPN for the rest of my internet usage only due to not whitelist Prime Video or Netflix.

mvd-ows commented 3 years ago

Microsoft Store apps aren't supported at this time, because they don't exist as discrete processes.

E.g. if you launch the Netflix app, an instance of C:\Windows\System32\RuntimeBroker.exe is launched in its place and made responsible for interpreting the Netflix app logic. App windows are owned by a separate process which is responsible for coordinating all desktop interactions (C:\WINDOWS\system32\ApplicationFrameHost.exe).

The only way to address this is to use a ton of hacks piled on top of each other to eventually identify the correct broker process that corresponds to an app we want to split.

In the meantime, may I suggest that you use a stand-alone release of the respective app, or the in-browser version?

Inverness commented 3 years ago

I see that when looking at RuntimeBroker.exe instances using Process Explorer, it is able to identify which application package spawned the process.

I don't know how it does this, and it seems this person on Stack Overflow had the same question: https://stackoverflow.com/questions/66658049/how-to-get-the-uwp-package-associated-with-an-uwp-process

There isn't a good answer though. The command "tasklist /apps" can be used to see which processes are part of which app packages, but I don't know what API calls this tool uses.

mvd-ows commented 3 years ago

Thanks, we'll look into it.

TheRealDadbeard commented 2 years ago

Any fix in sight for this? This is badly needed for forza horizon 4 as it will not work with a VPN. Even giving myself all the right to the encrypted folder is not sufficent.

faern commented 2 years ago

I'm sorry to say this. But Microsoft store apps are not supported at this time, and we have no fix in progress. We might look into this in the future. But for now, your only solution will be to try to install these programs from another source, so they are proper processes that can be split.

TheRealDadbeard commented 2 years ago

Huh what a shame as other VPN providers figured that out. I wont buy them on other storefront if I have gamepass so that is not an option for me and everyone else.

I really hope you can figure it out as mullvad works amazing for me and I don't want to switch honestly.

Gaveroid commented 2 years ago

I'm sorry to say this. But Microsoft store apps are not supported at this time, and we have no fix in progress. We might look into this in the future. But for now, your only solution will be to try to install these programs from another source, so they are proper processes that can be split.

The majority of the apps that I find a use for split tunneling for are Microsoft store apps. I understand that this is no trivial task to implement but as @TheRealDadbeard mentioned others have managed to make it work. Not trying to shoot the messenger - but to say that there is no fix in progress is not quite acceptable.

Split tunneling is a major feature of any VPN client, and it's very concerning that it refuses to support a major method of software distribution that has been in use since 2012 now (Windows store began with Windows 8). So many applications are only offering Windows Store versions these days. I cannot for example just "use the browser" for Hulu, Amazon Prime, etc. because by adding my browser to split tunneling, my whole browser is now unprotected when all I need is one service.

I feel that if UWP-centered split tunneling is not an option, then we should at least be able to manually whitelist sites/domains/IPs to be excluded from the tunnel.

4nn0nym05 commented 2 years ago

You can split tunnel windows apps now

For Disney+ for example In split tunneling browse for a file
C:/Program Files/WindowsApps/Disney.[id]/DisneyPlus.exe

If you cant access folder change owner to you and it shall work

Snazzah commented 1 year ago

Found a better way of split tunneling Windows apps, at least for me.

  1. Using Process Explorer, find the app with Ctrl + F and right-click the application to go to Properties.
  2. Copy the path from the properties (example), and click "Find another app" in the Mullvad app under the Split tunneling options.
  3. In the "File name" field of the open dialog, paste the path and then click "Add".
  4. Probably relaunch the app to make sure, and you should be good to go.

Note that this may stop working when the application updates.

r4df0x commented 1 year ago

The above two methods don't work for Netflix unfortunately - it doesn't appear to have its own executable file.

phizch commented 1 year ago

@r4df0x I managed to get Netflix to work. It uses WWAHost.exe as its host process. To exclude it run this cli command:

mullvad split-tunnel app add C:\Windows\System32\WWAHost.exe

Note: This will exclude all apps that use wwahost.exe as its process, not just Netflix. On my system only Netflix was using it as it's host process, though other UWP javascript apps will also use it. (yes, the Netflix Windows app is written in js)

Amazon Prime is easier, since it has an executable file. Note that windows apps create when they update, so you'll need to exclude the new path. Use Task Manager or Process Explorer to get the path of PrimeVideo.exe and exclude it with the CLI tool.

e.g: (the path will change based on the version! - don't copy-paste)

mullvad split-tunnel app add "C:\Program Files\WindowsApps\AmazonVideo.PrimeVideo_1.0.115.0_x64__pwbj9vvecjh7j\PrimeVideo.exe"

You can also use PowerShell to get the path:

> Get-Process -name PrimeVideo | Select-Object Path

Path
----
C:\Program Files\WindowsApps\AmazonVideo.PrimeVideo_1.0.115.0_x64__pwbj9vvecjh7j\PrimeVideo.exe

ps. I also excluded RuntimeBroker.exe before I figured out it was WWAHost.exe that I needed to exclude. It is possible that both need to be excluded, but I doubt it.

phizch commented 1 year ago

@faern , @mvd-ows I've done some digging, and you can get info about MS Store pacakages from the process handle. Kernel32.dll: GetPackageID gets a struct with enough info that you can build a package id/path like this 4DF9E0F8.Netflix_6.98.1805.0_x64__mcm4njqhnhss8

I've never written a line in Rust in my life, so forgive me my C#.

var procs = Process.GetProcesses();
var nf = procs.Where( x => x.ProcessName == "WWAHost" ).SingleOrDefault(); // get process for Netflix.
var package = GetPackageID( nf );
var packagePath = $"{package.Name}_{package.PackageVersion}_{package.ProcessorArchitecture switch { 9 => "x64", _ => "Unknown" }}__{package.PublisherId}";

Debug.Assert( packagePath == "4DF9E0F8.Netflix_6.98.1805.0_x64__mcm4njqhnhss8" ); // yup

I don't know how you determine whether a program should be excluded, but assuming

  1. get the PID of a newly opened program
  2. get a Process handle using OpenProcess
  3. get the path of the process' main module
  4. check against the list in ´settings.split_tunnel.apps´
  5. exclude if found

then it would be simple to extend it to MSIX / Microsoft Store apps.

  1. get the PID
  2. get a process handle
  3. try to get PACKAGE_ID using GetPackageId. If it fails with APPMODEL_ERROR_NO_PACKAGE (15700), then abort.
  4. get full path using GetPackagePath (C:\Program Files\WindowsApps\4DF9E0F8.Netflix_6.98.1805.0_x64__mcm4njqhnhss8)

-- or -- use information from PACKAGE_ID to create a version-independent key.

for example:

name    = "4DF9E0F8.Netflix"
version = 6.98.1805.0     (u16,u16,u16,u16)
processorArchitecture : u32 = 9 => "x64", 0 => "x86" , etc
publisherId = "mcm4njqhnhss8"

Key = "<name>_<publisherId>" = "4DF9E0F8.Netflix_mcm4njqhnhss8"
  1. check either path or key against list of excluded programs.
  2. exclude if found.

You won't have the name of the executable, but I assume that only needed to match a "normal" program with a path. If the path is the magic thing, not the PID/Handle, then there's really a problem.

faern commented 1 year ago

Thanks for the detailed investigation @phizch! We'll see what we can do with that information.

We currently do splitting on exe path. So if you exclude a program we add the full path to it (C:\Program Files\Foo\bar.exe) to a list of excluded apps. And the split tunneling kernel driver then checks the process' binary path for all new sockets to determine if it should go inside or outside the tunnel.

phizch commented 1 year ago

Hi @faern, I think I've started to figure things out. I was looking for driver code in the mullvad repository.. I only discovered the win-split-tunnel repository just a couple of hours ago 😄.

I've never done any driver programming either, so I'm not sure of what functions are possible to call. GetPackageId is part of Kernel32.dll, but I'm not sure if it's available in a driver. I'm having trouble figuring that out.

If GetPackageId is available:

procmon.cpp's SystemProcessEvent gets the path to the program using util::GetDevicePathImageName. It also has access to the process-id, so it can use that in a call to GetPackageId. If it doesn't return APPMODEL_ERROR_NO_PACKAGE, that means the process is a Microsoft Store program.

The PACKAGE_ID structure contains enough info to match it to a specific key. Alternatively, You can use GetPackagePath to get an ID like 4DF9E0F8.Netflix_6.98.1805.0_x64__mcm4njqhnhss8 or use that with GetPackagePathByFullName to get the full path C:\Program Files\WindowsApps\4DF9E0F8.Netflix_6.98.1805.0_x64__mcm4njqhnhss8. The path can be added as normal by mullvad split-tunnel app add .... It doesn't seem to care if the path is a folder or a program 😃.

From here you can use the same lookup as you do with normal paths, which as far as I can tell is handled by EvaluateSplitting in procmgmt.cpp

Personally I would try to use the package-id and have a key such as MS://4DF9E0F8.Netflix__mcm4njqhnhss8 so that it won't have to be manually updated when the Microsoft Store app updates. This will require modification to the cli tool's Rust code though. It balks at things that doesn't look like a valid Windows path.

I could try to implement it myself, but I don't know how to set up the dev environment to build and test it. Also, I don't know how to test drivers 😄.

If you, or someone, can point me in the right direction on how to do that, I can take a shot at it.

faern commented 1 year ago

Your information here is really helpful. We have not had the time to look into this yet, but we of course want to solve split tunneling for MS Store apps eventually.

Maybe @dlon have some pointers for you if you want to play around with it!

AhmedAtxha commented 1 year ago

https://www.reddit.com/r/ProtonVPN/comments/r5f2mh/guide_adding_firefox_and_other_windows_store_apps/

this reddit thread helped me figure this problem out

Nalci commented 11 months ago

Thanks @MasterAtcha for the reddit thread, I'll try that shortly!

It's a bit disappointing to see that this issue is still open. I wish it would get a bit more prio.