Giter VIP home page Giter VIP logo

namespaced-openvpn's Introduction

namespaced-openvpn

namespaced-openvpn is a wrapper script for OpenVPN on Linux that uses network namespaces to solve a variety of deanonymization, information disclosure, and usability issues. Relative to OpenVPN's default behavior, it can be used to provide additional hardening or additional isolation (e.g., running some processes inside a VPN and some outside it, or running multiple VPN sessions concurrently and assigning different processes to different VPNs).

# create an openvpn tunnel in a new namespace, named `protected` by default:
sudo /path/to/namespaced-openvpn --config ./my_openvpn_config_file

# start an unprivileged shell in the new namespace
# anything started from this shell will use the openvpn tunnel exclusively for connectivity:
sudo ip netns exec protected sudo -u $USER -i

The main implementation idea of namespaced-openvpn is this: instead of connecting a network namespace to the physical network using virtual Ethernet adapters and bridging, it suffices to transfer a tunnel interface into the namespace, while the process managing the tunnel (in this case openvpn) remains in the root namespace.

Summary

OpenVPN is widely used as a privacy technology: both for concealing the user's IP address from remote services, and for protecting otherwise unencrypted IP traffic from interception or modification by a malicious local Internet provider. However, default configurations of OpenVPN are susceptible to various "leaks" that can violate these guarantees. Notable examples include route injection attacks and the so-called "Port Fail" vulnerability.

My view is that these issues have two root causes. One is that VPNs are not inherently a privacy technology --- their core function is to bridge two trusted networks using an untrusted network (generally the public Internet) as a link. On this reading, since the fundamental role of VPNs is to connect networks, rather than to isolate them (as required in the privacy use case), it is unsurprising that in the absence of additional precautions, they can allow information to escape. The second cause is that the openvpn process itself, the system-level network configuration software (e.g., NetworkManager), and the user's applications are all sharing a single routing table --- and when their use cases for this shared resource come into conflict, it can lead to expectations being violated.

This repository contains two approaches to these problems:

  • namespaced-openvpn, a wrapper script which systematically solves all of the enumerated security issues by moving the tunnel interface into an isolated network namespace
  • seal-unseal-gateway, a helper script which solves "Port Fail" only, but which otherwise preserves the default OpenVPN routing behavior

This code is released under the MIT (Expat) license.

Security and usability problems with OpenVPN's default configuration

OpenVPN's --redirect-gateway option (described in detail in its manual page) is the basic mechanism by which it attempts to provide network-layer privacy. In the following examples, a physical interface eth0 is connected to a LAN on 192.168.1.0/24, with 192.168.1.1 as its default gateway; 1.2.3.4 is the publicly routable address of the remote VPN server, and 10.10.10.10 is the default gateway of the tunnel interface tun0. If the --redirect-gateway option is set by the client or pushed from the server side, the openvpn process performs these three steps after establishing the tunnel:

  1. First, create a static route for 1.2.3.4 going over eth0 via 192.168.1.1
  2. Delete the default route over eth0 via 192.168.1.1
  3. Add a new default route over tun0 via 10.10.10.10

(Under a near variant of this option, --redirect-gateway def1, steps 2 and 3 are combined by adding routes to 0.0.0.0/1 and 128.0.0.0/1 via tun0. These routes override the default route, while being in turn overridden by the static route defined in step 1, without requiring the deletion of the original default route. The distinction between these two configurations will not be important.)

The result is a routing table that routes all public IPs over tun0, with the exception of 1.2.3.4, which is still routed over eth0: without this exception, the openvpn process itself would be stuck in a routing loop, unable to send its encrypted output packets to the Internet. The LAN subnet 192.168.1.0/24 will still be routed over eth0 as well: otherwise the system would lose access to LAN services, such as printers. We can now describe the aforementioned problems in detail:

Route injection attacks

Route injection attacks are described by Perta et al., 2015. A brief example: suppose that you're connected to a VPN, but your physical interface is connected to a malicious local gateway (e.g., a rogue wireless access point). Your DNS server is set to 8.8.8.8, which is correctly being routed over the VPN. If the local gateway guesses the address of your DNS server, it can force a DHCP renew on your physical interface and then claim that the gateway's IP is 8.8.8.8. Your DHCP client will then add a route for 8.8.8.8 over the physical interface, allowing interception and modification of your DNS requests.

"Port Fail"

