Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hostonly and WSL2 #173

Open
audetto opened this issue Nov 8, 2022 · 12 comments
Open

hostonly and WSL2 #173

audetto opened this issue Nov 8, 2022 · 12 comments

Comments

@audetto
Copy link

audetto commented Nov 8, 2022

I am trying to find the simplest setup to use this on WSL2.

I have read #149 but I think it could be even easier.

Basically --hostonly is not enough to cover WSL2.

I get

Client not allowed 172.18.88.214

even if the log has

proxy:hostonly = 1

On Windows I can see a WSL Ethernet adapter

image

So,

I wonder if px could not scan all these Virtual adapters and add them to the "local" adapters directly.

@genotrance
Copy link
Owner

The virtual adapter on the Px side is x.80.* whereas the connection is coming from x.88.* which is why Px rejects it.

@audetto
Copy link
Author

audetto commented Nov 8, 2022

the subnet mask is .240 not .255
172.18.88.* is in the networks defined by the IP+mask

@audetto
Copy link
Author

audetto commented Nov 8, 2022

px/px/main.py

Lines 412 to 417 in faaa57c

def get_host_ips():
localips = [ip[4][0] for ip in socket.getaddrinfo(
socket.gethostname(), 80, socket.AF_INET)]
localips.insert(0, "127.0.0.1")
return localips

this function will return the hostname which is 172.18.80.1, but it knows nothing about the local network behind it.

is there a python way to extract the subnet mask?

@genotrance
Copy link
Owner

The goal of --hostonly is to allow all apps running on that same host OS to access Px even if via different interfaces. It does not equate to VMs running on the host which will have a different IP, they are a different host. WSL2 uses a VM so you will need to specify the IP or a range via --allow like in #149 to make it work.

We want to be super careful who can authenticate via Px. --hostonly is a shortcut to simplify that specific case. There's no way to correctly guess that the subnet is a virtual network and even if we did, the admin might not want those apps in VMs to inherit access. It has to be explicit. We could come up with another shortcut but --gateway + --allow enable this already and can be very prescriptive.

@audetto
Copy link
Author

audetto commented Nov 8, 2022

The difference between "apps" and "VMs" is probably a bit blurred, especially when the doc says

This allows local apps as well as VM or container apps to use Px when in a NAT config.

but I totally understand that what I ask requires a deeper knowledge of the type of adapters each network uses and this might not be easy to extract.

@dfillingham
Copy link

The hostonly feature is fantastic at protecting security. The problem with WSL2 is that at every reboot it will grab a new random subnet to run it's virtual network on.
If I was to open up allow to eg 172.17.0.0/16, then I'm opening myself up to potentially other people using my proxy if I happen to connect to a physical network that falls into the same range.

I'd like to see a configuration option added that allows me to specify the names of the WSL2 distros I want included as part of hostonly and the command to execute in that distro to return it's IP address on stdout.

Then, when determining host IPs we could run wsl -l --running on the windows side, read it's stdout and see if the distro I asked for is running.

  • If it's not, no problem just skip adding it to host IPs
  • If it is, execute the command given and read the IP address from that command's stdout
    • If the command fails/doesn't return what looks like a valid IPv4, just skip adding it and log the error in the debug log

We would need to implement a refresh of host IPs every x seconds, similar to how proxyreload works.

For example, a config that might look something like:

hostonly = 0
hostonlywsl2distros = [ { "distro": "Ubuntu", "command": "/home/david/get-ip.sh" } ]

This would mean at startup (and then every x seconds on a timer afterwards) we would:

  • Create a buffer list of all host IPs as it currently works today
  • Iterate the hostonlywsl2distros
    • Check if the given distro name is running
    • If no, ignore it
    • If yes, run the given command to get the IP address and add it to the buffer
  • Replace the allowed hosts with the buffer

We can execute commands in a running distro with wsl on the windows side:

wsl -d Ubuntu /home/david/get-ip.sh

Some examples of outputs:

No distros running

PS C:\Users\david> wsl -l --running
There are no running distributions.

Multiple distros running

PS C:\Users\david> wsl -l --running
Windows Subsystem for Linux Distributions:
Ubuntu (Default)
kali-linux

Getting the IP address by the command given

PS C:\Users\david> wsl -d Ubuntu /home/david/get-ip.sh
172.17.245.154

@genotrance
Copy link
Owner

I'm open to PRs that can do this cleanly, agree randomizing the WSL2 IP will be a pain to deal with. That being said, I'm not a WSL2 user so hard to implement at this time.

@DBS-ST-VIT
Copy link

In WSL2 under Windows 11, i got it working by setting the networkingMode to mirrored. I ran px with --hostonly and connected in the WSL to http://localhost:3128 and it worked without any problems.

Just make sure to restart WSL (wsl --shutdown and wsl) after changing the networkingMode in the .wslconfig.

@Roemer
Copy link

Roemer commented Sep 19, 2024

Mirrored mode does not work really well with VPN adapters currently.
What you can try is to fix the ip address range of the hyper-v adapter for WSL by adjusting some registry keys:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss]
"NatGatewayIpAddress"="10.20.30.1"
"NatNetwork"="10.20.30.0/24"

With this, any WSL will get an ip from the range 10.20.30.0/24. You can of course adjust this to your liking.
After this, configuring px with:

allow = 10.20.30.*
gateway = 1
hostonly = 1

seems to allow access from a local WSL.

@genotrance
Copy link
Owner

I've been doing basically the opposite - I run Px in a docker image on WSL2 and have my Windows, WSL2 and Docker apps connect to it. My WSL2 gets an internal IP (172.x) IP in a different range from Docker. In my case, I am not admin on Windows and the firewall is configured to block all inbound connections so Px is inaccessible to WSL2 and Docker. This might be affecting others as well.

I can set network_mode: host or expose port 3128 in Docker. For Px, I simply set PX_GATEWAY=1. I can access Px using localhost:3128 on Windows or WSL2. On Docker, I can specify the container name or use the WSL2 IP.

This setup is more secure since there's no way to access WSL2 from outside the physical machine. If WSL2 is configured with an external IP (assuming that's possible), Px might need to be configured more carefully.

@Roemer
Copy link

Roemer commented Sep 19, 2024

The problem there is, that there is no SSPI in WSL2, so you need another way to securely store the username/password to access the proxy (keyring?) to not have the Windows domain password somewhere in plain text. In Windows, it can just use the Windows domain credentials which is fairly nice.
Small edit: What we use from Docker in WSL2 to access WSL itself is to start all containers with --add-host=host.docker.internal:host-gateway and then you can use http://host.docker.internal:3128 from the containers to get to the port 3128 in WSL2.

@genotrance
Copy link
Owner

Agree - forgot the primary reason Px came to be! I use env vars to configure Px (username, server, etc) and keyring for saving the password. I also mount -v ./keyrings:/root/.local/share/keyrings to store the password outside the container.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants