DevOpsTutorials

Securing small IT setup with VPN

Whether you are a webdeveloper or a mobile developer in a small company, at some point you will probably need to interact with a test webservice of some sort. It can be a simple test version of a website that you work on, or a REST API for your mobile application. Anyway, test services should not be easily accessible from the Internet. They usually have some debug options enabled and can expose your productive environment for attacks.

This problem can be easily solved with setting up an VPN server in front your application server, which will be used to control access to applications. Below chart shows a simplified architecture of such a setup.

VPN Setup

Access to Secure Application Server (which hosts test applications and other services that should be secured) allows access only from a VPN Server. So everyone else, who will try to connect to our Secure Application Server from the internet will be rejected. Only users who will be connected to the VPN Server will be able to connect to Secure Application Server.

Choosing VPN server

Unless you are an experienced IT Administrator, setting up a VPN Server may seem like a difficult task. First you have to select your VPN Server type. You can choose between many paid and free solutions like OpenVPN and IPSec/L2TP (both of theme are free). My choice was to go with IPSec as it’s much easier to setup clients which will connect to our server – many operating systems support IPSec out of the box (iOS, macOS – just to name a few). With OpenVPN you have to install additional client on your device.

I will setup a VPN server on Virtual Private Server in the cloud running Ubuntu 16.04 LTS.

IPSec/L2TP installation

Many tutorials describe installation processes in details and they usually include dozens or even hundreds of commands that you type or blindly copy-paste into a console. However, we can speed up this process! Thanks to great open source community we can use a script that will do this process for us! If you are interested in the script source code and detailed docs, you can find it on GitHub.

First, we will need a root access on our server so login as a root or some other user which can do sudo. Then, we need to download the script that will help us with the installation.

wget https://git.io/vpnsetup -O vpnsetup.sh

We could now run the script and have everything auto-generated for us, including username, password and shared secret which will be used by clients to establish connection. However, if we would like to specify this values ourselves than we have to edit the script and provide our own values.

nano -w vpnsetup.sh

In an opened file, look for the following lines. They should be somewhere close to the beginning.

# Define your own values for these variables
# - IPsec pre-shared key, VPN username and password
# - All values MUST be placed inside 'single quotes'
# - DO NOT use these special characters within values: \ " '

YOUR_IPSEC_PSK=''
YOUR_USERNAME=''
YOUR_PASSWORD=''

We can now enter our own values. Remember to use strong password and shared_secret (IPSEC_PSK).

When we are ready we close the editor with CRTL + X followed by Y and then run the script.

sudo sh vpnsetup.sh

Depending on your connection and machine speed, installation can take up to a few minutes. When it’s ready you will be presented with values required to connect.

IPsec VPN server is now ready for use!

Connect to your new VPN with these details:

Server IP: IP_ADDRESS
IPsec PSK: ExampleOfIpSecPSKDontTryIt
Username: vpnuser
Password: SomeStupidPasswordDontTryIt

Write them down.

Our VPN server is ready for connections so let’s test it. 😎

Setting up VPN client on macOS

In this blog post I will only show how to setup VPN Client connection on macOS. If you are running Windows or some Linux distribution, please refer to this guide. It also covers VPN Client setup on mobile platforms like iOS and Android.

  1. Open System Preferences and go to the Network section.
  2. Click the + button in the lower-left corner of the window.
  3. Select VPN from the Interface drop-down menu.
  4. Select L2TP over IPSec from the VPN Type drop-down menu.
  5. Enter Service Name which will server as you VPN name.
  6. Click Create.
  7. Enter Your VPN Server IP or VPN Server DNS address for the Server Address.
  8. Enter Your VPN Username for the Account Name.
  9. Click the Authentication Settings button.
  10. In the User Authentication section, select the Password radio button and enter Your VPN Password.
  11. In the Machine Authentication section, select the Shared Secret radio button and enter Your VPN IPsec PSK.
  12. Click OK.
  13. Check the Show VPN status in menu bar checkbox.
  14. (Important) Click the Advanced button and make sure the Send all traffic over VPN connection checkbox is checked.
  15. Click the TCP/IP tab, and make sure Link-local only is selected in the Configure IPv6 section.
  16. Click OK to close the Advanced settings, and then click Apply to save the VPN connection information.

To connect to the VPN: Use the menu bar icon, or go to the Network section of System Preferences, select the VPN and choose Connect. You can verify that your traffic is being routed properly by looking up your IP address on Google. It should say “Your public IP address is Your VPN Server IP”.

Securing websites with Nginx

This section assumes that you have at least a slight understanding of how Nginx works and how to add sites definitions in it. A quick reminder for those who don’t remember – in Nginx websites definitions are stored in files in directory /etc/nginx/sites-available/. To enable a website you have add a symlink in /etc/nginx/sites-enabled/ which points to a file located in /etc/nginx/sites-available/.

Detailed explanations of what options are available in Nginx configuration is out of a scope of this article. Let’s take a look at simple example of a site definition:

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        # SSL configuration
        
        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html 

        server_name behind-vpn.com;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }
}

This definition tells Nginx to listen on port 80 and serve all HTTP requests to domain behind-vpn.com with index.html from /var/www/html. In a typical production setup this configuration would be much more verbose but I will keep it simple for this article.

To limit access to our website behind-vpn.com we have to add two lines to above configuration. First, we want to allow traffic from our VPN server. This can be done with:

allow $IP_ADDRESS;

where $IP_ADDRESS should be replace with the IP address of the VPN Server – the same that we used in a client to connect.
Secondly we want to block all other incoming traffic like this:

deny all;

So our final configuration will look similar to:

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        # SSL configuration
        
        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html 

        server_name behind-vpn.com;

        allow $IP_ADDRESS;
        deny all;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }
}

And that’s it. Now, anyone who is not connected to our VPN Server and will try to access behind-vpn.com will see a 403 Forbidden page.

To learn more about limiting access to other services with VPN wait for second part of this blog post.