Wireguard as a VPN solution for Home connection

Oren Oichman
7 min readSep 29, 2021

--

Why this story

Wireguard has been the main talk in the VPN community for the past year and lately I wanted to give it a try. As it turns out it really is as simple as it seems.

Setup ?

For this setup we will need a server in our home internal network that will run the wireguard server and a workstation which will connect to it from any where in the world (I will setup the GUI for example in this quick tutorial).

Configuration

We will start the configuration regarding both sides. Once those steps are completed we will move on to the server side and lastly we will configure the client side.

For both Sides

Install wireguard on both machines (I am using Centos as a server and fedora as a workstation in my example)

# dnf install -y wireguard-tools
(yum install -y wireguard-tools)

Next let’s create a public and private key which will be used for the VPN authentication.

Change our working directory to wireguard and setup the umask for 022:

# cd /etc/wireguard# umask 022

and now run the command to generate the two keys :

# wg genkey | tee privatekey | wg pubkey > publickey

The command will take a few seconds and at the end we will have 2 files available :

# ls -la
-rw-------. 1 root root 45 Sep 19 08:52 privatekey
-rw-------. 1 root root 45 Sep 19 08:52 publickey

Server Side

Now we need to generate a configuration file for the NetworkManager and then import it to the networkManager service.

# cat > wg0.conf << EOF
[Interface]
Address = 172.16.4.1/24
SaveConfig = true
ListenPort = 50001
PrivateKey = $(cat privatekey)
[Peer]
PublicKey = <Client Public Key>
AllowedIPs = 172.16.4.0/24
2EOF

As you can see , we setup the VPN network segment with the range of 172.16.4.0/24 and we gave our server the first IP.

