About me: My name is Solène Rapenne, pronouns she/her. I like learning and sharing knowledge. Hobbies: '(BSD OpenBSD Lisp cmdline gaming internet-stuff). I love percent and lambda characters. OpenBSD developer solene@.

Contact me: solene on libera.chat, solene+www at dataswamp dot org or @solene@bsd.network (mastodon). If for some reason you want to support my work, this is my paypal address: donate@perso.pw.

OpenVPN on OpenBSD in its own rdomain to prevent data leak

Written by Solène, on 16 December 2021.
Tags: #openbsd #openvpn #security

Comments on Mastodon

Introduction §

Today I will explain how to establish an OpenVPN tunnel through a dedicated rdomain to only expose the VPN tunnel as an available interface, preventing data leak outside the VPN (and may induce privacy issues). I did the same recently for WireGuard tunnels, but it had an integrated mechanism for this.

Let's reuse the network diagram from the WireGuard text to explain:

    |   server    | tun0 remote peer
    |             |---------------+
    +-------------+               |
           | public IP            |
           |              |
           |                      |
           |                      |
    /\/\/\/\/\/\/\                |OpenVPN
    |  internet  |                |VPN
    \/\/\/\/\/\/\/                |
           |                      |
           |                      |
           |rdomain 1             |
    +-------------+               |
    |   computer  |---------------+
    +-------------+ tun0
                    rdomain 0 (default)

We have our computer and have been provided an OpenVPN configuration file, we want to establish the OpenVPN toward the server using rdomain 1. We will set our network interfaces into rdomain 1 so when the VPN is NOT up, we won't be able to connect to the Internet (without the VPN).

Network configuration §

Add "rdomain 1" to your network interfaces configuration file like "/etc/hostname.trunk0" if you use a trunk interface to aggregate Ethernet/Wi-Fi interfaces into an automatic fail over trunk, or in each interface you are supposed to use regularly. I suppose this setup is mostly interesting for wireless users.

Create a "/etc/hostname.tun0" file that will be used to prepare the tun0 interface for OpenVPN, add "rdomain 0" to the file, this will be enough to create the tun0 interface at startup. (Note that the keyword "up" would work too, but if you edit your files I find it easier to understand the rdomains of each interface).

Run "sh /etc/netstart" as root to apply changes done to the files, you should have your network interfaces in rdomain 1 now.

OpenVPN configuration §

From here, I assume your OpenVPN configuration works. The OpenVPN client/server setup is out of the scope of this text.

We will use rcctl to ensure openvpn service is enabled (if it's already enabled this is not an issue), then we will configure it to use rtable 1 to run, this mean it will connect through the interfaces in the rdomain 1.

If your OpenVPN configuration runs a script to set up the route(s) (through "up /etc/something..." directive in the configuration file), you will have to by add parameter -T0 to the command route in the script. This is important because openvpn will run in rdomain 1 so calls to "route" will apply to routing table 1, so you must change the route command to apply the changes in routing table 0.

rcctl enable openvpn
rcctl set openvpn rtable 1
rcctl restart openvpn

Now, you should have your tun0 interface in rdomain 0, being the default route and the other interfaces in rdomain 1.

If you run any network program it will go through the VPN, if the VPN is down, the programs won't connect to the Internet (which is the wanted behavior here).

Conclusion §

The rdomain and routing tables concepts are powerful tools, but they are not always easy to grasp, especially in a context of a VPN mixing both (one for connectivity and one for the tunnel). People using VPN certainly want to prevent their programs to not go through the VPN and this setup is absolutely effective in that task.