Raspberry Pi Smart VPN Server Installation and Configuration

Carder

Professional
Messages
2,619
Reputation
9
Reaction score
1,719
Points
113
I believe that you have the latest version of OS Raspbian installed, all the default packages have the latest versions and SSH access is configured, we are proceeding to install additional software to build a VPN server.

Installing UPnP Client

Universal Plug-n-Play (UPnP) is a protocol for opening ports on your internet router so that applications can communicate with each other over the internet. We need this so that Putty can communicate with your RPi after installing it in a remote location, and so that the OpenVPN client on your Windows and / or Android devices can use it.

The RPi VPN server we create is virtually maintenance free. But from time to time you will want to check it and update the software. SSH with Putty allows us to do all this, and the UPnP software ensures that we can access our RPi from anywhere in the world.

MiniUPnP

MiniUPnP is the easiest to install and fastest to use. So we're going to install it initially. If you have problems with how MiniUPnP will work with your router, you can refer to the next part of this article to install PortMapper, an alternative UPnP software package.

We execute the commands for installing MiniUPnP and its Python module:

Code:
apt install miniupnpc
apt install python-pip
pip install miniupnpc

Answer "Y" to any request for additional disk space, etc. The first command installs the upnpc program from the command line for testing. The second command installs the Python Package Installer (PIP), which is used in the third command to install the layer used by the Python miniupnpc package in our script. Now let's test it. Enter the following:

Code:
upnpc -s

Among all the junk you spit out should be a line starting with:
  • Found valid IGD
g1O0Y2GPFEk.jpg

However, if you don't see it or instead find error messages such as “No IGD UPnP Device found on the network!"

Then MiniUPnP will not be able to connect to your router. This could be because your router does not have UPnP enabled or MiniUPnP is not compatible with your router. Check your router's user manual to make sure it supports UPnP and how to enable it.

If MiniUPnP doesn't work with your router and supports UPnP, skip to the next section, PortMapper (MiniUPnP alternative) to use it. If not, we're done with this part.

PortMapper (alternative to MiniUPnP)

You are here because MiniUPnP cannot communicate with your router even though it supports UPnP and is enabled. Fear not, we have an alternative.

PortMapper is a Java application so it takes more work to install. It also runs a little slower, but that shouldn't be a problem for us.

If you haven't logged into your RPi with puTTY yet, do so now, install the root user and navigate to the "root" folder:

Code:
sudo -s
cd / root

Now run the wget command to download the PortMapper:

Code:
wget -O PortMapper.jar https://downloads.sourceforge.net/project/upnp-portmapper/PortMapper-1.9.5.jar

Or download the script from here:
The wget 'web-gets' command PortMapper-1.9.5.jar renames it just PortMapper.jar (much easier to work with).
  • Note: I have tested this ONLY with version 1.9.5 of PortMapper. There may be newer versions of this program (and some are alpha (untested) versions). Using any other version may not work and is not supported.
PortMapper requires the Java Runtime Enviroment (JRE), and depending on which version of Raspbian you downloaded, it may not be installed. So, we'll run the install command for the JRE to make sure we have it:

Code:
apt-get install default-jre-headless

If it's already there, you'll see a message stating that it's up to date. If not, you will be prompted to install it along with your space requirements. Just answer "Y"

We are doing a "headless" installation because we only talk to the RPi over SSH and not through the graphical user interface (GUI), so we don't need all of these additional components. However, it is a bit large and takes time to install.

Now let's test it and make sure it can communicate with your router. Enter this single line:

Code:
java -jar PortMapper.jar -s | grep 'Router Info:'

This will output about a dozen lines (if everything works correctly). They should contain information such as your router name, manufacturer, model, etc. If you do not see this information, or instead see error messages, then PortMapper is not compatible with your router.

I hope you succeeded, but you can ask questions in the comments.

Installing and configuring OpenVPN

For Wireless:

OpenVPN on Jessie doesn't work well with WiFi adapters. Terminates the Wi-Fi connection on startup. So, if you are using your RPi wirelessly, we need to edit the file first:

