DEV Community

Cover image for 4 Step WireGuard Tutorial
Stefan Wintermeyer
Stefan Wintermeyer

Posted on

4 Step WireGuard Tutorial

WireGuard can be used to quickly setup a private tunnel/network between one server with a public IP address and one or multiple peers which might be behind a NAT. Let me show you how.

All commands in this tutorial have to be run with root privileges.

1. IP-Address Setup

We assume that the public IP address of the server is 172.16.187.4 and that the new WireGuard setup uses IP addresses within the 10.0.0.1/24 range. Please change those values according your setup.

Internal IP Address Public IP Address
Server (Debian) 10.0.0.1 172.16.187.4
Peer 1 (Debian) 10.0.0.2 unknown behind NAT
Peer 2 (Debian) 10.0.0.3 unknown behind NAT
Peer 3 (macOS) 10.0.0.4 unknown behind NAT

2. Install WireGuard on Debian GNU/Linux

Install the WireGuard software on the server and all clients. For Debian 10.x systems (find out which version you run with lsb_release -a) you have to use buster-backports to do so:

$ echo 'deb http://deb.debian.org/debian buster-backports main' \ 
>> /etc/apt/sources.list
$ apt-get update
$ apt-get install wireguard/buster-backports
Enter fullscreen mode Exit fullscreen mode

If you are running Debian 11 (Bullseye) or later you don't need the backport and can just run apt-get install wireguard

After that create a private and public key on each system:

$ umask 077
$ cd /etc/wireguard
$ wg genkey | tee privatekey | wg pubkey > publickey
$ cat privatekey 
uA3OFbVYW7QP4qDQlqIzrie2B3+kX+0NcxkY2XEMBl0=
$ cat publickey 
2M1BpjkzBU5z9/NyFy+661rhKLA+1hKKV7KI8J/SB18=
Enter fullscreen mode Exit fullscreen mode

Firewall

If you are running a firewall on your server have to open a port for WireGuard. In our setup we use UDP port 51820. For the popular UFW firewall this is the needed command:

$ ufw allow 51820/udp
Enter fullscreen mode Exit fullscreen mode

3. Server Configuration

For the clients to be able to communicate to each other you have to make sure that you have ip_forward activated in /etc/sysctl.conf:

$ sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/g' \ 
/etc/sysctl.conf
$ sysctl --system
Enter fullscreen mode Exit fullscreen mode

Use your favorite editor to create a file /etc/wireguard/wg0.conf with the following content. Use the private and public keys you just created on the server and all the peers. Do not use the example keys from this tutorial!

Adjust the peer entries according to your own needs. One entry per peer.

