Skip to content

Wireguard on qnap docker container

wireguard and qnap

I will explain you how to run Wireguard on your Qnap NAS as a docker container using Container Station.

Introduction

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.

Docker container

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.g. 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 = 1.1.1.1 # 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.

Conclusion

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.

13 thoughts on “Wireguard on qnap docker container”

  1. Hi,
    I just used your method to setup wireguard on my T451+(intel QNAP), but it was failed. The concole message is as below,

    Unable to access interface: Protocol not supported
    [#] ip link delete dev wg0
    Cannot find device “wg0”
    [#] ip link add wg0 type wireguard
    RTNETLINK answers: Not supported

    Would you please advice me how could I start the service ?

    Thank you.

    1. Hi, It sounds strange to me, as your ts-451 and my ts-453 are quite similar. I really do not know what the issue could be.

      Unable to access interface: Protocol not supported
      [#] ip link delete dev wg0
      Cannot find device “wg0”

      I have never saw these lines on my container console.

      [#] ip link add wg0 type wireguard
      RTNETLINK answers: Not supported

      These two ones are somehow normal, as it tries to load the kernel module and this is not possible, that is why we are using the userspace implementation of wireguard. Right after this lines my container console show how the container uses this implementation.

      [#] ip link add wg0 type wireguard
      RTNETLINK answers: Not supported
      [!] Missing WireGuard kernel module. Falling back to slow userspace implementation.
      INFO: (wg0) 2021/04/11 12:31:20 Starting wireguard-go version 0.0.20200320
      DEBUG: (wg0) 2021/04/11 12:31:20 Debug log enabled
      [#] wireguard-go wg0
      WARNING WARNING WARNING WARNING WARNING WARNING WARNING
      W G
      W You are running this software on a Linux kernel, G
      W which is probably unnecessary and misguided. This G
      W is because the Linux kernel has built-in first G
      W class support for WireGuard, and this support is G
      W much more refined than this slower userspace G
      W implementation. For more information on G
      W installing the kernel module, please visit: G
      W https://www.wireguard.com/install G
      W G
      WARNING WARNING WARNING WARNING WARNING WARNING WARNING
      [#] wg setconf wg0 /dev/fd/63
      INFO: (wg0) 2021/04/11 12:31:20 Starting wireguard-go version 0.0.20200320
      DEBUG: (wg0) 2021/04/11 12:31:20 Debug log enabled
      DEBUG: (wg0) 2021/04/11 12:31:20 Routine: event worker – started
      DEBUG: (wg0) 2021/04/11 12:31:20 Routine: decryption worker – started
      DEBUG: (wg0) 2021/04/11 12:31:20 Routine: handshake worker – started
      […]

      Are those lines the only ones that appear in your console? If there are more messages, provide me all the console output to check if I can see anything else.

      You can also check a few things:

      – From inside the container terminal, check If ‘/etc/wireguard/wg0.conf’ is properly configured (paste it here for checking).

      – From inside the container terminal, execute ‘ip address’ command and check if wg0 interface is shown there.

      – Check if ‘/dev/net/tun’ exists in your nas, not inside the container, you will need to ssh into your nas to check this with ‘ls -l /dev/net/tun’

      I am sorry I cannot say much more, If you can pass me your configurations (wg0.conf, compose file, …) and as much logs as you can, I will be glad in review them to see if I can find something than can cause the issue.

      Please let me know of any advance.

      Regards.

  2. This is not working on my TS-451+. I used the instructions as directed. However, nothing is connecting. Using a port scanner to my public IP shows that 51820 is closed. I have it forwarding to my NAS with an internal IP of 192.168.0.10. The docker has an IP of 172.29.4.2. How this was generated is beyond my knowledge of the QNAP virtual switch. I tried to port forward to that as well on my router, but I get the same results – port closed, incoming traffic denied.

    The VPN Client on my phone sends data but never gets anything back. I’ve verified the generated keys, but if the data is never even reaching the server, then nothing will work anyway. I have QuFirewall turned off as well. Any ideas?

    1. Hi, This is strange. Provided You have forwarded 51820 UDP port on your router to your NAS internal ip, packets should be arriving to it. Container exposes this port (51820/UDP) so you should be able to check it with a command like netstat on your nas command line (try ‘netstat -puntl|grep 51820’). If all of this is fine, perhaps there is something on the container logs to guide us to the cause of this issue.

      By the way, last versions of qnap firmware ships with more modern kernels that already supports wireguard natively, so the qnap vpn app should support it as well. Perhaps you can try this way as It is more effective an reliable. Hope this helps.

  3. I’m experiencing a similar situation with my QNAP 253A. Although the required port for the connection is available, I’m unable to establish a connection to the container. It’s worth noting that the QuFirewall is not installed on my device. Here’s the log obtained by using SSH to access the NAS.

    [~] # netstat -puntl|grep 51820
    udp 0 0 0.0.0.0:51820 0.0.0.0:* 26793/dockerd
    [~] # telnet localhost 51820
    telnet: can’t connect to remote host (127.0.0.1): Connection refused
    [~] # telnet 127.0.0.1 51820
    telnet: can’t connect to remote host (127.0.0.1): Connection refused

    1. Hi Joe, as stated in your netstat output, port 51820 is open so I will assume that the container is exposing that port properly.

      The problem with your tests (telnet) is that you are trying to establish a TCP connection against an UDP port and that would never is going to work. I would suggest you to do a real test, like configuring a wireguard client and trying to connect from it. Please, let me know If it this test finally worked.

      As a side note, I will comment that some time ago qnap added native wireguard support to QTS firmware, so perhaps there is no need to use the userspace implementation nowadays. I do not know you use case, just letting you know.

      Hope this helps.

  4. For whatever reason that YAML won’t validate for me, and I confirmed it’s due to the line: – /share/Container/wireguard:/etc/wireguard

    if I comment out that line, it works. How do I create the folder prior to this step? I actually did create a “wireguard” folder inside “Container” folder on my DataVol1. But what if I had multiple data volumes, how would container station know where to look?

    1. Hello Michael, I’m glad it finally worked for you. As I told Joe, you can also try the native WireGuard version if it is supported by your QNAP firmware. Best regards.

Leave a Reply

Your email address will not be published. Required fields are marked *