"Port Fail" is an issue first documented by the commercial VPN provider Perfect Privacy. Some VPN providers offer to forward a port from the publicly routable VPN gateway back to the client, over the tunnel interface. Suppose a malicious adversary is a client of the same gateway 1.2.3.4 as you, and that 1.2.3.4 is also the egress for the VPN traffic. If the adversary gets a forward of port 56789 on the gateway, then tricks you into accessing a network service (e.g., by including a tracking pixel in a webpage they control) hosted at 1.2.3.4:56789, your request will be routed over eth0 instead of tun0 and the adversary will see your real IP address.

A more salient concern than such a deanonymization attack may be the possibility of "Port Fail" occurring by accident. For example, a BitTorrent client running over the VPN with port 56789 forwarded will see trackers reporting 1.2.3.4:56789 as a leecher in its swarms --- it will then attempt to request chunks from itself over eth0. Depending on the client's support for BitTorrent protocol encryption, this traffic may be identifiable to ISP deep packet inspection as BitTorrent traffic, or result in the disclosure of BitTorrent infohashes.

Asymmetric routing

In a Medium article, ValdikSS describes a different deanonymization vulnerability related to port forwarding. Suppose that you first enable your VPN, which forwards port 56789 to you from the egress 1.2.3.4, and then also forward port 56789 from the egress IP of your physical interface eth0 (call it 2.4.6.8) via a NAT traversal mechanism like UPnP. An adversary who knows that you have a network service accessible at 1.2.3.4:56789, and who can guess a set of candidate IPs including 2.4.6.8, can attempt to access port 56789 on each of the candidate IPs. When the adversary sends a packet to 2.4.6.8 and gets a reply from 1.2.3.4, your real IP will be revealed. (In particular, for UDP services, the IPv4 space is small enough that it's feasible to send a UDP packet to every publicly routable address.)

On Linux, this attack already has an effective mitigation: the sysctl options net.ipv4.conf.*.rp_filter, when set to 1 (as is the default in many distributions), will drop incoming packets with "asymmetric routes" (such as the attacker's probes, which come in on eth0 but whose replies would go out on tun0).

CVE-2019-14899 is a similar attack based on asymmetric routing (and hence is similarly mitigated by rp_filter). The attacker sends packets to the physical interface with source IPs in the private VPN space, then monitors the replies from the VPN interface, which disclose information about the state of its TCP/IP stack (including the IP address and TCP sequence numbers, which can then be used for data injection).

IPv6 leaks

"IPv6 leaks" are a fairly trivial problem: on a dual-stack system, changing the default route for IPv4 has no effect on the IPv6 stack, so applications will continue to route their IPv6 traffic over the physical interface. Despite the straightforward nature of the issue, its incidence in the wild is apparently high: Perta et al., 2015 discuss the scope of the problem.

DNS leaks

Many residential gateways include a caching DNS resolver (such as dnsmasq) and then push their own IP to their DHCP clients as the nameserver. Since by default, OpenVPN does not remove LAN routes and does not modify /etc/resolv.conf, it will not prevent clients in this situation from having their DNS requests routed over the physical interface to the gateway, which will then forward them in cleartext over the public Internet.

ping-restart

This is a usability issue, rather than a privacy issue, but it stems from the same root cause (the shared routing table) as many of the privacy issues. Commercial VPN providers commonly balance traffic to their endpoints via round-robin DNS: the remote endpoint (e.g., vpn.example.com) will have A records for multiple IPs. Periodically, a server may be shut down and replaced with another. By default, OpenVPN's --ping-restart option will respond to this by gracefully restarting the session after 120 seconds of inactivity: without bringing down the routes, the client will attempt to re-resolve the server's address, then reconnect to the remote. But if name resolution returns a new IP (say 1.2.3.5) for the remote, the client will be unable to connect to it, because only 1.2.3.4 was whitelisted to use eth0 --- 1.2.3.5 is still being routed over the defunct tun0 interface. (In fact, if DNS is being routed over tun0, we won't even get this far, because we'll be unable to resolve the name vpn.example.com a second time.)

namespaced-openvpn

The network namespace functionality of Linux provides, in effect, additional isolated copies of the entire kernel networking stack. The idea behind namespaced-openvpn is this: the openvpn process itself can run in the root namespace, but its tunnel interface tun0 can be transferred into a new, protected network namespace. This new namespace will have the loopback adapter lo and tun0 as its only interfaces, and all non-localhost traffic will be routed over tun0. The openvpn process is not disrupted by this because it communicates with tun0 via the file descriptor it opened to /dev/net/tun, which is unaffected by the change of namespace.

As long as sensitive applications are correctly launched within the new, isolated namespace, most of the enumerated issues are systematically resolved:

  1. Route injection is impossible because NetworkManager, dhclient, etc. are running in the root namespace, so they can respond to routing changes in the external network environment without affecting the protected namespace.
  2. "Port Fail" is blocked because the protected namespace has no routing exception for the remote gateway: every packet must go to tun0.
  3. Asymmetric routing attacks (including CVE-2019-14899) and IPv6 leaks are blocked because the protected namespace has no access to any physical interface.
  4. The openvpn process can freely restart because it runs in the root namespace, which has unmodified routes --- so its DNS request for the remote, and then its handshake with the resulting remote IP, all use eth0.
  5. Accidental DNS leaks via LAN resolvers are typically blocked because the protected namespace has no direct layer-3 access to the LAN. However, additional hardening is needed to protect against some attacks and leaks --- see the "DNS hardening" section below.

This approach has some further strengths:

  1. It does not require any configuration changes to the root namespace, e.g., recreating eth0 as a virtual bridge.
  2. Non-sensitive applications are free to use the physical interfaces, which may have better bandwidth or latency characteristics.
  3. A namespaced-openvpn instance can peacefully coexist with another OpenVPN connection in the root namespace, without any concerns about conflicting private IPv4 addresses and routes. (Use the --nobind option to prevent the second openvpn process from trying and failing to reuse port 1194 in the root namespace.)
  4. openvpn can be stopped and started without exposing processes in the protected namespace. If tun0 goes away, those processes don't revert to using a physical interface; instead, they have no connectivity at all.

Use it like this:

sudo /path/to/namespaced-openvpn --config ./my_openvpn_config_file

The new, isolated namespace will be named protected by default. Start an unprivileged shell in it like this:

sudo ip netns exec protected sudo -u $USER -i

Any applications started from this shell will inherit the namespace.

The Wireguard documentation describes a technique where the physical interface is moved into an isolated network namespace (named, e.g., physical), then a tunnel is used as the sole source of connectivity for the root namespace. namespaced-openvpn supports this configuration as well: pass the empty string as the namespace (e.g., --namespace '').

namespaced-openvpn can also be used to "stack" VPN tunnels, e.g.,

sudo namespaced-openvpn --namespace levelone --config ./config_one
sudo ip netns exec levelone namespaced-openvpn --namespace leveltwo --config ./config_two

The new namespace will come up with an empty set of iptables/nftables rules. If additional firewalling is desired inside the protected namespace (although I think this is likely unnecessary), it can be added in an openvpn --up script, which will run before the tunnel interface is transferred and given its routes. (openvpn will execute all scripts in the root namespace, so the script should first enter the namespace and then apply, or remove and reapply, the desired rules.)

DNS hardening

Name resolution is unfortunately a complex issue, presenting several hardening challenges. Here are two known issues:

  1. Due to limitations in the implementation of ip-netns(8) and the semantics of bind mounts on Linux, namespaced-openvpn running on a typical Linux system is still vulnerable to certain active attacks against DNS, affecting both confidentiality and integrity of DNS queries.
  2. Certain local DNS daemons can allow DNS queries to escape the namespace.

These problems can be fully mitigated in the following way:

  1. Disable systemd-resolved, resolvconf, and nscd.
  2. Instead, create /etc/resolv.conf as a static file. (A non-mobile system can use a LAN resolver; a mobile system can use one of the standard public resolvers, such as OpenDNS or 1.1.1.1.)

The first problem is that ip netns exec masks /etc/resolv.conf inside the namespace by bind-mounting /etc/netns/${namespace}/resolv.conf on top of it. Due to an implementation detail of the bind mount system, if the inode of the mountpoint /etc/resolv.conf changes in the root mount namespace, the bind mount will silently disappear in the protected namespace, uncovering the external /etc/resolv.conf. Consequently, on a system configured to use resolvconf(8) or a similar mechanism for automatically rewriting /etc/resolv.conf in response to DHCP changes, an active attacker can inject a malicious publicly-routable DNS server into /etc/resolv.conf inside the namespace. DNS queries to this server will be routed correctly over the VPN, but since the attacker controls the server, confidentiality and integrity are still violated. This attack is fully mitigated if /etc/resolv.conf cannot be rewritten, i.e., if it is maintained as a static file.

systemd-resolved presents a different problem; like the earlier nscd, it provides name resolution over UNIX domain sockets (via D-Bus), which can cross network namespace boundaries. That is to say, a name resolution inside the protected namespace may be delegated to a systemd-resolved instance running outside it, which will then issue a DNS request in cleartext. This is similar to a conventional DNS leak. Although most systems and applications are not yet using this functionality, we recommend against using systemd-resolved for this reason.

seal-unseal-gateway

Unfortunately, namespaced-openvpn sacrifices one of the traditional strengths of VPNs as privacy tools: it is relatively prone to user error, because the user must be careful to start any sensitive applications in the protected namespace. Processes running in the root namespace receive no protection. Therefore, it's worth presenting an alternative approach, one applicable to a traditional configuration that alters routes in the root namespace.

seal-unseal-gateway is a helper script that addresses the "Port Fail" vulnerability. It attempts to stop processes other than openvpn itself from using the whitelisted route. Specifically, it uses the owner matching functionality of iptables to drop outgoing packets to the remote gateway, unless they originate from a process with the same EUID as openvpn. Since openvpn will typically run as root or as a dedicated user, ordinary applications will be unable to use the route. (Some sources on the Internet claim that iptables can do owner matching by PID, which would be more precise. However, this functionality was removed from the kernel in 2005.)

Use it by adding these lines to your OpenVPN config file (or adding the equivalent command-line options):

script-security 2
up /path/to/seal-unseal-gateway
down /path/to/seal-unseal-gateway

The other privacy issues have relatively standard mitigations. To wit, route injection can be mitigated by using only trusted DHCP servers (e.g., trusted residential gateways), IPv6 leaks can be mitigated by disabling IPv6 (sysctl -w net.ipv6.conf.all.disable_ipv6=1), DNS leaks can be mitigated by ensuring that no LAN nameservers appear in /etc/resolv.conf, and asymmetric routing attacks can be mitigated with the rp_filter sysctl.

Caveats

This is relatively new software. It has only been tested with a few VPN configurations, and with modern versions of OpenVPN (>=2.3.11) and the Linux kernel (>=4.4). If privacy is critical for your use case and you're not comfortable with monitoring that namespaced-openvpn is working as expected, I can't recommend it yet. (You can use tools like iftop and ss, in the root namespace and the protected namespace, to verify that your traffic is being routed correctly over the VPN.)

To borrow a phrase from Stroustrup, namespaced-openvpn "protects against accident, not against fraud." It should be impossible for any normal application to have its traffic escape from the protected namespace back to the physical interface. However, without additional hardening, there is no guarantee that a malicious application can't force such an escape --- therefore, namespaced-openvpn should not be used by itself to "jail" an untrusted application.

Starting applications in the new namespace

There are a few different ways to launch applications in the new namespace. Unfortunately, none of them is perfect:

  1. Commands can be run in the protected namespace by prepending them with sudo ip netns exec protected sudo -u $USER. The first sudo invocation gets root privileges in order to change the namespace, then the second invocation runs the command as the original user. By default, sudo has the effect of unsetting most environment variables, which can break some application functionality (e.g., on my system, XDG_RUNTIME_DIR must be set correctly for Pulseaudio to work). This can be fixed by adding the -E option to both sudo invocations: sudo -E ip netns exec protected sudo -E -u $USER
  2. In addition to its jail functionality, firejail can easily launch applications in named network namespaces using its --netns= option, e.g., firejail --netns=protected firefox. I use firejail personally, but I'm hesitant about recommending it to others due to concerns that have been raised about its architecture.
  3. bubblewrap is a more conservative approach to the same problem as firejail. It works with the double-sudo technique; see this recipe as an example for jailing Firefox.

It might be helpful to set up a trusted script or binary, with either a sudoers(5) entry or CAP_SYS_ADMIN, that can be used to enter the protected namespace but not to re-enter the root namespace, but I haven't fully investigated this.

TODO

Bugs:

  • namespaced-openvpn tries to be a drop-in replacement for openvpn, but due to implementation details, route-up directives that use multiple levels of quotes or escaping may not be handled correctly. It is recommended that any route-up directive be syntactically valid both as an OpenVPN script directive and as Bourne shell.

Wishlist:

  • Ideally, there would be an option to offer both limited protection to the root namespace (e.g., without protecting against route injection) and full protection to an isolated namespace. This seems difficult to achieve in a nondisruptive way.

namespaced-openvpn's People

Contributors

e00e avatar eklitzke avatar slingamn avatar vmsh0 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

namespaced-openvpn's Issues

protected namespace inherits a default iptables config that is wide open

Hi

Thanks for writing this and for all the notes. I've integrated it into my script to connect to my VPN provider. It works really well.

Is there some way to automate the loading of my custom firewall script and overwrite the default one the protected name-space inherits?

At the moment I pull the ethernet cable out while openvpn is trying to connect, check the iptables rules... sometimes they have reverted to the wide-open default, other times they haven't... and if necessary flush the rules, and read my custom rules back in. After that it's fine. It only seems to happen when I open the first namespace. From then on it's fine.

But otherwise this works very well. As far as I am able to tell.

document / provide an example systemd unit file

Continued from #14. We should have an example of a systemd unit file that can be used in a dependency chain. My guess is that Type=forking together with openvpn's --daemon argument is the best strategy.

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

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

No connectivity in protected namespace as unprivileged

I have successfully used namespaced-openvpn for a year or two, but now after having upgraded to the latest testing version of Debian I am experiencing problems running unprivileged applications with it.

I have installed namespaced-openvpn in /usr/local/sbin (-rwxr-xr-x root).

Once the namespace is set up (sudo namespaced-openvpn --config ./my_openvpn_config_file
), if I run ping in the protected namespace as root:
sudo ip netns exec protected ping -w 3 www.google.com
then all is fine.

But, if I run ping in the protected namespace as user:
sudo ip netns exec protected sudo -u $USER ping -w 3 www.google.com
then I have no connection and get 'ping: www.google.com: Name or service not known'.

I have no connectivity running all other applications in the protected namespace unprivileged - apart from, for some reason, Tor.

Unfortunately, I don't have a great deal of expertise in this area and haven't been able to find the cause, and so any pointers would be gratefully received.

Access a single port in the root namespace from inside namespace

Hey, I've run into something interesting where I have a tool that needs to access to both the service inside and a different service on the outside of the namespace. I've exposed the namespace service ports IN the root namespace, so I need to be launching the processes external to the namespace, from inside.

App launches external process that checks files and communicates status of download to both the App and the App in the root namespace. Currently, App in the root namespace is invisible. I"ve attempted to find a socat config to expose just that one port, but not having luck.

I'm using a socat config to expose the namespace ports to the root namespace for the control interfaces.

I can't find if there's a way to launch an external process in a different namespace from inside the namespace. ip netns only lists the vpn namespace as available.

ip netns exec - where - is a reference to the root namespace.

any thoughts?

Using --up script (with root commands) forces user to retype sudo password

When the openvpn process reconnects, it successfully restarts and reruns the --up command (which requires root), then it forces the user to retype the sudo password to execute the --up script and complete the reconnect. The goal ist to avoid the retyping of the sudo password.

This problem could be reproduced with this simple upscript command for ufw or iptables:
ufw command: (just enables the firewall in the namespace with default rules)
sudo ip netns exec protected sudo -u [USER] sudo ufw enable
iptables command: (just shows the firewall rules in the namespace)
sudo ip netns exec protected sudo -u [USER] sudo iptables -L

I am not exactly sure which of the 3x sudo commands in the line forces the user to retype the password.

Namespace DNS resolver is pushed to the global resolver configuration

I seem to be experiencing the oppposite as the issue #7 . In my case, when the VPN is not active, the contents of /etc/resolv.conf are:

# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
# 127.0.0.53 is the systemd-resolved stub resolver.
# run "systemd-resolve --status" to see details about the actual nameservers.

nameserver 127.0.0.53

However, whenever I start the VPN ( namespaced-openvpn --namespace vpn --writepid foo.pid --log bar.log --daemon --config foobar.ovpn --daemon), the server pushes its DNS server and somehow it ends up prepended to /etc/resolv.conf:

# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
# 127.0.0.53 is the systemd-resolved stub resolver.
# run "systemd-resolve --status" to see details about the actual nameservers.

nameserver 1.2.3.4
nameserver 127.0.0.53

The line nameserver 1.2.3.4 is the only contents of /etc/netns/vpn/resolv.conf. When I kill the OpenVPN process, /etc/resolv.conf reverts to its original contents. What am I doing wrong?

Suggestion: Allow multiple OVPNs for fallback in case one is unconnectable

Thanks for this great script. Sometimes one of my VPN servers become non-connectable. It would be great if the script allowed a series of OVPNs to be input so if the first fails after several reconnect attempts, it falls back to the second, and so on. Could even repeat in a round robin fashion.

how would i start a docker container in the protected namespace?

Hi,
i love 'namespaced-openvpn' - it works like a charm. I can run any daemon or programm inside the protected namespace and it tunnels through vpn. I switched to using docker containers lately and want to run a docker container in the protected namespace. Can you point me in the right direction?

Thanks in advance.

openconnect flavour?

Long time lover of this script but for work, i want to be able do the same idea with openconnect, which supports anyconnect protocols.
Any suggestions on where to mod / perhaps you've considered this?

namespaced-openvpn argument issue?

Hi, it seems there is a little bug inside the namespaced-openvpn script.
It concerns this section:

namespaced-openvpn can also be used to "stack" VPN tunnels, e.g.,
sudo namespaced-openvpn --namespace level1 --config ./config1
sudo ip netns exec level1 namespaced-openvpn --namespace level2 --config ./config2

I get this error:
Options error: Unrecognized option or missing or extra parameter(s) in [CMD-LINE]:1: config (2.4.4)
Use --help for more information.

I think the script tries to pass the --namespace argument to openvpn, instead of using it in the namespaced-openvpn script.
2.4.4 is my openvpn version.

Tracking: integrate with usage of nss-resolve

Fedora 33 released and now uses systemd-resolved for its DNS lookups from glibc's level. This means that the resolv.conf approach is not as useful anymore. I have modified /etc/nsswitch.conf to avoid nss-resolve for now, but this is not a long-term solution. I've started a discussion on Ask Fedora, but would like to let developers here be aware of it in case there's something that can be done here too.

I suspect we'll need something from systemd to support network namespaces better, but I don't know.

Bittorrent through namespaced-openvpn

Bittorrent applications (tried Deluge and qBitTorrent), when ran inside the protected namespace, won't be able to connect to trackers, with the error: no route to host.

Interestingly they can still connect to DHT, and find peers and download (slowly), but just can't connect to tracker.

I "fixed" it by changing the default route to go via the vpn gateway.

> ip route show
default via 10.8.2.1 dev tun0 
10.8.2.1 dev tun0 proto kernel scope link src 10.8.2.11 

So far it seems to work, but there probably is a reason this was not the default, and I don't know enough about networking to know what protections this change will break (or maybe this change is fine?).

Any help with properly fixing bittorrent tracker issue would be greatly appreciated :)

Is it intentional for the root namespace to become innaccessible?

I run

sudo ./namespaced-openvpn --config ~/config.ovpn

default namespace, nothing special.

pings in default namespace now time out, outside connection cannot connect.
pings in private namespace do work, and curl-ing an ip checker shows vpn ip.
outside of namespaced', internet and openvpn work as expected.

The readme says that that namespaced-openvpn can be used for "running some processes inside a VPN and some outside it".

My personal goal would be to only run the vpn in said namespace and not have a vpn connection otherwise. I wish to have a publicly facing server, and occasionally run e.g. curl/wget etc through a vpn.

I kind of expected my root namespace to remain accessible - is it supposed to be? Can I achieve what I wish through this, or is namespaced-openvpn maybe not the right tool for my usecase?

setting the network namespace "protected" failed

Hi there,

I'am using Ubuntu 19.10, Python 3.7.5

$ sudo ./namespaced-openvpn --config ../vpn-config/openvpn.ovpn
setting the network namespace "protected" failed: Invalid argument
Traceback (most recent call last):
  File "./namespaced-openvpn", line 398, in <module>
    sys.exit(main())
  File "./namespaced-openvpn", line 377, in main
    setup_namespace(args.namespace)
  File "./namespaced-openvpn", line 66, in setup_namespace
    adapters = _adapter_names(namespace)
  File "./namespaced-openvpn", line 56, in _adapter_names
    output = subprocess.check_output(cmd)
  File "/usr/lib/python3.7/subprocess.py", line 411, in check_output
    **kwargs).stdout
  File "/usr/lib/python3.7/subprocess.py", line 512, in run
    output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['/sbin/ip', 'netns', 'exec', 'protected', '/sbin/ip', 'link', 'show']' returned non-zero exit status 255.

