Dim - Continued
Some people have a NAS server (or Nextcloud) on which to store files and movies. However, it might not be possible to compile and run Dim on the same server, and it could also be a good idea to separate the two servers (just in case).
Fortunately, we can share a directory over the network using NFS. NFS is a network filesystem, and is included in the Linux Kernel. There are clients in Windows and MacOS for the protocol, and it's possible to use on Kubernetes and Docker Swarm.
Why it's better to create a Wireguard tunnel?
The problem with NFS is that in it's default configuration, the authorisation system uses a simple IP, and it's very easy to fool/spoof it. Also, it's not encrypted, so it's possible to hack it. But we can create a secure encrypted tunnel using Wireguard, which only permits the machine with the correct public/private key to connect with the NFS directory.
Wireguard is a new and fast VPN protocol, also included in the Linux kernel, and has clients for Android, OpenWRT, MacOS and Windows.
NFS allows the restriction in the access of a network directory to a single IP, and Wireguard allows us to give a specific IP on a distinct subnet to clients which authenticate using secure public/private key cryptography.
Wireguard
The Wireguard tunnel runs on a distinct subnet to the server's IP address. For example, the server can have an IP of 192.168.1.10
but have a distinct IP for Wireguard on another subnet, eg 10.1.0.1
.
NFS
For the server/NAS of NFS, which contains the movies
sudo apt install nfs-kernel-server
We have to configure the NFS service to only listen on a single IP (of the Wireguard tunnel). Also, we'll configure it to only use the new protocol NFSv4.
We'll modify the file /etc/default/nfs-kernel-server
nano /etc/default/nfs-kernel-server
And find and add the following lines:
RPCNFSDOPTS="-N 2 -N 3"
to force it to use only the newest version 4 protocol.
RPCMOUNTDOPTS="--manage-gids -N 2 -N 3 -H 10.1.0.1"
to force it to use the tunnel IP.
We'll edit the file /etc/nfs.conf
nano /etc/nfs.conf
And add the following, to make sure the NFS service is only listening on the tunnel IP.
[nfsd] host=10.1.0.1
We have to figure out where the movies are stored.
We modify the exports file (nano /etc/exports
) to contain the following:
/the/route/to/the/movies (the client's tunnel IP)/32(rw,sync,no_subtree_check,no_root_squash)
Eg, as I keep my movies on my nextcloud, my configuration is:
/var/cloud/user/movies 10.1.0.2/32(rw,sync,no_subtree_check,no_root_squash)
10.1.0.2/32
is the IP of the client, inside the tunnel
We can export the directory:
sudo exportfs -a
NFSv4 doesn't need some services, so we can deactivate them:
sudo systemctl mask rpcbind.service
sudo systemctl mask rpcbind.socket
Note: In my case, I use Kaspersky Endpoint Security on the server to protect it from malware. The Kaspersky antivirus (KESL) has a feature called anti-cryptor, which monitors the NFS server to prevent a compromised client from deploying ransomware and encrypting all the files on the network share. However, it needs the rpcbind service to function, otherwise it doesn't detect that NFS is running.
and can start the NFS service:
sudo systemctl enable --now nfs-kernel-server.service
The Client:
sudo apt install nfs-common
First, we verify that the authentication works. That is, we want to verify that we can't connect to the NFS without using Wireguard. For this, we can check the error that's given when we try to connect a client which is not permitted.
mkdir /mnt/NFS
sudo mount -t nfs -o vers=4.2 (the *normal* IP of the server/NAS):/route/to/movies /mnt/NFS
If everything works correctly, we want an error like:
mount.nfs: Operación not permitted
or mount.nfs: access denied...
Wireguard
Installing Wireguard on the server and client (run on both):
sudo apt install wireguard
sudo modprobe wireguard
Generate the keys:
cd /etc/wireguard
umask 077
wg genkey > claveprivada
wg pubkey < claveprivada > clavepublica
Server
We create and modify the archive for wireguard:
nano /etc/wireguard/wgNFS.conf
Note, that you can choose the subnet and tunnel IP arbitrarily. We can use for example something like 10.1.0.0/24 range and add the following:
[Interface]
Address = 10.1.0.1/24 #the *tunnel* IP of the servidor/NAS
ListenPort = 51820
PrivateKey = THE_PRIVATE_KEY_OF_THE_SERVER
# client1
[Peer]
PublicKey = THE_PUBLIC_KEY_OF_THE_CLIENT
AllowedIPs = 10.1.0.2/32 #The tunnel IP of the client (chosen arbitrarily)
We can find out the public and private keys using: cat claveprivada
and cat clavepublica
Client
As above, we create and modify the Wireguard file:
nano /etc/wireguard/wgNFS.conf
and add the following:
[Interface]
Address = 10.1.0.2/24
PrivateKey = PRIVATE_KEY_OF_THE_CLIENT
[Peer]
PublicKey = PUBLIC_KEY_OF_THE_SERVER
Endpoint = the real IP of the server:51820
AllowedIPs = 10.1.0.0/24
We can start the Wireguard tunnel using:
sudo wg-quick up wgNFS
on the server, and later the same on the client.
If everything works, we can check using:
ping 10.1.0.1
and ping 10.1.0.2
Mount the folder through Wireguard
On the client we can again try to run sudo mount -t nfs -o vers=4.2 (the *tunnel* IP of the server/NAS):/route/to/movies /mnt/NFS
and this time it should work. We can see the files on the client using ls /mnt/NFS
Making it permanent:
for those using systemd, you can do the following:
# start it automatically when the system starts
sudo systemctl enable wg-quick@wgNFS.service
sudo systemctl daemon-reload
# stop wireguard
sudo wg-quick down wgNFS
# start wireguard using systemd
sudo systemctl start wg-quick@wgNFS.service
sudo umount -f /mnt/NFS
We edit fstab to mount it automatically, and add the following:
10.1.0.1:/route/to/movies /a/folder/on/the/client nfs vers=4.2,_netdev,noauto,x-systemd.automount,x-systemd.requires=wg-quick@wgNFS.service
and reload the services
sudo systemctl daemon-reload
sudo systemctl restart remote-fs.target
If everything worked, in /a/folder/on/the/client which we specified above, should be the files from the server.
UFW
If we use a firewall like UFW, we need to allow port 2049, used by NFS:
On the server, we can run:
sudo ufw allow from (tunnel ip from wireguard) to any port 2049
,
,
,
,
,
Runit
If you use runit:
you can use the following file run
to mount the directories:
#!/bin/sh
set -e
exec 2>&1
# Load user defined variables
[ -r conf ] && . ./conf
# Ensure the network manager is running
# If it's running or not in used - rc.local - discover default gateway
if [ -z "$GATEWAY" ]; then
set -- $(ip route show | grep default)
GATEWAY="$3"
fi
ping -W 1 -c 1 $GATEWAY > /dev/null 2>&1 || exit 1
# Network is up and running so now mount network filesystems from fstab
mount -a -t "$NETWORK_FS" || exit 1
mount -a -O _netdev || exit 1
# Then wait to behave like the service is up
exec chpst -b netmount sleep 100000
the file conf
:
# Configuration for netmount service
NETWORK_FS="nfs4"
and the file stop
#!/bin/sh
# Load user defined variables
[ -r conf ] && . ./conf
# Don't do anything if ./run didn't exit properly
[ "$1" -eq 1 ] && exit 0
# Simply umount network filesystems
umount -a -f -t $NETWORK_FS > /dev/null 2>&1
ret=$?
[ $ret -ne 0 ] && umount -a -f -l -t $NETWORK_FS > /dev/null 2>&1
umount -a -f -O _netdev > /dev/null 2>&1
ret=$?
[ $ret -ne 0 ] && umount -a -f -l -O _netdev > /dev/null 2>&1
#chpst -b netmount pause
for wireguard, i couldn't get the service for runit, so i set it using cron (crontab -e
)
@reboot wg-quick up wgNFS