Code:
nano / etc / default / ifplugd

Edit the HOTPLUG_INTERFACES line so it looks like this:

Code:
HOTPLUG_INTERFACES = "eth0 wlan0"

Press Ctrl + X and Y to save and exit.
  • Note: The above ifplugd file does not apply to Raspberry Pi 3 models or Raspbian Stretch or Buster version.
Since we prefer an Ethernet connection, just move on. So now we run the following command on your Raspberry Pi:

Code:
apt install openvpn

Aha, now you have a working VPN server! But ... The problem is that no one can talk to him or even knows how to talk to him. So we have a little more work to do. We need to generate some keys, both public and private, that will be used to connect to our RPi VPN server. We will be using the RSA (Rivest-Shamir-Adleman) Cryptosystem. It's already built into OpenVPN, so all we have to do is tell OpenVPN to use it. We execute the following command:

Code:
cp -r / usr / share / easy-rsa / etc / openvpn / easy-rsa

This copies the RSA software from the "examples" directory to the "etc" directory so that we can make changes without messing up the original. Now we'll just "change directory" to our working copy so we can work with it:

Code:
cd / etc / openvpn / easy-rsa

And let's make a working copy of the vars.example file:

Code:
cp vars.example vars

At this point it is not necessary to change any of the parameters in the vars file, the defaults work well for this setting. Now it's time to generate a CA (Certificate Authority) certificate and a root CA certificate. This is the first step in creating a key pair (server and client) to use our VPN server. So do the following: Initialize the Public Key Infrastructure (PKI).

Public Key Infrastructure

(PKI - Public Key Infrastructure) - a set of tools (technical, material, human, etc.), distributed services and components, collectively used to support crypto-tasks based on private and public keys. PKI is based on the use of a public key cryptographic system and several basic principles:
  • The private key is known only to its owner;
  • The certification authority creates an electronic document - a public key certificate, thus certifying the fact that the private (secret) key is known exclusively to the owner of this certificate, the public key is freely transferred in the certificate;
  • Nobody trusts each other, but everyone trusts the certification authority;
  • The certification authority confirms or denies that the public key belongs to a given person who owns the corresponding private key.
This creates the structure for our main certificate of authority (CA) and public / private key pairs (in fact, these keys are not only generated for structures):

Code:
./easyrsa init-pki

Create our CA, enter:

Code:
./easyrsa build-ca nopass

You can choose not to use the "nopass" option and you will be prompted for a passphrase. You will need it every time you connect to the OpenVPN server. But if you don't publicly disclose your CA, there is no need to password protect it with a passphrase. You will now be prompted to enter "Common name". I recommend using the Raspberry Pi hostname if you provide one, or a unique name for this server. If you create multiple Raspberry Pi VPN servers, it will be easier to tell them apart.
  • Note: remember this common name you entered! You will need this later.
Now it's time to create a root CA certificate, so enter the following # at the command prompt:

Code:
./easyrsa gen-req servername nopass

Servername is exactly what you entered in the "Common Name" field. You haven't forgotten it already, have you? You will also be prompted for "Common Name" again, but by default it should match the server name you entered, so just press Enter. Now we need to sign this server certificate so that we can use it:

Code:
./easyrsa sign-req server servername

FZh7yDumsc4.jpg

Where "servername" is, again, the server name you chose above. Then just answer "yes" to the prompt.

The next step is to create a Diffie-Hellman key exchange. This allows two computers to exchange private keys without knowing who they are. Enter (this may take a while for example hours if you are using a 2048 bit key size - highly recommended):

  • The Diffie-Hellman ( DH ) protocol is a cryptographic protocol that allows two or more parties to obtain a shared secret key using an unsecured communication channel. The resulting key is used to encrypt further exchange using symmetric encryption algorithms.
  • The public key distribution scheme proposed by Diffie and Hellman made a real revolution in the world of encryption, as it removed the main problem of classical cryptography - the problem of key distribution.
  • In its pure form, the Diffie - Hellman algorithm is vulnerable to data modification in the communication channel, including the Man-in-the-middle attack, therefore schemes using it use additional methods of one-way or two-way authentication.