Tell me if you want any specific command outputs!

Hangs after "Initialization Sequence Completed"

I'm running sudo ~/git/namespaced-openvpn/namespaced-openvpn --config my.conf

It goes through all the expected startup actions, gets to "Initialization Sequence Completed" and then.... nothing! I left it for a couple of minutes, but nothing happened.

Is there any way to debug this?

Sat Aug 22 15:12:20 2020 OpenVPN 2.4.7 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on May 27 2020
Sat Aug 22 15:12:20 2020 library versions: OpenSSL 1.1.1c  28 May 2019, LZO 2.10
Sat Aug 22 15:12:20 2020 NOTE: the current --script-security setting may allow this configuration to call user-defined scripts
Sat Aug 22 15:12:20 2020 TCP/UDP: Preserving recently used remote address: [AF_INET]123.456.789.000:1198
Sat Aug 22 15:12:20 2020 UDP link local: (not bound)
Sat Aug 22 15:12:20 2020 UDP link remote: [AF_INET]123.456.789.000:1198
Sat Aug 22 15:13:20 2020 TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity)
Sat Aug 22 15:13:20 2020 TLS Error: TLS handshake failed
Sat Aug 22 15:13:20 2020 SIGUSR1[soft,tls-error] received, process restarting
Sat Aug 22 15:13:25 2020 NOTE: the current --script-security setting may allow this configuration to call user-defined scripts
Sat Aug 22 15:13:25 2020 TCP/UDP: Preserving recently used remote address: [AF_INET]123.456.789.000:1198
Sat Aug 22 15:13:25 2020 UDP link local: (not bound)
Sat Aug 22 15:13:25 2020 UDP link remote: [AF_INET]123.456.789.000:1198
Sat Aug 22 15:13:25 2020 WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this
Sat Aug 22 15:13:25 2020 [abc123] Peer Connection Initiated with [AF_INET]123.456.789.000:1198
Sat Aug 22 15:13:26 2020 TUN/TAP device tun0 opened
Sat Aug 22 15:13:26 2020 /etc/openvpn/update-resolv-conf tun0 1500 1558 10.62.15.6 10.62.15.5 init
dhcp-option DNS 9.9.9.9
dhcp-option DNS 209.222.18.222
dhcp-option DNS 209.222.18.218
Sat Aug 22 15:13:26 2020 Initialization Sequence Completed

