Differences between revisions 8 and 9
Revision 8 as of 2021-08-31 20:03:27
Size: 7623
Editor: ?ThomasDaly
Comment: Spelling error correction
Revision 9 as of 2021-12-17 09:14:26
Size: 7623
Editor: ?OlofSivertsson
Comment: Correct sysctl parameter for IPv6 forwarding
Deletions are marked like this. Additions are marked like this.
Line 106: Line 106:
    post-up sysctl --write net.ipv4.conf.all.forwarding=1     post-up sysctl --write net.ipv6.conf.all.forwarding=1
Line 108: Line 108:
    post-down sysctl --write net.ipv4.conf.all.forwarding=0     post-down sysctl --write net.ipv6.conf.all.forwarding=0

Translation(s): српски

(Simple) Private Tunnel VPN with WireGuard

If you own a Virtual Machine or Virtual Private Server, you can easily setup a VPN server with WireGuard on it to securely tunnel your internet traffic from your home or office.

Once connected to the VPN, outgoing traffic from your VPN client will appear as coming from your server.

There are multiple tutorials online describing how to achieve such a setup. This tutorial uses the default recommended tools for a server with Debian 10 or 11 : ifupdown and nftables. For configuration using other network tools, see WireGuard

Don't follow tutorials which recommend executing a random script downloaded from github. Execute commands step by step, and read the man pages of wg(8) and interfaces(5) if you want to know more.

WireGuard setup

  • WireGuard uses Public Key Authentication, similarly to SSH, which means:

  • client and server have both a public and a private key
  • the client needs to know the VPN server public key before connecting (akin to the SSH server key fingerprint saved in ~/.ssh/known_hosts)

  • the server authenticates the VPN client using the client public key (akin to the SSH client key saved in ~/.ssh/authorized_keys)

Installation on server

  • if using Debian 10 (buster) enable the backports repository, otherwise go to the next step

#  echo 'deb http://deb.debian.org/debian buster-backports main' >> /etc/apt/sources.list
  • make sure you're using the latest kernel for this Debian release

# apt install linux-image-amd64
  • install WireGuard

# apt update
# apt install wireguard
  • verify the wireguard kernel module is properly installed. This should display the module details, like filename, description, author

$ /sbin/modinfo wireguard

Configuration on server

  • create the server keypair:

# mkdir /etc/wireguard/
# chmod 700 /etc/wireguard/
# cd /etc/wireguard/
# wg genkey | tee vpn-server-private.key | wg pubkey > vpn-server-public.key
  • print the private key, we’ll need it at the next step

# cat vpn-server-private.key
  • create the WireGuard service config file at /etc/wireguard/wg0.conf

# cat > /etc/wireguard/server.conf << EOF
# define the  !WireGuard service
# contents of file vpn-server-private.key
PrivateKey = ...
# UDP service port
ListenPort = 55820
  • get the name of the outgoing network interface of your server (ens5 in this example)

$ ip route ls default
default via dev ens5 proto dhcp src metric 1024
  • create a WireGuard network interface configuration, replacing ens5 with the value you got from the above command

# cat > /etc/network/interfaces.d/wg0 << EOF
# activate on boot
auto wg0
# interface configuration
iface wg0 inet static
    pre-up ip link add wg0 type wireguard
    pre-up wg setconf wg0 /etc/wireguard/server.conf
    # route packages when the VPN interface is up
    post-up sysctl --write net.ipv4.ip_forward=1

    # and stop routing when stopping the VPN interface
    post-down sysctl --write net.ipv4.ip_forward=0
    post-down ip link del wg0

iface wg0 inet6 static
    address fc00:23:5::1/64
    # route packages when the VPN interface is up
    post-up sysctl --write net.ipv6.conf.all.forwarding=1
    # and stop routing when stopping the VPN interface
    post-down sysctl --write net.ipv6.conf.all.forwarding=0

  • activate the new network configuration

# ifup wg0
  • inspect the wireguard device created

# wg show wg0
interface: wg0
  public key: 2efuG9OYmMPQpbkJ8CVxGlvQflY6p1u+o4wjcgGII0A=
  private key: (hidden)
  listening port: 55820

WireGuard client setup

  • install WireGuard like you did for the server

  • create the client keypair:

# mkdir /etc/wireguard/
# chmod 700 /etc/wireguard/
# cd /etc/wireguard/
# wg genkey | tee vpn-client-private.key | wg pubkey > vpn-client-public.key
  • create an initial configuration file for wg-quick, a wrapup around the wg command

cat > /etc/wireguard/wg0.conf << EOF
# Put here the content of vpn-client-private.key
PrivateKey = ...
Address =, fc00:23:5::2/64

# Put here the content of vpn-server-public.key created on the server
PublicKey = ...
Endpoint = wg.example.com:55820
  • add the following at the end of /etc/wireguard/server.conf on your server, so that your client is allowed to connect:

cat >> /etc/wireguard/server.conf << EOF
# Put here the content of vpn-client-public.key
PublicKey = ...
AllowedIPs =
  • finally start a connection from the client:

# wg-quick up wg0
  • verify that you can ping the VPN endpoint:

$ ping -c 5

Routing configuration

Now that we have the VPN working, we want to configure client and server, so that all client traffic is sent to the server by default, and the server masquerades the IP address of the client outgoing packets with its own address.

Server part

  • define Network Address Translation for nftables. This will allow packages coming from the VPN client to go to the Internet with the IP of the VPN server. Replace ens5 with the name of the network device you got in the previous chapter.

cat >> /etc/nftables.conf << EOF

add table wireguard-nat

table ip wireguard-nat {
        chain prerouting {
                type nat hook prerouting priority -100; policy accept;

        chain postrouting {
                type nat hook postrouting priority 100; policy accept;
                oifname "ens5" masquerade
  • make sure nftables configuration is active

systemctl enable --now nftables
  • verify that wireguard-nat table and its ruleset is loaded

# nft list tables
# nft list ruleset

Client part

  • Forward all client traffic to the VPN

# cat >> /etc/wireguard/wg0.conf << EOF
AllowedIPs =, ::/0
  • restart the vpn client

# wg-quick down wg0
# wg-quick up wg0
  • display the IP address of an outgoing connection. You should see here the IP address of your server

$ curl ipinfo.io

GUI to start / stop wireguard on the client side

If using a Debian Desktop for your VPN client, you will have NetworkManager installed to manage your wireless connections. NetworkManager can also start / stop the WireGuard tunnel. For this you just need to export your wg-quick configuration wg0.conf into a new NetworkManager profile. See https://blogs.gnome.org/thaller/2019/03/15/wireguard-in-networkmanager/ for details