[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = uA3OFbVYW7QP4qDQlqIzrie2B3+kX+0NcxkY2XEMBl0=

[Peer]
PublicKey = 2KyqIPdsgroQZvucFVF2VEy64zeR1744gqwcXzqBfhw=
AllowedIPs = 10.0.0.2/32

[Peer]
PublicKey = 0qDtefB2NZTNZ3uYEOmmR7J7VUdzONqWfvZ+ZGpnDQU=
AllowedIPs = 10.0.0.3/32

[Peer]
PublicKey = 3ayqIPdsgroQZvucEOmmR7J7VUdzONqWfvZ+ZGpnDQU=
AllowedIPs = 10.0.0.4/32
Enter fullscreen mode Exit fullscreen mode

Fire it up the first time manually:

$ wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.0.0.1/24 dev wg0
[#] ip link set mtu 1420 up dev wg0
Enter fullscreen mode Exit fullscreen mode

Stop it manually:

$ wg-quick down wg0
[#] ip link delete dev wg0
Enter fullscreen mode Exit fullscreen mode

If you want to have it activated all the time (which you probably do):

$ systemctl enable wg-quick@wg0
$ systemctl start wg-quick@wg0
Enter fullscreen mode Exit fullscreen mode

Use the command wg to get an overview:

$ wg
interface: wg0
  public key: 2M1BpjkzBU5z9/NyFy+661rhKLA+1hKKV7KI8J/SB18=
  private key: (hidden)
  listening port: 51820

peer: 2KyqIPdsgroQZvucFVF2VEy64zeR1744gqwcXzqBfhw=
  allowed ips: 10.0.0.2/32

peer: 0qDtefB2NZTNZ3uYEOmmR7J7VUdzONqWfvZ+ZGpnDQU=
  allowed ips: 10.0.0.3/32

peer: 3ayqIPdsgroQZvucEOmmR7J7VUdzONqWfvZ+ZGpnDQU=
  allowed ips: 10.0.0.4/32
Enter fullscreen mode Exit fullscreen mode

You are now all set on the server side.

4. Peer configuration

Debian Linux

On each peer you have to create a /etc/wireguard/wg0.conf file with this content. Please replace the keys with your own ones. Use the ones you created with wg genkey | tee privatekey | wg pubkey > publickey during the installation of WireGuard on the peers.

[Interface]
PrivateKey = oH+eQXaI3VMj9XDaUWmAghPXmsLTDAjzONPWwISw1no=
Address = 10.0.0.2/32

[Peer]
PublicKey = 2M1BpjkzBU5z9/NyFy+661rhKLA+1hKKV7KI8J/SB18=
Endpoint = 172.16.187.4:51820
AllowedIPs = 10.0.0.1/24
PersistentKeepalive = 25
Enter fullscreen mode Exit fullscreen mode

Replace 10.0.0.2 with the internal WireGuard IP of your peer (e.g. 10.0.0.3 or 10.0.0.4).

If your peer is not behind a NAT you don't need the PersistentKeepalive = 25 line which just configures a keep alive ping to the server.

Fire it up the first time manually:

$ wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.0.0.1/24 dev wg0
[#] ip link set mtu 1420 up dev wg0
Enter fullscreen mode Exit fullscreen mode

Stop it manually:

$ wg-quick down wg0
[#] ip link delete dev wg0
Enter fullscreen mode Exit fullscreen mode

If you want to have it activated all the time (which you probably do):

$ systemctl enable wg-quick@wg0
$ systemctl start wg-quick@wg0
Enter fullscreen mode Exit fullscreen mode

You might need to run a systemctl restart wg-quick@wg0 on the server in case you ran into a chicken-egg-problem with the key configuration.

Use the wg command to get an overview:

$ wg
interface: wg0
  public key: 2KyqIPdsgroQZvucFVF2VEy64zeR1744gqwcXzqBfhw=
  private key: (hidden)
  listening port: 33067

peer: 2M1BpjkzBU5z9/NyFy+661rhKLA+1hKKV7KI8J/SB18=
  endpoint: 172.16.187.4:51820
  allowed ips: 10.0.0.0/24
  latest handshake: 1 hour, 18 minutes, 37 seconds ago
  transfer: 8.40 KiB received, 7.52 KiB sent
Enter fullscreen mode Exit fullscreen mode

macOS

Install the WireGuard software from the app store at https://apps.apple.com/us/app/wireguard/id1451685025

Use the same config in the macOS peer as in the Debian peer.

Top comments (5)

Collapse
 
tlsalex profile image
tlsalex

The clients(10.0.0.2 , 10.0.0.3 , 10.0.0.4) can ping server(10.0.0.1) without problem , but did you ever try to ping the client each other, it works or not ? in my case ,it didn't work at all, any advise ?

Collapse
 
wintermeyer profile image
Stefan Wintermeyer

It works in my setup. I'd check the firewall.

Collapse
 
brokenchains profile image
Shan • Edited

Hey, i have this peculiar situation, can you suggest a solution. So the client and server are connected over ipv6 on eth0 interface, how would the configuration and other settings look like for wg0 if i want my wire guard interface to be ipv4. How to do that?

Collapse
 
tlsalex profile image
tlsalex

how about the setup of "WireGuard Over http(s)" ?

Collapse
 
wintermeyer profile image
Stefan Wintermeyer