Code:
./easyrsa gen-dh

KJMWg7GuKkU.jpg

Make a coffee (or watch a movie if you used a 2048-bit key size) and come back here when it's ready. Sometimes, if you're really lucky, it can happen quickly if he finds a suitable pair of random simple keys early.

It took me about 40 minutes and the output will be the following:

To8yAx1waiI.jpg


We now need to take additional security measures to prevent Denial of Service (DoS) attacks. We need to create a hash based message authentication code (HMAC).

If the OpenVPN server sees a VPN request without this code, it won't even respond, which will prevent DoS attacks.

Just enter:

Code:
openvpn --genkey --secret pki / ta.key

OnDmZxQFssk.jpg


Next, we need to create a server config file that tells OpenVPN how to run this RPi.

Code:
nano /etc/openvpn/server/server.conf

Then copy the following into nano:

Code:
# local 111.111.111.111
dev tun
proto udp
port 1194
ca /etc/openvpn/easy-rsa/pki/ca.crt
cert /etc/openvpn/easy-rsa/pki/issued/SERVERNAME.crt # TBD - Change SERVERNAME to your Server name
key /etc/openvpn/easy-rsa/pki/private/SERVERNAME.key # TBD - Change SERVERNAME to your Server name
dh /etc/openvpn/easy-rsa/pki/dh.pem
server 10.8.0.0 255.255.255.0
ifconfig 10.8.0.1 10.8.0.2
push "route 10.8.0.1 255.255.255.255"
push "route 10.8.0.0 255.255.255.0"
push "route 111.111.111.111 255.255.255.0"
push "dhcp-option DNS 222.222.222.222"
push "redirect-gateway def1"
client-to-client
duplicate-cn
keepalive 10 120
tls-auth /etc/openvpn/easy-rsa/pki/ta.key 0
compress lzo
persist-key
persist-tun
user nobody
group nogroup
cipher AES-128-CBC
log /var/log/openvpn.log
status /var/log/openvpn-status.log 20
verb 1

You need to change two lines. They are all marked with "# TBD". Set your OpenVPN server name instead of SERVERNAME (it's CaSe Sensitive!). Press Ctrl + X and Y to save and exit.
  • Note: Don't worry about the fancy 111.111.111.111 and 222.222.222.222 IP addresses, a little script in the next chapter will set it all up.
Almost done. The next part is setting up the server configuration file that allows OpenVPN to send / receive data (packet forwarding). By default, Raspbian OS blocks all of this.

Code:
nano /etc/sysctl.conf

Let's uncomment the following line:
  • net.ipv4.ip_forward = 1

Sr7964XyatY.jpg

Press Ctrl + X and Y to save and exit. Then enter this to apply this change:

Code:
sysctl -p

Then we need to open up the Raspbian firewall a bit to allow OpenVPN to communicate with the outside world. To do this, we need to create a new file.

Code:
nano /root/open_vpn_firewall.sh

Insert the following lines:

Code:
#! / bin / sh
sleep 30
Adapter = `ip -o link show | awk '{print $ 2, $ 9}' | grep 'UP' | awk -F: '{print $ 1}' '
if [-z "$ Adapter"]
then
    Adapter = 'eth0'
fi
echo "Adapter = | $ Adapter |"
/ sbin / iptables -t nat -A POSTROUTING -o $ Adapter -j MASQUERADE
/ sbin / iptables -A FORWARD -i $ Adapter -o tun0 -m state --state RELATED, ESTABLISHED -j ACCEPT
/ sbin / iptables -A FORWARD -i tun0 -o $ Adapter -j ACCEPT

p7LNIolGpJM.jpg

We just created a Bash script and we need to make it executable and configure it to run every time our RPi boots.

So, enter these 2 commands to make it executable and make it the owner "root":

Code:
chmod 700 /root/open_vpn_firewall.sh
chown root /root/open_vpn_firewall.sh

On this we will finish for now, to be continued.
 
Top