(Redacted for privacy)

Split hosted services from tunnel

So I mentioned this before about hosting http/s and ssh on the host machine while running the tunnel inside the namespace.
I am still getting martians when I attempt this, so my router is forwarding the traffic but the kernel isn't handling it.
What should the routes look like in the root namespace when the tunnel is established.

I think the 0.0.0.0/1 and 128.0.0.0/1 routes are the problem.

Idea about using the namespace with an access point

Hello @slingamn

Thanks for your script with the namespace vpn it's really helpfull.

I wanted your thought about a security point of view of my idea that is working but it's not really easy to setup right now.
The idea is to have an wifi interface as access point in the namespace so that all the connected device would directly benefit from a secure vpn setup.

  1. Moving the wifi interface in the namespace
  2. Forward all the paquets on the wifi interface to the vpn interface

I think it's stay pretty "safe" because the access point can only be used for connecting on the wifi and not going on internet but I want your thought about it.

Cheers.

Connecting to a server in the namespace from outside the namespace

I'd like to run transmission-daemon in the openvpn protected namespace, and be able to access its web UI (on port 9091) directly from my LAN. I thought I should be able to access it over the loopback device on localhost, and use ssh port forwarding to access it from other machines. It's not working though. The connection is always refused, even if I try from localhost. I also tried running a simple python http server in the protected namespace, and that port is refused too, so the problem seems to be that the namespace's lo is isolated from the rest of the system. Any ideas?

