chrisbouchard / namespaced-wireguard-vpn

Systemd configuration for a network namespace containing a WireGuard VPN connection
MIT License
40 stars 6 forks source link
copr fedora-copr mullvad netns rpkg rpm-spec systemd systemd-service vpn wireguard wireguard-vpn

Namespaced WireGuard VPN

Copr build status

Systemd configuration for a network namespace containing a WireGuard VPN connection

Overview

        I N T E R N E T
              Λ :
              | :
              | :
+------------ | : ------------+    +-----------------------------------------------+
| Init NS     | :             |    | VPN NS                                        |
|          -- V --            |    |      --------                                 |
|        / enp0s3  \ .................. / wg-vpn   \ .............                 |
|        \ 1.2.3.4 <--------------------> 10.0.0.1 /             :                 |
|          -------            |    |      --------       O------ : ------------O   |
|                             |    |                     | transmission-daemon |   |
|         ----------          |    |     ----------      O------------ : ------O   |
|       / veth─init  <-----------------> veth─vpn   \                  :           |
|       \ 10.127.0.1 / ............... \ 10.127.0.2 / .................:           |
|         ----------          |    |     ----------                                |
|              :              |    |                                               |
|   O--------- : ---------O   |    +-----------------------------------------------+
|   | transmission-remote |   |
|   O---------------------O   |
|                             |
+-----------------------------+

Rough illustration of the intended setup. See Routing & Network Namespace Integration for a more thorough explanation of how WireGuard works across network namespaces.

Installation

This package is available from the chrisbouchard/upliftinglemma COPR. Assuming you're using a recent version of Fedora or CentOS, you can install using dnf.

$ dnf copr enable chrisbouchard/upliftinglemma
$ dnf install namespaced-wireguard-vpn

You may have to agree to some prompts if this is the first COPR you've enabled.

Configuration

The systemd unit configuration file for this project is /etc/namespaced-wireguard-vpn/namespaced-wireguard-vpn.conf which, by default, is owned by root with 0600 permissions since it will contain your VPN WireGuard private key. The file will be read as a systemd environment file (see the EnvironmentFile= directive in systemd.exec(5)). All expected values are set by default, most with dummy default values.

Configuration Values

Tunnel

This package provides a tunnel between the init namesapce and the created VPN namespace so, e.g., you can control services inside the VPN namespace from outside. If you don't need or want the tunnel, just set TUNNEL_ENABLE=0.

Namespace Overlay

Most likely, there will be some additional configuration that you will want to make, particularly if your system uses systemd-resolved for domain name resolution. Since systemd-resolved uses a UNIX socket, it won't be namespaced and requests over the VPN will use the configured DNS name servers — name resolution will either break (if configured to use local servers) or worse leak information.

Linux network namespaces allow you to add configuration files in /etc/netns/$NETNS_NAME, which will replace the existing configuration file for processes running inside the namespace. I'd recommend overriding nsswitch.conf and resolv.conf to use your VPN provider's name servers. See DNS Leaks with Network Namespaces for more detail.

Running

Once the configuration is done, you can start the VPN with

$ systemctl start namespaced-wireguard-vpn.target

If you would like it to always start on boot, you can enable it with

$ systemctl enable namespaced-wireguard-vpn.target

At this point, if there are no errors, you should have a new network namespace (by default named vpn). You can test it out by running some commands in the default (init) namespace and VPN namespace and comparing the output.

$ curl ifconfig.me/ip
$ ip netns exec $NETNS_NAME curl ifconfig.me/ip

You may want to confirm that DNS requests are going to your VPN's name servers.

$ nslookup example.com
$ ip netns exec $NETNS_NAME nslookup example.com

Configuring Other Units to Run in the Namespace

While ip netns exec is handy for one-off commands, this project is most useful to allow running other systemd units in a VPN-only namespace. This is accomplished by adding a drop-in override file to the unit. In the following example, we'll configure Transmission Daemon to run in our namespace.

/etc/systemd/system/transmission-daemon.service.d/10-vpn-netns.conf:

[Unit]
BindsTo=namespaced-wireguard-vpn-netns.service
After=namespaced-wireguard-vpn-netns.service
JoinsNamespaceOf=namespaced-wireguard-vpn-netns.service

[Service]
PrivateNetwork=yes

Future Work/TODO

Contributing

The configuration is geared for a Mullvad configuration, since that's the VPN I use, but I think it should be general enough to work with any simple WireGuard VPN setup that wg-quick could handle. If you need something more complicated, feel free to fork and open a merge request.