Installing WireGuard on Amazon Lightsail

Published: October 11, 2018  •  linux

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 will 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

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:
https://aws.amazon.com/lightsail/pricing/

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.


Setup VPS

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. region

Next select the operating system. We don't need any pre installed applications, just a pure 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/ os

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"
changesshkey

then "Upload New"
uploadnew

select the public key file (lightsail.pub) and upload the key.
upload

And finally choose the instance plan. The cheapest server is powerful enough for just running Wireguard. upload

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. staticip

Attach your instance to this static IP address and click "Create" createstaticip

The website should now show you the static IP address for your server. createstaticip

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". firwall

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 will use the port 54321. firwall

This concludes the configuration of our virtual server. You can close the website and we will continue on the command line.


Install required packages

Connect to the server with SSH.

ssh -i lightsail admin@54.147.249.172

-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 bash
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: 150\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:

net.ipv4.ip_forward=1

And finally we do some clean-up and remove unused packages

apt-get autoremove

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 wg0.conf

nano wg0.conf

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

For the 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 server_private_key and 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

cat wg0.conf

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 will answer all DNS queries from the VPN clients.

I use the configuration described in this Wireguard article:
https://www.ckn.io/blog/2017/11/14/wireguard-vpn-typical-setup/

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 will automatically start 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 iptables-persistent package.

I copied the rules from this Wireguard article:
https://www.ckn.io/blog/2017/11/14/wireguard-vpn-typical-setup/

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 will start each time we boot our server and automatically load the saved iptables rules.

systemctl enable netfilter-persistent

Reboot

After setting everything up we reboot the server

reboot

This will also close your SSH connection. Reconnect

ssh -i lightsail admin@54.147.249.172

and check if unbound is running and the iptable rules are loaded

sudo bash
systemctl status unbound
iptables -L

Now we start the Wireguard wg0 network interface and enable it so Linux will automatically create the interface each time we boot the server.

wg-quick up wg0
systemctl enable wg-quick@wg0.service 

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)

Client setup

If you want to connect from an Android phone to a Wireguard server you need to install the Wireguard app from the play store:
https://play.google.com/store/apps/details?id=com.wireguard.android&hl=en

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 will 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 = 54.147.249.172: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 client_private_key and 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

qrcode

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. app

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.


Additional clients

If you want to connect more Android clients you repeat the client configuration.


Links

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.