DNS appears to be broken in root namespace

Hey, there! When I'm using namespaced-openvpn, it seems like it breaks my DNS configuration outside of the protected namespace. ping 8.8.8.8 works fine, but nslookup google.com hangs (so does dig and curl when a hostname is specified). All networking inside of the protected namespace appears to work as I expect, and is correctly routed through my VPN. I'm running Arch Linux, kernel 5.17.5-arch1-1.

Is this an unfortunate side effect of namespaced-openvpn, or a bug? Thank you for taking the time to look at this!

Pass other command-line openvpn args possible?

Is it possible to pass other command-line openvpn args with the namespaced-openvpn script?
I see namespaced-openvpn takes these argument --config.

Is it possible to pass other openvpn arguments from the client.ovpn file directly to namespaced-openvpn?
Like this: namespaced-openvpn --config vpn.ovpn --(other openvpn argument like –proto udp)
So i don`t have to edit each .ovpn file and change these values.

How to run snap-apps in namespaced-openvpn?

Hey, does anyone know a solution how to run snap-apps inside the namespaced-openvpns namespace?
Would be great to find a solution for that.
These are the first kind of apps i found which are not running with this script by default.

Support of tap mode?

I encounter a problem when trying to run namespace-OpenVPN in dev tap

When I run dev tun, It works just fine. Can you add support for tap mode ?

Traceback (most recent call last):                                                                                                                    
  File "/root/namespaced-openvpn/namespaced-openvpn", line 399, in <module>                                                                           
    sys.exit(main())                                                                                                                                  
  File "/root/namespaced-openvpn/namespaced-openvpn", line 370, in main                                                                               
    return route_up(sys.argv[1:])                                                                                                                     
  File "/root/namespaced-openvpn/namespaced-openvpn", line 186, in route_up                                  
    have_ipv4 = assert_all_or_none(                                                                                                                   
  File "/root/namespaced-openvpn/namespaced-openvpn", line 163, in assert_all_or_none              
    raise ValueError(message, *variables)                                                                                                             
ValueError: ('Bad ipv4 options pushed from server', '10.0.1.1', None)  

Connection lost after hibernation/standby

After waking up my system from either hibernation or standby, all processes started using sudo ip netns exec protected sudo -u $USER <command> lose their connection. Restarting them inside the namespaced shell doesn't work, however, after closing and re-opening the shell everything works just fine.

Steps to reproduce

  1. Start namespaced-openvpn
  2. Start a bash shell in the protected namespace: sudo ip netns exec protected sudo -u $USER bash
  3. Run any command that requires an internet connection in the bash shell (e.g. a webbrowser). It should work just fine and route through the vpn.
  4. Put the system in standby or hibernation. Do not exit the shell from (2).
  5. Wake up, try any command that requires internet again. No connection.
  6. Exit the namespaced bash shell and reopen it using the command in (2)
  7. Connection in that shell works just fine now...

Steps to mitigate this

None I found so far, any help is appreciated.

Additional info

My system log shows that the VPN reconnects successfully after waking up, although on a different device number (e.g. in ip addr inside the namespace I get 4: tun0 ... after waking up while its 3: tun0 ... before). Maybe that's related?

I run Manjaro linux (arch-based) on Kernel 5.10

Manually reconnecting namespaced-openvpn while other namespaces remain active from sudo ip netns exec

When I use Firejail to route sandboxed applications to the protected VPN namespace, I can manually restart namespaced-openvpn to reconnect the VPN without terminating any of the sandboxed applications. When applications are launched with the sudo ip netns exec protected sudo -u $USER -i argument, namespaced-openvpn fails to manually restart after the original instance disconnects with error code such as:

ERROR:root:Namespace protected already has adapters [b'in-ns1@if26', b'in-ns2@if26'], exiting.
Closing all the applications with their unique namespaces allows namespaced-openvpn to be manually restarted and connect normally. Is there a simple method to restart namespaced-openvpn without first closing all the child namespace processes?

namespace using dns from /etc/resolv.conf, not from the /etc/netns/protected/resolv.conf

@slingamn @chros73
I start sudo $HOME/git/namespaced-openvpn/namespaced-openvpn --config $HOME/Documents/vpn/ccrypto-fr-udp.ovpn

My openvpn .conf file:

verb 4
client
tls-client
script-security 2
remote-cert-tls server
dev tun
nobind
persist-key
persist-tun
comp-lzo yes

remote gw.fr.204vpn.net 1196 udp

auth-user-pass

redirect-gateway def1
tun-ipv6
route-ipv6 2000::/3

up /etc/openvpn/update-resolv-conf
down /etc/openvpn/update-resolv-conf

how to include authentification?

script works awesome. But i cannot add authentification to the .ovpn file.
auth-user-pass auth.txt --> auth.txt is in the same directory as namespaced-openvpn.

root@DietPi:~# /root/OpenVPN/namespaced-openvpn --config /root/OpenVPN/frankfurt_-_1_udp.ovpn
Wed Apr 25 21:30:53 2018 WARNING: cannot stat file 'auth.txt': No such file or directory (errno=2)

got it to work - included full path to 'auth.txt' in the .ovpn file

Service Dependencies

Hey There,
I'm using a different method and looking at switching to your project, as I was hoping it would skip the need for bridged interfaces that my current method uses.
I'm hoping that if I put the tun interface into the namespace, that the reset of the system can not live with the restrictions of not being able to host services, is this the case?
I'm trying to set it up so that this MUST be running as a service before other services (ie torrent) are launched.
This is the current method i'm using
https://gist.github.com/JimboMonkey1234/1dfed632f6a45bb5f06bbb1c7eef770d

Approach and ideas to reduce the amount of console windows...

Since some time i try to reduce the amount of open console windows.
But only sudo -E in console seems to work. So each GUI app has an additional console window open.

My plan is to start GUI apps without additional console window.
With lots of started GUI apps you have as much open console windows and you loose count of it.

Sadly gksu did not work although there is an option to preserve environment variables like sudo -E.

I tried pkexec together with sudo -E, but it is only working with rudimental GUI apps which work without preserving enviroment variables.

Has anyone other approaches to get a double sudo -E working with graphical authentification without a console window?

I thought about hiding annoying console windows, but it seems even that is not possible in an easy practical way.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.