I will explain you how to run Wireguard on your Qnap NAS as a docker container using Container Station.
I have been using Wireguard for some time on Linux systems with Android and Linux clients. I am very happy with its performance an reliability. Wireguard is a fast and modern point-to-point vpn protocol, easy to setup and very performant. It uses strong and modern cryptography and has a small code footprint. You can find out more on the Wireguard site.
Today I will show you how to run Wireguard on your Qnap NAS server as a docker container, using Qnap Container Station. This way you will be able to externally connect to your NAS in a very secure way. Also If you want you will be able to reach other systems in your home network through the vpn tunnel.
Note that we wont’t be using the kernel implementation of Wireguard. Wireguard is included since the 5.6 version on the Linux kernel. At this moment my NAS is using version 4.14 version of the kernel, so I cannot use the Wireguard kernel module. I do not know if Qnap plans to include the module or update the kernel to a valid version in a near future but I figure out it can take a while.
Instead we will be using the userspace implementation of Wireguard, written in Go. This implementation is not as performant as the kernel implementation, even though I have been also testing it with very good results.
We will need Container Station installed on our Qnap. Also we need to create a persistent folder (e.g. /share/Container/wireguard) to keep Wireguard configuration files and not lose them in case that we need to recreate the container.
To create the container open Container Station, then click on Create, and on the top right click on Create Application button. This will open a dialog where you can paste a Docker Compose file. Set an application name and paste the YAML code below.
version: '3.3' services: wireguard: image: masipcat/wireguard-go:latest container_name: wireguard cap_add: - NET_ADMIN sysctls: - net.ipv4.ip_forward=1 volumes: - /dev/net/tun:/dev/net/tun # Persistent folder you created before - /share/Container/wireguard:/etc/wireguard environment: - WG_COLOR_MODE=always - LOG_LEVEL=debug ports: - 51820:51820/udp privileged: true restart: unless-stopped
Create keys for server and client
Next we need to create some keys for the peers acting as server and client and also a configuration file for each peer. We will call ‘server’ to our Qnap NAS peer and ‘client’ to the device that will connect to the NAS (e.j. phone, laptop).
We need to execute some commands in our container to generate public and private keys for the client and server. This can be done directly from the container terminal. You can access the container terminal from Container Station overview page, unfolding the application you created, and clicking in the terminal button (>_). Type ‘/bin/bash’ as your command, and then ‘OK’. A new tab will open on your browser with a terminal from our container.
To generate the server keys execute following commands:
bash-5.0# echo -n "server private key: ";wg genkey server private key: GPZ/qF/GFCMi65neErSj1KxslsmFOmKQdaB/8GRuLWU= bash-5.0# echo -n "server public key: ";echo GPZ/qF/GFCMi65neErSj1KxslsmFOmKQdaB/8GRuLWU=|wg pubkey server public key: 2NPyahRD4k0rjg1ERAA1873E/s42JSmoPz+vpVgbzW4=
Client keys are generated in the same way:
bash-5.0# echo -n "client private key: ";wg genkey client private key: wKzA7588TIQ5r9IOimBZdJoFdYniEfRWojaX412BrHo= bash-5.0# echo -n "client public key: ";echo wKzA7588TIQ5r9IOimBZdJoFdYniEfRWojaX412BrHo=|wg pubkey client public key: LInzz/1nT/x+vbuQLWbk85rQw2Ca63huFuhWMPDqHT8=
Keys will be shown on screen, you will need them in next step to create the server and client configuration files. Note that the public key is derived from the corresponding private one.
Server configuration file
Enter the directory /etc/wireguard. Then create the file wg0.conf.
cd /etc/wireguard sh -c 'umask 077; touch wg0.conf'
You can edit the file from terminal with vi editor or, if you have Text Editor installed on your NAS you can access it from the mapped folder (e.g. /share/Container/wireguard/wg0.conf)
## server configuration (wg0.conf) [Interface] Address = 10.13.13.1/24 ListenPort = 51820 PrivateKey = <server privatekey> ## uncomment next two lines if you also want to gain access to your entire lan or if you ## want all traffic to go through the tunnel #PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE #PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE [Peer] PublicKey = <client publickey> AllowedIPs = 10.13.13.2/32
- Replace ‘server privatekey’ and ‘client publickey’ by the ones created before.
- Address: You can choose any address that does not overlap with your private LAN, for the examples I am using IPs from the 10.13.13.0/24 network. Modify server and client configuration files if you change it.
- ListenPort: you can use whatever port you want. Just make sure to forward it in your router to your NAS server and configure it in the docker-compose yaml and in the client configuration.
- If you want to reach your entire network from the client or send all traffic through the tunnel, uncomment both PostUp and PostDown lines.
It is time to restart the container to apply the configuration and to bring the interface wg0 up. You can restart the container from the overview page on Container Station. After this, your Wireguard server is ready to accept connections.
Client configuration file
Create the client configuration file client1.conf.
cd /etc/wireguard sh -c 'umask 077; touch client1.conf'
## client configurtion (client1.conf) [Interface] Address = 10.13.13.2/24 PrivateKey = <client privatekey> DNS = 184.108.40.206 # use custom dns, optional [Peer] PublicKey = <server publickey> Endpoint = <your public ip>:51820 AllowedIPs = 10.13.13.0/24 ## if you want also reach you remote lan, add it to AllowedIPs ## e.g. AllowedIPs = 10.13.13.0/24, 192.168.1.0/24 ## if you want all traffic go over the tunnel, add 0.0.0.0/0 ## e.g. AllowedIPs = 0.0.0.0/0 ## uncomment below to keep the connection alive #PersistentKeepalive = 25
- This client config should be copied to the client device you want to use (e.g. mobile, laptop) in a secure way.
- AllowedIPs: a comma separated list of networks that should be reached from the client. Add 0.0.0.0/0 if you want all client traffic go through the tunnel.
- PersistentKeepalive: uncomment this line if you want to keep the tunnel up even with no traffic, or if you are experiencing issues because of being behind nat.
Once you copy this configuration to your client and enable it, you should be able to reach your server tunnel ip, and if configured to do so, to your NAS and your internal network, or pass all the traffic through the tunnel.
We have seen how to configure Wireguard on our Qnap server as a docker container. If you have any question or comment, please let me know.