Get Rewarded! We will reward you with up to €50 credit on your account for every tutorial that you write and we publish!

Installing and configuring a WireGuard VPN server on Debian 9.9

profile picture
Author
Ben G
Published
2019-06-18
Time to read
12 minutes reading time

Introduction

WireGuard is a fast and secure alternative to other VPN software such as IPSec and OpenVPN. The benefit of WireGuard is that it is multithreaded and built into the kernel, meaning you can achieve symmetrical throughputs of 1Gbps even on lower end boxes, something that is not possible with OpenVPN. The server is very lightweight and easy to setup. There are clients for most operating systems including Windows.

Some other benefits of WireGuard include being able to run internal services such as SSH, FTP, and remote desktop, on the VPN IP address instead of the main IP address of the server, which reduces the possible attack vectors on your server. For example, you can enable SSH access for one user on your public IP, and all other users on the VPN IP only.

You can also tunnel part or all of your internet traffic over WireGuard as a VPN, and easily achieve speeds of over 1Gbps. If you are behind NAT and cannot port forward, a simple WireGuard server on a low end VPS is a good way to allow servers running on your computer to be accessible from the internet.

This tutorial will focus on installing WireGuard on a Debian 9.9 (Stretch) server.

Step 1 - Installation

After logging into your server via SSH, switch to the root user by typing sudo su -.

Run the following commands:

echo "deb http://deb.debian.org/debian/ unstable main" > /etc/apt/sources.list.d/unstable-wireguard.list
printf 'Package: *\nPin: release a=unstable\nPin-Priority: 150\n' > /etc/apt/preferences.d/limit-unstable
apt-get update

Install the headers for your kernel if you have not done so:

apt-get install linux-headers-$(uname -r|sed 's/[^-]*-[^-]*-//')

Then install WireGuard:

apt-get install wireguard

You should see output similar to:

Building for 4.9.0-8-amd64
Building initial module for 4.9.0-8-amd64
Done.

If you do not see this and see an error instead, ensure the linux headers you have installed are the same version as the kernel you are running (compare uname -a vs what is being built). You may need to reboot your server otherwise, for example if you have just done a dist-upgrade and not rebooted.

Step 2 - Server configuration

This guide will assume you have a server with a single client. WireGuard supports as many clients as needed, simply add another peer to the wg0.conf configuration file, and follow client installation steps again on the client.

First, generate public and private keys on the server:

wg genkey | tee /etc/wireguard/wg-private.key | wg pubkey > /etc/wireguard/wg-public.key

Ensure these can only be read by root by setting appropriate permissions for your system. Retrieve them for later with cat /etc/wireguard/wg-private.key and cat /etc/wireguard/wg-public.key.

This tutorial will use wg-quick for the running of the server. There are other methods, but this is the easiest to start with.

Create and edit the file /etc/wireguard/wg0.conf in your favorite text editor.

Here, 1.2.3.4 is the public IPv4 address of your server, 10.0.0.1 is the private IPv4 address used for the VPN server, and 10.0.0.2 is used for the client. If you need more clients, simply use other IPs (10.0.0.3, etc) within the subnet 10.0.0.0/24.

  • The private (10.0.0.1) IPv4 will be the VPN IP address of the server. This IP is not accessible from the public internet, and any services listening on it will only be accessible from within clients connected to the VPN.
  • This subnet can be changed to other private networks. Alternatively, you can use and forward public IP addresses if your server has at least 3 public IPv4, but this is outside the scope of the tutorial, and needs careful firewalling.

Add a configuration such as:

[Interface]
Address = 10.0.0.1/24
SaveConfig = false
ListenPort = 56
PrivateKey = PRIVATE KEY YOU GENERATED GOES HERE

[Peer]
PublicKey = NOTHING GOES HERE YET
AllowedIPs = 10.0.0.0/24, 10.0.0.2/32
PersistentKeepalive = 25

