While building a network-attached storage (NAS) device based on openmediavault (omv), I wanted to add a virtual private network (VPN) server to provide secure remote access to the NAS and to other resources on the local network. This made sense to me because currently the NAS will be left on at all times. Of course the VPN server will be WireGuard because of my past experience with it. In essence then, I wanted to duplicate what was done with the Raspberry Pi hosting my home automation system on a Intel Core i5-2400 system running openmediavault. Since both Raspberry Pi OS and omv are based on Debian, the procedure to install the VPN is almost identical on both systems as will be shown below.
This is all experimental. In the near future, the local network will be revamped. The plan calls for the addition of a firewall, probably based on pfSense, and the segregation of devices into different VLANs (written, as if I know what I'm talking about!) Clearly, some thought will have to be given to remote access. Time will tell if changes to the VPN servers are required.
Table of Contents
Re-inventing the Wheel
Someone had probably added WireGuard in omv. So I did a quick search and found the beta openmediavault-wireguard plugin. However, development seems to be halted since there has been only one commit in the last 18 months, and that was almost exactly a year ago.
There is also a June 30, 2019 forum discussion [HowTo] WireGuard with omv Super-Easy by henfri with many replies. The discussion starts with an installation script by henfri. I have not used it as it is not as complete as the Adrian Mihalko script which has worked very well on a Raspberry Pi and works just as well in Debian. If the henfri script is used, be aware that it uses UPnP to forward the necessary UDP port at the router. Many recommend disabling UPnP altogether, so perhaps one should forward the port manually or disable UPnP once WireGuard has been installed.
Finally, I will mention the OpenVPN plugin, openmediavault-openvpn 5.1
, found in the usual OMV-Extras.org channel. That usually means juggling CA certificates and other complications, but there are advantages to this older VPN, although I will not go into that topic here. I have not tested this plugin.
This was a cursory search and I apologize to everyone whose contribution has been overlooked.
Installing WireGuard
Installing openmediavault on a second generation i5 computer was fairly straightforward following the instructions in the New User Guide - Getting Started with Openmediavault 5. As recommended, all the configuration was done with the omv Web-based administration tool, including defining the host name (vault
in my case), setting up a static IP address, doing system updates and so on. But when I wanted to install a WireGuard VPN, I had to return to the command line and use standard Debian tools.
Version 5.6.1 of omv released February 27, 2021 is based on Debian 10.8 with version 5.10.0 of the Linux kernel. Given that this version of Debian was released on February 6, 2021, it was not too surprising that installing wireguard
was quite straight forward. In what follows, I opened an SSH session as root
from a terminal on my desktop.
Using a terminal from a Linux desktop to the omv machine is very simple: all that is required is to press the hotkey combination (usually AltT) to bring up a terminal emulator and then entering the ssh
command as shown above. Perhaps those using a different desktop operating system might want to use a terminal emulator in a Web browser. There was a plugin called shellinabox
for just that purpose in omv 4. This is no longer available in omv 5 as far as I can determine. There are recommendations to use Dockerized Wetty (weTTY in a Docker) as a replacement for the plugin. I do not have experience with either of these approaches.
Even though a user was added in omv, made a member of the important groups (users
, adm
, sudo
etc.), no directory for that user was created in the home
directory. That is why I logged in as root
as shown above which is something I rarely do. In any case, the WireGuard installation requires root privileges, so this will eliminate the need for the sudo
prefix usually needed when installing packages.
Once logged in, I checked that WireGuard was not already present, and then just installed it from the buster-backports
repository. Contrary to past installations in Raspbian and a recent installation in Rasbpberry Pi OS, this was done with a single install
command.
Unlike on the Raspberry Pi, the installation was completed in a short time. A quick check verified that the tools were now available. As a further test, the VPN server was started with an empty configuration file.
From there, it is easy enough to check that the WireGuard interface was created and that the VPN server was listening for incoming connections.
Of course, that last command, wg
, did not display much information because no connection was established. Because the Ethernet interface on my system it named eno1
instead of the classic eth0
, it will be necessary to adapt configuration script later on.
Configuring WireGuard
It is necessary to configure Wireguard in order to do anything useful. In the past I used a script by Adrian Mihalko to easily configure WireGuard on the Raspberry Pi. There is nothing in that script that is really Pi centric and it works just as well in the Debian distribution hosting omv. It would be worthwhile to read User management with Wireguard User Management Script written by Adrian Milhalko and return here for more information if needed.
It may be useful to raise a little point here. WireGuard operates a peer-to-peer network. However it is sometimes useful to look at it as a client-server model, such as here where the WireGuard peer running on the omv machine is viewed as a server and the WireGuard peers on various Linux and Android devices are viewed as clients. In the end, peer, server, client and user are all the same thing. Hopefully that will not be a source of confusion.
Installing the Adrian Mihalko User Management Script
There are a couple of prerequisites to install: unzip
to extract the script from a downloaded .zip
archive and qrencode
used to generate QR-code images that will make it very easy to configure WireGuard clients on Android and iOS devices.
Next the archive containing the script and supporting files needs to be downloaded and its content has to be extracted to a directory that will be called wp_config
or any other desired name.
In those last two steps a /root/downloads
directory was created and the script archive was moved into it while changing its name to something more meaningful. Instead, it would have been fine to just delete the archive.
Generating the Private and Public Server Keys
WireGuard encrypts the data exchanged over the virtual network. Much like SSH, asymmetric encryption is used to set up the secure session. Both server and client (or peers actually) have private and public keys, but only the latter are exchanged for authentication. Again, like SSH, the private keys have to be shared "out-of-band" beforehand. In this case that means that the keys must be manually copied to each peer configuration file. There is no third party "certificate authority" for SSL certificates as when using HTTPS or OpenVPN.
The first step, which is done only once, is to generate the private and public keys of the WireGuard server on the machine.
These two keys are needed in the next steps. Copy them into a text editor on the desktop or open a second SSH session on the Raspberry Pi for easy access to the keys later.
Normally, one never makes the private key public. So the keys shown above are only for demonstration purposes, and you must replace those values with the one actually generated.
Creating and Editing the Server Definition File
This step, performed once only, creates the wg.def
file which contains data the script will use to make the server and client configuration files.
This is the original content.
And this is how I changed it.
Note the change of the "private" WireGuard subnet from the suggested 192.168.99.0/24
to 192.168.199.0/24
. This is because WireGuard is already running on a Raspberry Pi at 192.168.99.1
. The _SERVER_PORT
is the UDP
port that will have to be forwarded to the WireGuard sever by the LAN router or gateway.
This can be (perhaps should be) changed. And, of course, it is necessary to change wg.example.com
in _SERVER_LISTEN
to the host name of the Raspberry Pi which, in my (fictitious) case, is:
modomo.twilightparadox.com
as explained in 2.2 Public IP Address or Dynamic Host Name. Enter just the domain name without a protocol specifier such as https://
. As I explained above, the public IP address assigned to me by my ISP changes
so rarely that I could get away with the public IP address instead of a host name for testing purposes!
If the CIDR notation 192.168.99.0/24
is not familiar, just think of the trailing integer after the slash as the number of fixed most significant 1 bits in the subnet mask. Well, that's really clear. Perhaps working out the example will help. The subnet mask is 32 bits (or 4 bytes) of which the most significant 24 are 1s and the least significant 8 bits are 0. Hence the mask is 255.255.255.0. So the virtual network peers will have IP addresses in the 192.168.99.xxx
block. The server will be at 192.168.99.1
, the first client at 192.168.99.2
, the second at 192.168.99.3
and so on. The script will handle this sequential allocation of IP addresses automatically.
WireGuard
IP addresses at 192.168.99.1
,
192.168.99.101
, and 192.168.99.151
on three different single-board computers. Android and Linux clients could connect to each without problems. Nevertheless, this time I chose different subnets altogether to avoid unnecessary complications. Whatever "private" subnet is chosen, care must be taken to avoid IP address collisions with any device already on the local network.
Editing the Client Configuration Template
The client configuration template, client.conf.tpl
, used by the script to create each user (or client) configuration file is quite short.
I changed the AllowdIPs
.
Note that the first AllowedIPs
(192.168.99.1/32
) is the address of the Wireguard server on the virtual network and the 32-bit mask means that the client/user will not be able to reach any other IP address on the 192.168.99.xx
subnet. The second allowed IP address 192.168.1.0/24
, which is the 192.168.1.xxx
block of IP addresses corresponding to my home local network. The Raspberry Pi has a static IP address on that network: 192.168.1.22
, the ISP supplied cable modem/router is at 192.168.1.1
and its integrated DHCP server allocates IP addresses in the 192.168.1.100-200
range where most of my IoT devices can be found. You will, of course, have to adjust the AllowedIPs
to refer to the correct IP addresses in your particular situation. It could be that your LAN is on subnet 192.168.1.xxx
as suggest above, or 192.168.0.xxx
, but some LANs use other blocks of private IPv4 addresses such as 10.0.3.xxx
.
Editing the Server Configuration Template
In the server configuration template, it is assumed that the name of the network interface used by the
host of the WireGuard server is eth0
. In my case that
is not correct, the Ethernet interface is named eno1
as we saw before, so
it was necessary to edit the sever configuration template.
The eth0
interface is replaced by eno1
in the
PostUp
and PostDown
lines that define changes
to the server iptables
when activating or deactivating the
VPN.
Again, this change needs to be done once only if at all.
Managing the WireGuard Service
When first installing WireGuard and when testing the installation of the server, it is useful to manually start and stop the service. This is done with the wg-quick
utility.
Again when testing, it may be of value to check on the status of the VPN server. This can be done with the systemd
control utility and with the wg
utility.
The above is only an indication of the information that may be displayed. It will depend on the number of peers/clients that have been set up. Even more information will be displayed when a client or peer has created a tunnel (i.e. opened a VPN connection) including the number of bytes transmitted and received through the connection.
Once WireGuard is properly installed, the service should be started automatically. This is done with the usual systemctl
command.
This is usually done only once. From then on, whenever the computer is booted, systemd
will start the VPN server. If for some reason the WireGuard service should no longer be automatically started, use the disable command.
It will be possible to enable the service again later. If one thinks about it, a VPN server should really be functioning at all times.
Managing Users and Using the VPN
I have already covered in much detail the use of the Mihalko user.sh
script to add or delete users in the WireGuard configuration. In the same post, there are descriptions of how to set up WireGuard clients in Android, Linux and Windows. The post also contains a quick explanation of how to use these clients with the WireGuard VPN. The original file by Adrian Mihalko contains instructions for setting up an iOS client.
There is more to using a self-hosted VPN. Again, my previous post about using WireGuard in Raspberry Pi OS contains information about the need to set up a static IP address for the omv machine (something easily done in omv, by the way), the interest in creating a dynamic host name in order to reach the machine from outside the local network. How to forward the UDP port used by WireGuard at the router is described in the post. Enabling IP forwarding is also described in the post. That is needed if the VPN is used to access resources over the local area network not installed on the omv server.