WireGuard is a new VPN that got a bit of a buzz lately. It claims to be faster, simpler and leaner than it's competitor IPSec and OpenVPN. You can read all about it on the official homepage: https://www.wireguard.com/
Before we start you should note that WireGuard is, at the time of writing (October 2018), a work in progress. If you want to use WireGuard for serious applications you should at least wait for the 1.0 release. If you are really concerned about security, you should even wait until an independent third party audited the software.
Despite all this the software is in a functioning state and we can install and experiment with it.
In the following sections we're going to install Wireguard on an Amazon Lightsail virtual server and install the Wireguard Android app on a smartphone. This is one use case of a VPN, to hide network traffic from an ISP. This is especially useful for mobile devices when you are connecting to public internet access points, such as hotels. All they see is a connection to the VPN server but nothing else.
Another use case of a VPN, especially for companies, is connecting local networks of remote offices to the main company network. A VPN allows them to securely connect these two local networks over the public Internet. A company can also use a VPN for employees that work at home to allow them to securely connect to the internal network.
Wireguard can be used for all these use cases. Currently Wireguard only runs on Linux, FreeBDS, OpenBSD, macOS and Android. A Windows client should come soon according to the web site.
Lightsail is Amazon's answer to all the cheap VPS providers. It provides virtual server that run on Amazon EC2. You don't have to be familiar with EC2, Amazon makes it very simple to set up a virtual server with a web interface.
Prices start at USD 3.50 and go up to $240 per month depending on the CPU, RAM, SSD, network data transfer and operating system. Visit the pricing page to learn more:
Lightsail supports Linux and Windows based virtual servers. Windows servers cost a bit more because of the additional license they have to pay Microsoft.
For this setup we create a Linux VPS and choose the cheapest server for $3.50. The first month is free so it's a great way to test these servers.
If you want to follow this tutorial you need an Amazon account. To sign up you can go to https://aws.amazon.com/ and click on the "Sign Up" button.
Go to https://lightsail.aws.amazon.com and sign in with your Amazon account. Click on Create instance.
First you need to select the Region and Availability Zone where Amazon should create your new virtual server.
Next select the operating system. We don't need any pre installed applications, just a plain operating system. I chose Debian 8, which is one of the operating system that Wireguard supports. Check the Wireguard install page for more information: https://www.wireguard.com/install/
Next we create a public/private key for connecting to the server with SSH. On your local computer run this command:
ssh-keygen -N "mysupersecretpassphrase" -t rsa -b 4096 -C "mydesktopcomputer" -f lightsail
The passphrase (string after
-N) protects your private key. Replace it with something else! This command creates two files in the current directory, a public key (lightsail.pub) and a private key (lightsail).
On the server creation page click on "Change SSH key pair"
then "Upload New"
select the public key file (lightsail.pub) and upload the key.
And finally choose the instance plan. The cheapest server is powerful enough for just running Wireguard.
Click "Create" and wait about a minute, while Amazon is preparing and starting your virtual server. By default, Lightsail virtual servers get a new IP address each time you reboot them. But what we want is a static IP address that never changes. A static IP address for your server is included in the monthly fee.
After your VPS is running click on the "Networking" tab and create a static IP address.
Attach your instance to this static IP address and click "Create"
The website should now show you the static IP address for your server.
Click on the name of your instance. In my case "Debian-512MB-Virgina-1". This opens the configuration page for a specific instance.
Here we need to add a new firewall rule. Click on "Networking and "Edit rules".
Delete the HTTP TCP 80 rule, we don't run a web server on this server and add a new UDP rule. You can choose any free port you want. Usually I pick a port between 32768 - 65535. For this blog post I'm going to use the port 54321.
This concludes the configuration of our virtual server. You can close the website and we're going to continue on the command line.
Install required packages
Connect to the server with SSH.
ssh -i lightsail firstname.lastname@example.org
-i specifies the path to the private key file. SSH asks you for the private key passphrase and when everything is correct connects you to your new virtual server.
First we make sure that all installed packages are up to date.
sudo -i apt update apt dist-upgrade
Next we install all the required packages for this tutorial: Wireguard, unbound (DNS server), iptables-persistent and qrencode.
As mentioned at the beginning, Wireguard is a work in progress and there is no 1.0 release yet, so there is no Wireguard package in the release repository, but you can install it from the Debian unstable repository.
echo "deb http://deb.debian.org/debian/ unstable main" > /etc/apt/sources.list.d/unstable.list printf 'Package: *\nPin: release a=unstable\nPin-Priority: 90\n' > /etc/apt/preferences.d/limit-unstable apt update apt install wireguard unbound iptables-persistent qrencode curl
The iptables-persistent installation asks you about saving the current iptables rules, select no.
Next we need to enable IP Forwarding. Open
/etc/sysctl.conf and look for the line
#net.ipv4.ip_forward uncomment this line by removing the
# at the beginning. It should look like this:
And finally we do some clean-up and remove unused packages
Set up Wireguard
Wireguard is using public/private key cryptography. For that we need to create a public/private key pair for each participant of the VPN. In this setup we have the server and one Android phone, so we create two key pairs.
cd /etc/wireguard/ umask 077 wg genkey | tee server_private.key | wg pubkey > server_public.key wg genkey | tee client_private.key | wg pubkey > client_public.key
Create the file
and insert the following text
[Interface] Address = 192.168.2.1 PrivateKey = server_private_key ListenPort = 54321 [Peer] PublicKey = client_public_key AllowedIPs = 192.168.2.2/32
ListenPort you need to use the same port number that you specified in the UDP firewall rule on the Lightsail configuration page. This is the port where Wireguard is listening for incoming VPN connections.
Save the file and close Nano. Next we replace the string
client_public_key with the content of the files.
sed -i "s/server_private_key/$(sed 's:/:\\/:g' server_private.key)/" wg0.conf sed -i "s/client_public_key/$(sed 's:/:\\/:g' client_public.key)/" wg0.conf
Check the wg0.conf file
It should look similar to this.
[Interface] Address = 192.168.2.1 PrivateKey = cMgbJqIl6CuU6U6gpXu4TwUlJ+TnAgaSa6Dc8b5g1F8= ListenPort = 54321 [Peer] PublicKey = GXehejiGNxfOk5bEKECYgQg0nM9cu80BxPJap47s3QE= AllowedIPs = 192.168.2.2/32
Set up DNS server
Next we configure the DNS server
unbound. This server is going to answer all DNS queries from the VPN clients.
I use the configuration described in this Wireguard article:
curl -o /var/lib/unbound/root.hints https://www.internic.net/domain/named.cache chown -R unbound:unbound /var/lib/unbound cd /etc/unbound/unbound.conf.d nano unbound_srv.conf
Insert the following text into the editor
server: num-threads: 4 verbosity: 1 root-hints: "/var/lib/unbound/root.hints" interface: 0.0.0.0 max-udp-size: 3072 access-control: 0.0.0.0/0 refuse access-control: 127.0.0.1 allow access-control: 192.168.2.0/24 allow private-address: 192.168.2.0/24 hide-identity: yes hide-version: yes harden-glue: yes harden-dnssec-stripped: yes harden-referral-path: yes unwanted-reply-threshold: 10000000 val-log-level: 1 cache-min-ttl: 1800 cache-max-ttl: 14400 prefetch: yes prefetch-key: yes
Save the file and exit Nano, restart the process and enable it so it automatically starts each time you boot the server.
systemctl restart unbound systemctl enable unbound
Check if the service is running. You should see a green
active (running) text.
systemctl status unbound
Set up Firewall
We add the following iptables rules and make them persistent with
netfilter-persistent, which is a command from the
I copied the rules from this Wireguard article:
Run the following commands in the shell. Make sure that you change the port (54321) if you use a different number.
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT iptables -A INPUT -p udp -m udp --dport 54321 -m conntrack --ctstate NEW -j ACCEPT iptables -A INPUT -s 192.168.2.0/24 -p tcp -m tcp --dport 53 -m conntrack --ctstate NEW -j ACCEPT iptables -A INPUT -s 192.168.2.0/24 -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT iptables -A FORWARD -i wg0 -o wg0 -m conntrack --ctstate NEW -j ACCEPT iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o eth0 -j MASQUERADE netfilter-persistent save
We also need to enable
netfilter-persistent so it starts each time we boot our server and automatically loads the saved iptables rules.
systemctl enable netfilter-persistent
After setting everything up we reboot the server
This also closes your SSH connection. Reconnect
ssh -i lightsail email@example.com
and check if
unbound is running and the iptable rules are loaded
sudo -i systemctl status unbound iptables -L
Now we start the Wireguard
wg0 network interface and enable it so Linux automatically creates the interface each time we boot the server.
wg-quick up wg0 systemctl enable firstname.lastname@example.org
When you enter
ifconfig you should see the Wireguard interface
wg0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 inet addr:192.168.2.1 P-t-P:192.168.2.1 Mask:255.255.255.255 UP POINTOPOINT RUNNING NOARP MTU:8921 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
If you want to connect from an Android phone to a Wireguard server you need to install the Wireguard app from the play store:
Next we need to create a new configuration in the app. We can do this either from scratch by entering all the information manually or by importing a file. In this tutorial we're going to use the third option and create the configuration file on the server, display a QR code and then scan the QR code with the app.
First we create the configuration file. I call it
client2 in this example.
cd /etc/wireguard/ nano client2
Paste the following text into the editor.
[Interface] Address = 192.168.2.2/32 PrivateKey = client_private_key DNS = 192.168.2.1 [Peer] PublicKey = server_public_key Endpoint = 220.127.116.11:54321 AllowedIPs = 0.0.0.0/0
Make sure that the
Endpoint points to the static IP address of your virtual server. Port must be the same as
ListenPort in the
wg0.conf file. If you have multiple clients you need to make sure that
Address is free and not already assigned to another client.
Next we replace the strings
server_public_key with the real keys.
sed -i "s/client_private_key/$(sed 's:/:\\/:g' client_private.key)/" client2 sed -i "s/server_public_key/$(sed 's:/:\\/:g' server_public.key)/" client2
Run the following command to display the QR code of the
client2 file conent.
qrencode -t ansiutf8 < client2
Open the Wireguard app on your Android phone, click on the + button, select "Create from QR code" and then point the camera to the QR code on your screen. If the app was able to successfully scan the code it asks for a tunnel name. Enter a name and tap on "Create tunnel".
Enable the tunnel with the slider. You should see a key icon at the top of your screen.
To check if the VPN works open a browser and go the URL: https://www.whatismyip.com/
Or enter the search term "my ip" into the Google search.
If the connection is routed through the VPN it should show the IP address of the virtual server as the public address.
To check if DNS requests are routed through the VPN go to https://www.dnsleaktest.com and run the extended test. The test runs for a few seconds and displays a list of servers that answered the DNS queries. Make sure that this list only contains your Lightsail server.
If you want to connect more Android clients you repeat the client configuration.
- Create public / private key pair
- Create a client configuration file. Make sure
Addressis not already assigned.
- Add a new
[Peer]section to wg0.conf
- Restart wg0 interface.
wg-quick down wg0 && wg-quick up wg0
- Display the QR code and scan it with the app.
In this blog post I showed how to connect an Android device to the Wireguard server. If you want to connect a linux or macOS computers to the VPN you find a lot of tutorials on the WWW. Here a few links:
The following link points to an interesting article about
unbound. Especially the part about ad blocking could be useful for this set up when we connect with mobile devices to the VPN. If you are on a limited data plan this could save some bandwidth.