A Guided Walk Through of OpenVPN
Before We Start
If the idea of accessing the devices under a protected private subnet has ever appeared in your mind, then OpenVPN
maybe one of your choices. OpenVPN
is a cross-platform software that allows you to build robust, flexible, and secure virtual private networking(VPN). Despite these renowned properties, building and configuring such a software is never an easy shoot, especially when you do it for the first time. So in this guide, I will walk you step by step through the entire process and finally build a private networking that allow you to access your devices in your home or company from every corner of the world!
The whole process is boring, I have to admit in the first place, but the final system will certainly outcome those frustration during the process. So please fasten your belt and we are going to take off.
First Equip Yourself with OpenWRT
and A VPS
OpenWRT
is a Linux operating system targeting embedded devices. You can just treat it as a super-power router
that runs a Linux OS so it allows you to do almost anything that an usual Linux can do. We use it mainly to serve as the OpenVPN Client
and the router that connects all the devices under it into the Internet. As opposed to the OpenVPN Client
, there is a OpenVPN Server
running on a remote VPS(Cloud Virtual Private Servers). Any server that has a public IP can server as the OpenVPN Server
. In this tutorial, I will use the VPS server provided by aliyun
running Ubuntu 16.04
. I choose these just because I’m used to it, you can choose whatever cloud service provider with whatever Linux distribution that you are familiar with or prefer, it really doesn’t count.
Cloud Server Setup
Now let’s login to the cloud server that we have just brought for the first time(maybe via the web page or password). We must make some configurations there to make it a OpenVPN Server
.
Basic Linux Cloud Server Security Setup (Optional)
Create a Non-Privileged User (Optional)
If the defalut user that the cloud provider gives you is a non-root user, you can just skip this section and use that user happily. If not, create a non-privileged user and grants it the sudo
privilege.
# if you are root, run the 2 commands
$ adduser <username>
$ usermod -a -G sudo <username>
$ su <username>
Upload your ssh
Public Key (Optional)
ssh
is a command that allows you to take control of your remote server gracefully. I’m not trying to explain those fundamental concepts in this article. When you get confused of some term
of command
in the rest of this article, feel free to google it.
In short, just copy the contents of file ~/.ssh/id_rsa.pub
in your local machine and append it into the file ~/.ssh/authorized_keys
on your remote server, and then you can ssh
to your server from your local machine without bothering to enter the password.
Strengthen your ssh
(Optional)
Modify /etc/ssh/sshd_config
and change the two settings PasswordAuthentication
and PermitRootLogin
from yes
to no
:
PasswordAuthentication no
PermitRootLogin no
Now only you, more specifically speaking, only this computer who owns the private key corresponding to the public key you have just uploaded can have legal access to login this cloud server as the user you have created(beside your cloud provider’s website).
Run sudo service sshd restart
to enable this configuration to take place.
Install OpenVPN
Installation is just easy with apt
under ubuntu, just give the command:
sudo apt update
sudo apt install openvpn
If it prompt you for choice, just choose the default choice. You can check that the OpenVPN is installed successfully by the following command.
$ openvpn --version
OpenVPN 2.4.4 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on May 14 2019
library versions: OpenSSL 1.1.1 11 Sep 2018, LZO 2.08
Originally developed by James Yonan
Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net>
...[omitted]
Install easy-rsa
easy-rsa
is just a small tool to generate the related certificates
needed by OpenVPN
.
sudo apt -y install easy-rsa
Build CA Certificates
Make a directory called easy-rsa
under the folder /etc/openvpn
and copy all the stuffs under the folder /usr/share/easy-rsa/
to the folder that we have just created.
sudo mkdir /etc/openvpn/easy-rsa/
sudo cp -r /usr/share/easy-rsa/* /etc/openvpn/easy-rsa/
cd /etc/openvpn/easy-rsa/
CA Certificate is a file shares between the server and the client and it only needs to be generated once for one server. Before we build the CA certificate, make sure you have changed to root
by the command sudo su
. The source vars
command sets up the environment needed by the following ./build-ca
command according to the contents in the file named vars
.
sudo su
source vars
./clean-all
./build-ca
Now you are the root, which means you should be extremely careful when you type because this superuser can do anything to your server. If you saw the following warning after executing the command
source vars
, you should add another command to make a soft link to that missing file. I have a file namedopenssl-1.0.0.cnf
under my folder so I just use this command:ln -s ./openssl-1.0.0.cnf openssl.cnf
.
***********************************************
No /etc/openvpn/easy-rsa/openssl.cnf file could be found
Further invocations will fail
***********************************************
If you are not reading this part of article for the first time, you should be aware that the command ./clean-all
is DANGEROUS. What this command do is simply removing all the files under the folder keys
, which contains all the things you have generated since you installed easy-rsa
. So be sure you know what you are doing before giving this command.
If the above commands finished successfully, you will find some new files generated in the folder keys
. Copy the file ca.crt
to the folder /etc/openvpn
. We do this copy command simply because OpenVPN assumes that all the configuration files locates in the default folder /etc/openvpn
. If you are skilled enough, it is not necessary since you can specify the configuration files in your .conf
file(see section below).
cp /etc/openvpn/easy-rsa/keys/ca.crt /etc/openvpn
Build Server Certificate
Here I wrote aliyun
as the first parameter, which totally depends on your preference. You can name it whatever you think is meaningful to you.
./build-key-server aliyun
Now more new stuffs appears in the keys
folder. Copy aliyun.crt
, aliyun.key
to the folder /etc/openvpn
.
cp keys/aliyun.key keys/aliyun.crt /etc/openvpn/
Build the Diffie-Hellman file and ta.key
Diffie-Hellman file and ta.key
is used to strengthen the security of the network. There is no need to understand what they really are, so just copy and paste the following commands.
./build-dh
cp keys/dh2048.pem /etc/openvpn
openvpn --genkey --secret ta.key
cp ./ta.key /etc/openvpn
Build Client Certificates
As opposed to Server Certificates
which are files stored in the remote server forever, Client Certificates
are files generated on the remote server but used by the multiple end-users, which means they will be copy out from the server one day.
./build-key ainevsia
cp keys/ainevsia.key keys/ainevsia.crt /etc/openvpn/
Here ainevsia
should also be DIYed by you.
How To Add a New Client
To add a new client just means building another client certificate. You can just run the above command twice the achieve that purpose. Caution that the server may prompt you to run source vars
again. Do so but DO NOT RUN ./clean-all
, that will remove all the files you already generated. just run source vars && ./build-key client-name
will be safe. See the following example.
root@iZuf6dpjg5t8prvwa2ajodZ:/etc/openvpn/easy-rsa$ ./build-key openwrt
Please edit the vars script to reflect your configuration,
then source it with "source ./vars".
Next, to start with a fresh PKI configuration and to delete any
previous certificates and keys, run "./clean-all".
Finally, you can run this tool (pkitool) to build certificates/keys.
root@iZuf6dpjg5t8prvwa2ajodZ:/etc/openvpn/easy-rsa# source vars && ./build-key openwrt
NOTE: If you run ./clean-all, I will be doing a rm -rf on /etc/openvpn/easy-rsa/keys
Generating a 2048 bit RSA private key
[...]
cp keys/openwrt.crt keys/openwrt.key /home/<username>
Here we already have built two clients: openwrt
and ainevsia
. They will all be used in the following sections.
If you have kept reading till this line, then congratulations, you have finished generating all the boring but essential crypto files that serve to secure our network. Now we will move on to configure the real OpenVPN
.
Setup the Server’s OpenVPN
First of all, copy a sample config file from the official documents.
cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/
cd /etc/openvpn
gzip -d server.conf.gz
Now change the essential entries according to your requests. Personally, I changed the port from the default 1194 to my customized port and select the proto tcp
. I also uncommented the line client-to-client
because all I want to do is just make connections between clients :D.
The lines that you should change are these lines:
proto tcp
port 1194
# change to your preferred port, 59318 in the article (just for example)
ca ca.crt
cert server.crt
# change to aliyun.crt
key server.key # This file should be kept secret
# change to aliyun.key
log /var/log/openvpn/openvpn.log
# uncomment this line (personal preference)
client-to-client
;explicit-exit-notify 1
Change the server.crt
and server.key
to the file names that you use. Additionally, if your configure files are not in the same folder of this server.conf
file, write the absolute file path
instead.
Modify Client’s OpenVPN Config File
Just like the above section, we change the client configuration files following the same guide line by the way.
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn/
proto tcp
remote <IP> 59318<Port>
ca ca.crt
cert ainevsia.crt
key ainevsia.key
Server Side Configuration Finished
Modifying the config file is really the most difficult part of this process. If you finish, you can finally launch the OpenVPN
service.
cd /etc/openvpn
systemctl restart openvpn@server.service
If the above command cannot start the service, try # openvpn --config /etc/openvpn/server.conf &
.
Here is a demo of how a success launch may look like. If your port number doesn’t show up in the netstat -tunlp
command, that means the OpenVPN service does not start successfully.
root@iZuf6dpjg5t8prvwa2ajodZ:/etc/openvpn# openvpn --config /etc/openvpn/server.conf &
[1] 8560
root@iZuf6dpjg5t8prvwa2ajodZ:/etc/openvpn# netstat -tunlp | grep 59318
tcp 0 0 0.0.0.0:59318 0.0.0.0:* LISTEN 8560/openvpn
Final Working Directory
Here’s a look from my cloud server when I started the OpenVPN
service.
$ tree /etc/openvpn/ -L 1
/etc/openvpn/
├── aliyun.crt
├── aliyun.key
├── ca.crt
├── client.conf
├── dh2048.pem
├── easy-rsa
├── ipp.txt
├── ainevsia.crt
├── ainevsia.key
├── openvpn.log
├── openvpn-status.log
├── server.conf
├── ta.key
└── update-resolv-conf
The OpenVPN Server
needs the file server.conf
to start up normally. The files ca.crt client.conf ainevsia.crt ainevsia.key ta.key dh2048.pem
will all be needed by the client, so we are going to download these file next from our cloud server to the local computer, which is the client.
Get the Client Config File
You can use the sftp
command.
Copy the file to the home directory and then change the privilege. Then you can use sftp
to get your files.
sudo cp ca.crt ainevsia.crt ainevsia.key ta.key client.conf ~/
cd
sudo chmod o+r ainevsia.key ta.key
If you are on Windows, change the file client.conf
to ainevsia.ovpn
.
The Big Picture
Before we move on to the OpenWRT
section, you can checkout the following image to make sure that we are on the right track.
OpenWRT from Scratch
Basic Connection
To make demonstrations, I reset my OpenWRT
router so I can make configures from scratch. Here is the official documents.
This router enables wireless connections by default, so we can connect to it via Wi-Fi. Otherwise, you have to get a network cable between your local computer and your router.
There is no password required before I successfully connected to its Wi-Fi and the default gateway is 192.168.1.1
, which I will change to 192.168.10.1
because my upper router also has IP 192.168.1.1
which may harm the successful network connection of my OpenWRT
router. The first thing to do after connection is to set a password for the Wi-Fi.
Before proceeding, make sure that you have plugged in the network cable in the WAN
port of the router so that it can surf the Internet because we need Internet connection while downloading packages. Then all the commands are carried out during ssh. Here is the OpenWRT
version and the Linux
kernel version.
BusyBox v1.29.2 () built-in shell (ash)
_______ ________ __
| |.-----.-----.-----.| | | |.----.| |_
| - || _ | -__| || | | || _|| _|
|_______|| __|_____|__|__||________||__| |____|
|__| W I R E L E S S F R E E D O M
-----------------------------------------------------
OpenWrt 18.06.1, r1026-811894e1
-----------------------------------------------------
root@OpenWrt:~# uname -a
Linux OpenWrt 4.9.138 #0 Fri Nov 30 14:52:43 2018 mips GNU/Linux
Install OpenVPN
opkg
is the OpenWRT
’s splendid package manager, just like apt
and apt-get
in Linux
. However, the default source in the file distfeeds.conf
is blocked in China mainland, so change the sourse to USTC open source software mirror
. Then update will be fast and happy.
root@OpenWrt:~# cd /etc/opkg/
root@OpenWrt:/etc/opkg# ls
customfeeds.conf distfeeds.conf keys
root@OpenWrt:/etc/opkg# cp distfeeds.conf distfeeds.conf.bkup # backup before any operations
root@OpenWrt:/etc/opkg# sed -i "s/openwrt.proxy.ustclug.org/mirrors.ustc.edu.cn\/lede/" /etc/opkg/distfeeds.conf
root@OpenWrt:/etc/opkg# opkg update
root@OpenWrt:/etc/opkg#opkg install openvpn-openssl
Upload Configuration Files
Now we need to upload our configuration files onto the OpenWRT
router, which requires the sftp
service which need installation.
root@OpenWrt:/etc/opkg# opkg install openssh-sftp-server
Configuring the client is just the same as the server. The core file here is the client.ovpn
.
root@OpenWrt:/etc/openvpn# openvpn client.ovpn
Fri Sep 27 13:09:43 2019 OpenVPN 2.4.5 mips-openwrt-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [MH/PKTINFO] [AEAD][nonblock]
[.. omitted]
Fri Sep 27 13:09:46 2019 Initialization Sequence Completed
If you see the last line Initialization Sequence Completed
, then well done. You almost finished all the steps and the network is nearly set up.
Start on Boot
Now we are going to make this OpenVPN service start automatically each time it boots up, since the OpenWRT is not like the cloud server, it may reboot for any unexpected reason. Luckily, OpenWRT
provides a uniformed configuration interface called UCI
. It is simple and robust to use the UCI
to make configurations to achieve the desired service. The only thing to do is to modify the /etc/config/openvpn
file.
package openvpn
#################################################
# Sample to include a custom config file. #
#################################################
config openvpn custom_config
# Set to 1 to enable this instance:
option enabled 1
# Include OpenVPN configuration
option config /etc/openvpn/client.conf
Now you can test your OpenVPN
connection by launching a new terminal and run logread -f
command, which is used to track system logs, before the /etc/init.d/openvpn restart
command.
The following two command makes the OpenVPN
service starts on boot.
/etc/init.d/openvpn enable
/etc/init.d/openvpn restart
Finally, you should use the command reboot
to gently stop and restart the router instead of powering it off. If successful, it will automatically connects to the server.
If not, /etc/init.d/firewall restart
.
Optional Settings
Give the OpenWRT a Fixed IP
This part involves the operations on the server.conf
file on the remote server. Take a look at its comments:
# EXAMPLE: Suppose you want to give
# Thelonious a fixed VPN IP address of 10.9.0.1.
# First uncomment out these lines:
client-config-dir ccd
route 10.8.0.101 255.255.255.0
# Then add this line to ccd/Thelonious:
# ifconfig-push 10.9.0.1 10.9.0.2
So do what it says and create the folder and the file, write ifconfig-push 10.8.0.101 10.8.0.102
into the file openwrt
by the following command:
mkdir /etc/openvpn/ccd
echo ifconfig-push 10.8.0.101 10.8.0.102 > /etc/openvpn/ccd/openwrt
Now restart the service and it will take effect.
Add A HTTP-Proxy to Allow Foreign Connection
Squid
is a full-featured web proxy cache server application which provides proxy and cache services for Hyper Text Transport Protocol (HTTP), File Transfer Protocol (FTP), and other popular network protocols.
On your remote cloud server, install squid
and htpassws
, which is used for passowrd authentication.
sudo apt install squid aainevsiahe2-utils
Squid is configured by editing the directives contained within the
/etc/squid/squid.conf
configuration file. Prior to editing the configuration file, you should make a copy of the original file and protect it from writing so you will have the original settings as a reference, and to re-use as necessary. Make this copy and protect it from writing using the following commands:
sudo cp /etc/squid/squid.conf /etc/squid/squid.conf.original # make copy
sudo chmod a-w /etc/squid/squid.conf.original # protect from anyone changing it
To set your Squid
server to listen on TCP port 39458 instead of the default TCP port 3128, change the http_port directive as such:
http_port 39458
Squid
allows password authentication, which depends on htpasswd
to generate the password file. To enable basic_ncsa_auth (config file locates on /usr/lib/squid/basic_ncsa_auth
), do the following:
- Add the content to the config file
/etc/squid/squid.conf
[TAG: auth_param
].
auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwd
acl auth_user proxy_auth REQUIRED
http_access allow auth_user
- Use
htpasswd
to generate thepasswd
file and the user. It will prompt you to enter the password twice.
htpasswd -c /etc/squid/passwd ainevsia # ainevsia is the proxy_username which can be changed accordingly
The above command generates the file /etc/squid/passwd
. Now you can restart your squid
server to apply this change by the command systemctl restart squid
.
Small Change on the Local client.ovpn
file
To enable the http-proxy
service you have just configured on the remote server, you just need tiny modification on your local configuration file. Uncomment these two lines and modify the corresponding parameters in the brackets. Make your password.txt
file and write the username on the first line while the password on the second line.
http-proxy-retry # retry on connection failures
http-proxy [ip address] [squid port] [password.txt]
Finally, I append my local configuration file here for your reference:
$ tree ./
./
├── ca.crt
├── client.ovpn
├── dh2048.pem
├── ainevsia.crt
├── ainevsia.key
├── password.txt
└── ta.key
0 directories, 7 files
If you encounters any problems, check out the default log file of
squid
which locates at/var/log/squid/access.log
.
Success
Now here you go.
Believe it or not, we now have finished setting up a working virtual private network totally from scratch. I hope you think this really deserves the all the efforts you have spent.
I want to cut off this ariticle right now, althought it has already been too long than I have expected. There certianly will be various different unexpected problems when you try it yourself but believe that all those technical problem can be tackled down. There is simply just no magic.
Best wishes to all of you in this last line.