To explain each configuration parameter:

  • Address is the aforementioned private IPv4. The /24 subnet indicates that this will handle IPs 10.0.0.1 - 10.0.0.254.

  • SaveConfig does not allow changes made in the command line to affect the configuration file, which may cause problems in wg-quick mode.

  • ListenPort is the listening port of your server. This will need to be opened in your firewall.

    Take a look here for additional notes about how to configure a firewall for the WireGuard server.

  • PrivateKey is the private key generated for the server. The public key will be given out to each client. The rule of thumb: the private key does not leave the device it was generated on, but the public key does.

Each peer (you can add multiple in the same file) has a public key which will be generated on the client, as well as:

  • AllowedIPs: Here we place the subnet for our clients, as well as the allowed IP address for the client. Restrict this as needed (for example, remove the 10.0.0.0/24 if you do not want each client to be able to talk to other clients on that subnet).
  • PersistentKeepalive: Keeps the connection alive by sending a handshake every 25 seconds.

Step 3 - Client configuration

Repeat the installation steps up until "configuration" if you are running Linux on the client, otherwise download TunSafe or another client for other operating systems such as Windows.

Generate a public and private key on the client via the same process as the server, or with File -> Generate Key Pair in TunSafe. TunSafe's default configuration comes with a public/private key that must be changed for security, it is the same across all installations.

Add the public key you just generated to the server wg0.conf in the peer's PublicKey section.

Next, you will need to configure the client. The configuration is very similar to the server. In fact, you can run a client as a server by adding a ListenPort directive, and connect multiple servers together that way.

An example Linux client configuration, which only tunnels VPN traffic on 10.0.0.0/24, and not the entire internet of the client computer:

[Interface]
Address = 10.0.0.2/32
SaveConfig = false
PrivateKey = PRIVATE KEY OF CLIENT GOES HERE

[Peer]
PublicKey = PUBLIC KEY OF SERVER GOES HERE
AllowedIPs = 10.0.0.0/24
Endpoint = 1.2.3.4:56
PersistentKeepalive = 25

An example Windows client configuration (Windows does not support /31 or /32), which tunnels all traffic through the server, with IPv6 support:

[Interface]
PrivateKey = PRIVATE KEY OF CLIENT GOES HERE
# Switch DNS server while connected
DNS = 8.8.8.8
Address = 10.0.0.2/30, 2a01:4f8:1234::2/128

[Peer]
PublicKey = PUBLIC KEY OF SERVER GOES HERE
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = 1.2.3.4:56
PersistentKeepalive = 25

Where 1.2.3.4 is the public IPv4 address of your server. Remove the IPv6 addresses if you do not want IPv6 support.

If you want IPv6 support, you will also need to add the client's IPv6 address to the server configuration under the peer's AllowedIPs. Each server gets a /64 so you can allocate an individual IP in there to your client (or a smaller subnet). Keep in mind when forwarding a public IPv6 you will need to firewall it correctly, which is outside the scope of this tutorial (it can either be firewalled on the client with windows firewall or the server with iptables, for example). It is possible to forward public IPv4 in a similar way. The benefit of doing this is you do not need NAT on the server-side for port forwarding.

Step 4 - Further server configuration in special cases

The AllowedIPs parameter on the client will specify what IP ranges go through the tunnel and what do not. You will need to configure iptables on the server like so to enable external internet access if forwarding all traffic (ie the 0.0.0.0/0 configuration):

echo 1 > /proc/sys/net/ipv4/ip_forward
nano /etc/sysctl.conf

Find and change net.ipv4.ip_forward = 0 to net.ipv4.ip_forward = 1

Install package iptables and iptables-persistent, then iptables-save > /etc/iptables/rules.v4 to save the config across reboots:

iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o enp1s0 -j SNAT --to-source 1.2.3.4
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -j MASQUERADE

Replace enp1s0 with the main interface (you can check this with ifconfig).

If you want to port forward, consider:

iptables -t NAT -A PREROUTING -d 1.2.3.4/32 -i enp1s0 -p tcp -m tcp --dport 45000 -j DNAT --to-destination 10.0.0.2:48000

