slingamn / namespaced-openvpn

Wrapper for OpenVPN on Linux solving various privacy issues
MIT License
320 stars 45 forks source link

Is it possible to skip the VPN for the local network? #10

Open WeakTopology opened 6 years ago

WeakTopology commented 6 years ago

Hi, I'm loving namespaced-openvpn. It's ridiculously easy to set up and use.

However, I've noticed that traffic to the local network is being routed through the VPN. Is there a way to avoid the VPN for IPs on my local network (e.g. 192.168.1.x), and just use the direct connection instead?

I've noticed that using openvpn appears to automatically do this on my system. i.e. the first command will skip the VPN for local addresses, but the second will not.

# openvpn --config foo.conf
# namespaced-openvpn  --config foo.conf
slingamn commented 6 years ago

Glad you like it :-)

It was a design goal not to allow this by default, because it's a potential source of DNS leaks (talking to a LAN resolver over the physical interface).

It might be possible to add this as an option. The interface would be an additional command-line option like --allow-lan 192.168.1.0/24.

The tricky part is implementing this without making any invasive changes to the root namespace (e.g., adding an additional layer of NAT or disabling reverse path filtering). I'll think some more about this. If you have any suggestions on ways to compose the various primitives (veth(4), bridge(8), maybe a next-gen approach using ip-vrf(8)), I'm all ears.

WeakTopology commented 6 years ago

It was a design goal not to allow this by default, because it's a potential source of DNS leaks

Ah, that makes sense.

It might be possible to add this as an option

That would be excellent, thank you!

If you have any suggestions

Unfortunately I have no programming knowledge in this area, but I'm happy to contribute in other areas if helpful.

Just as an example of a use case, I have some programs on my home server that have an outward-pointing service, but can also be accessed on the internal network. Hence, if want to access them at home, I have to then send network traffic from home to the VPN and back home again.

sbappudi commented 5 years ago

I'm also interested in this, I have some basic networking / linux experience so I could give it a shot. I'd need some direction and ideas on how to go about it as I'm less experienced in security and don't want to introduce any bugs!

slingamn commented 5 years ago

Thanks for your interest!

I think the most promising approach is to use VRFs. Here's what I'd suggest:

  1. First, start an openvpn client process without namespaced-openvpn, with these additional arguments: --ifconfig-noexec --route-noexec --route-up /usr/bin/env. (The first two prevent automatic modification of the routing table in the root namespace, the third dumps all the environment variables that have been set by the time --route-up executes. These environment variables are the raw information used to make the necessary routing and DNS changes; namespaced-openvpn currently uses the values of dev, route_vpn_gateway, and ifconfig_local among others. You can consult the "Environmental variables" section of man 8 openvpn to get their meanings.)
  2. Now, manually experiment with sequences of ip commands that create a new VRF that uses the VPN for WAN addresses but the LAN for local addresses. See the examples on the linked kernel page.

When you have a recipe for doing this, post the recipe and the results of ip route show vrf [name], and then we'll discuss whether it's best to automate it as part of the existing namespaced-openvpn script, or make a new vrfed-openvpn script for it.

winpassuser commented 1 year ago

I needed to forward only one port to the local network and used this method:

socat tcp-listen:8112,fork,reuseaddr exec:'ip netns exec protected socat STDIO "tcp-connect:127.0.0.1:8112"',nofork

This is safer than allowing unrestricted local network access.