Next we are setting the saveConfig option — if set to `true’, the configuration is saved from the current state of the interface upon shutdown. Any changes made to the configuration file before the interface is removed will therefore be overwritten.

The server is going to listen on port 50001.
in the final line of the file we set the private key of the server.

Next, use the nmcli command to import the configuration file and create a wg0 interface that will be managed by NetworkManager :

# nmcli con import type wireguard file /etc/wireguard/wg0.conf

Make sure NetworkManager starting up on boot and running :

# systemctl enable --now NetworkManager

Go ahead and look at our new interface :

# ip addr show dev wg0
8: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
link/none
inet 172.16.4.1/24 brd 172.16.4.255 scope global noprefixroute wg0
valid_lft forever preferred_lft forever
inet6 fe80::6379:a6c7:dac7:2732/64 scope link flags 800
valid_lft forever preferred_lft forever

We can look at the wireguard configuration with the wg command line as well:

# wg
interface: wg0
public key: Hq0JcXBjXJMHwa9TtGc0cQ6eiSa2y0ObUVGrnf/eUBc=
private key: (hidden)
listening port: 60001
peer: <Client Public Key>
allowed ips: 172.16.4.0/24

The next step is to configure our firewall correctly. We will need to add a firewall rule for our NAT requirements and a few kernel parameters.

First we will set a variable for our firewall zone :

# export FWZONE=$(firewall-cmd --get-default-zone)

open our wireguard port :

# firewall-cmd --add-port=50001/udp --permanent --zone=${FWZONE}# firewall-cmd --reload

Now we will set our NAT rule.
First let’s grep our primary IP :

# SERVERIP=$(ip route get 84.200.69.80 | awk 'NR==1 {print $(NF-2)}')(This will work in a disconnected network as well)

Now we can set the NAT and Enable ‘MASQUERADE’ on the ‘trusted’ zone firewalld.

# firewall-cmd --permanent --zone=${FWZONE} --add-masquerade# firewall-cmd --permanent --direct --passthrough ipv4 -t nat -A POSTROUTING -s 172.16.4.0/24 -o $SERVERIP -j MASQUERADE

If you need to make changes the configuration are been kept at the file “direct.xml”

# cat /etc/firewalld/direct.xml<?xml version=”1.0" encoding=”utf-8"?>
<direct>
<passthrough ipv=”ipv4">
-t nat -A POSTROUTING -s 172.16.4.0/24 -o $SERVERIP -j MASQUERADE
</passthrough>
</direct>

NOTE:

The “172.16.4.0/24 are taking from the server configuration and is the VPN network the Server will use for Client / Server communication.

Now we need to update our sysctl so our server will be able to act as a route :

# echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf# echo 'net.ipv4.conf.all.accept_redirects = 0' >> /etc/sysctl.conf# echo 'net.ipv4.conf.all.send_redirects = 0' >> /etc/sysctl.conf# sysctl -p

And reload firewall.

# firewall-cmd --reload

In case you didn’t add the client Public key in the first secion we can take the client public key and add it as a peer (we created that on our first task, if you haven’t done it already , go ahead and do it now)

# wg set wg0 peer <Public Key> allowed-ips 172.16.4.0/24

Not that we attached the public key to a specific IP which should be configured on the client side.

Client Side (GUI)

we already have a private and public key so all we need to do now is to setup our VPN connection.

Right click on your NetworkManager icon at your system try

and click on the “+” sign at the bottom of the window and then select the wireguard option from the dropdown menu :

Click on Create and add the following details :

Give the connection a name , setup the interface name (I recommend to use wg0) and copy paste your private key.

Next click on the “Add” button under the Peers section to add our VPN Server :

  • Add the Server public key (copy it from the server) to the top
  • Add your allowed IP’s to any (if your internet connection does not have a static IP address as in my case)
  • Add your server IP address or DNS (you can use services such as no-ip or duckdns.org to setup a DNS that will be updated in case your IP address is changing).

Once everything is set click on Apply. and switch to the “IPv4 Settings” TAB change the “Method” to “Manual” and add the IP address we setup as a peer on the server (in our example it is 172.16.4.3)

Note that we have added an internal DNS in my example , this could have been 8.8.8.8 and 8.8.4.4

the search domain is not mandatory but it is good practice to have an internal domain if you managing service in your internal network.

Next click on the “Routes” button at the bottom right and add your home network. we will add the following configuration so that only internal network traffic will run over the VPN (your internet communication will still go through the default gateway of your current network) .
The routes option should look as follow :

If you want all your network communication to go through the VPN connection you can skip this step.

click “OK” for everything and now try to connect , if you see a luck icon on your network manager icon then everything is working and you can access your home network.

Client Side (CLI)

In the /etc/wireguard/ directory we will create a new file called wg0.conf with the following options

[Interface] — the main section for the interface and under it we need to add several key / values :

  • Address — the IP address of our interface , this IP address needs to be part of the VPN rage we configured earlier.
  • PrivateKey — the private key for the client
  • DNS — the DNS for the VPN network

[Peer] — the Server Peer configuration.

  • PublicKey — the Public key of the wireguard Server
  • Endpoint — the IP address of the Server with the Server port.
  • AllowedIPs — the Allowed IP address range that the client can access through the VPN.

First we will export the important values :

$ export PRIVATEKEY=$(cat /etc/wireguard/privatekey)
$ export SERVER_PUBLICKEY="<From the Server>"
$ export SERVER_ENDPOINT="<From the Server>"

A good example can look as such :

$ cat > /etc/wireguard/wg0.conf << EOF
[Interface]
Address = 172.16.4.3/24
PrivateKey = ${PRIVATEKEY}
DNS = 8.8.8.8

[Peer]
PublicKey = ${SERVER_PUBLICKEY}
Endpoint = ${SERVER_ENDPOINT}
AllowedIPs = 0.0.0.0/0, ::/0
EOF

Run the following command to initiate the VPN

$ wg-quick up wg0

Now we will start with the systemctl

$ systemctl start wg-quick@wg0
( In case you want to connect on Boot )
$ systemctl enable --now wg-quick@wg0

If you have any question feel free to respond/ leave a comment.
You can find on linked-in at : https://www.linkedin.com/in/orenoichman
Or twitter at : https://twitter.com/ooichman

--

--

Oren Oichman
Oren Oichman

Written by Oren Oichman

Open Source contributer for the past 15 years

No responses yet