This will make a tcp service running on a client at 10.0.0.2:48000 accessible from the internet at 1.2.3.4:45000. A nginx reverse proxy may also be used as an alternative with the proxy_pass directive.

Step 5 - Enable the server

To start the server,

  • systemctl enable wg-quick@wg0 (start at boot)
  • systemctl status/stop/start/restart wg-quick@wg0 (as needed)

You can also run this on any Linux client. For Windows clients, start the client in the TunSafe client. If it gets stuck at "Sending handshake", there is a configuration or firewall issue. You will see "Connection established" when the connection is successful.

To check if things are working, type wg. This will display an output such as:

interface: wg0
  public key: removed
  private key: (hidden)
  listening port: 56

peer: removed
  endpoint: 12.13.14.15:31844
  allowed ips: 10.0.0.2/32, 2a01:4f8:1234::1/128
  latest handshake: 11 seconds ago
  transfer: 2.16 TiB received, 1.67 TiB sent
  persistent keepalive: every 25 seconds

If your client has connected correctly, you will see last handshake and total transfer.

You can now ping your server/client through the tunnel: ping 10.0.0.1. Any services bound to 0.0.0.0 or 10.0.0.1 will also be accessible from your clients over the VPN. Finally, with the AllowedIPs = 0.0.0.0/0 configuration, all internet traffic will be tunnelled over the VPN connection too.

To secure services to the VPN, either set their bind address to the VPN IP (10.0.0.1), or limit the access to 10.0.0.0/24 (for example, the AllowUsers directive in sshd_config: AllowUsers root@10.0.0.*). Avoid locking yourself completely out of the server doing this, and always leave a service open to all IPs while making changes in case something goes wrong. If you do lock yourself out, you will need to request a KVM console in robot and fix your mistakes.

Step 6 - Reloading config file (Optional)

To reload the configuration file completely, you will need to restart the server (this will kill current connections):

systemctl restart wg-quick@wg0

If you just want to add a client after updating the configuration file, you can instead run:

wg addconf wg0 <(wg-quick strip wg0)

This will not break existing connections.

Step 7 - Troubleshooting

  • Can you connect to the server at all? Type sudo wg. Do you see a handshake having taken place recently? If so, you are connected. If not, check your public and private keys, as well as firewall rules.
  • Can you connect to the server but not access the internet in a 0.0.0.0/0 configuration? If you can ping the server itself (10.0.0.1), it may be an iptables issue. Make sure you added the rule correctly, and cat /proc/sys/net/ipv4/ip_forward returns 1.
  • Can you not ping a windows client? Windows blocks ICMP by default on the 10.0.0.0/8 range, so you will need to enable it in windows firewall. The same applies to any service running on a windows client.
  • Slow speeds? Check your CPU usage on the client and server. If your CPU is maxing out, that is the problem, but you should have no issue with multi-gigabit speeds on a modern 4-core processor. Try killing or renicing other applications that might be using the CPU. You will not see WireGuard as a process as it runs in the kernel, but you will see its CPU usage as red bars in htop.
  • Cannot access a service at https://10.0.0.1:PORT? Type netstat -tulpn and check it is listening on 0.0.0.0 or 10.0.0.1, not 127.0.0.1 or 1.2.3.4.
  • TunSafe may need you to reboot your computer.
  • As a client, cannot access something running on another client? Ensure server allows FORWARD between the two clients in iptables / ufw. Also ensure /proc/sys/net/ipv4/ip_forward = 1.

Conclusion and further reading

By now you should have a working VPN server running WireGuard, congratulations!

The WireGuard page on the Debian wiki has alternatives to wg-quick and is useful for further reading, if you wish to use systemd or /etc/network/interfaces for configuration.

License: MIT
Want to contribute?

Get Rewarded: Get up to €50 in credit! Be a part of the community and contribute. Do it for the money. Do it for the bragging rights. And do it to teach others!

Report Issue

Discover our

Dedicated Servers

Configure your dream server. Top performance with an excellent connection at an unbeatable price!

Want to contribute?

Get Rewarded: Get up to €50 credit on your account for every tutorial you write and we publish!

Find out more