Configuring OpenVPN

Install OpenVPN packages

Packages must be delivered both on the client and on the server.
yum install openssl easy-rsa lzo mlocate man lftp zip unzip

We make autoload modules into the kernel necessary for OpenVPN

[root@vpnserver]# touch /etc/rc.modules
[root@vpnserver]# chmod 700 /etc/rc.modules
[root@vpnserver]# vi /etc/rc.modules
modprobe tun
modprobe iptable_filter
modprobe iptable_mangle
modprobe ipt_conntrack
modprobe iptable_nat
modprobe ipt_MASQUERADE

modprobe ipt_LOG

Allow packet forwarding between interfaces

[root@vpnserver]# vi /etc/sysctl.conf
We change or add:
net.ipv4.ip_forward = 1
Apply the configuration:
sysctl -p

If you install OpenVPN inside an OpenVZ container

If you run OpenVPN inside the OpenVZ container, then the kernel modules mentioned above must be raised to memory on the host system.
You do sysctl settings inside guest VE.
On the host system, you must add permissions to the guest VE configuration file with OpenVPN to use the necessary kernel modules inside the guest VE.
IPTABLES="ip_tables iptable_filter iptable_mangle ip_conntrack ipt_conntrack iptable_nat "
When buying VPS / VDS containers on OpenVZ for using OpenVPN there, make sure that you will be given this permission and the modules will be lifted to the host system by the container supplier.

We generate keys on the OpenVPN server

[root@vpnserver]# updatedb -l0
[root@vpnserver]# locate build-ca
/usr/share/easy-rsa/2.0/build-ca
[root@vpnserver]# cd /usr/share/easy-rsa/2.0

[root@vpnserver]# ./build-ca
  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@vpnserver]# vi ./vars
export CA_EXPIRE=3650     # Validity of the root certificate
export KEY_EXPIRE=3650    # Key expiration date
KEY_SIZE=2048             # Key length

# You can set an expiration time of 100 years (36500 days).
# And the key length is longer if the larger one does not contradict local legislation.

[root@vpnserver]# source ./vars
[root@vpnserver]# ./clean-all

# Without ./clean-all ./build-ca it will not start, since there are no index.txt and serial files.
#. / clean-all cleans the key directory and creates these files.

Now create a self-signed root certificate ca.crt with the private key ca.key

[root@vpnserver]# ./build-ca
[root@vpnserver]# ls keys/
ca.crt  ca.key  index.txt  serial
! ca.key # This file is secret

Now create a certificate and secret key for the server

[root@vpnserver]# ./build-key-server server
...
Common Name (eg, your name or your server's hostname) [server]:
...
A challenge password []:	# you don’t need to set a password for the server, just press Enter
...
Sign the certificate? [y/n]:y
...
1 out of 1 certificate requests certified, commit? [y/n]y

[root@vpnserver]# ls keys/
ca.crt  ca.key  index.txt  serial  server.crt  server.csr  server.key

! The server argument of the ./build-key-server command is substituted as the CN (Common Name) parameter.
It is the most important part of the Remote certificate subject, which is used to authenticate the server with the client. If you assign a name to your VPN server DNS, then it is better to enter this host name in full here - FQDN,
as some clients, when connecting to the server, require matching its name.
Another option is to specify the IP address here or set the value to server, as done in our example.
For example, OpenVPN for Android, although it checks the server name specified in CN for matching the host name of the VPN server, but it has a loyal policy, since the server name expected by it can be set \ redefined in the program settings.
It has several choices: "Complete DN", "RDN (common name)" and "RDN prefix".
In the context of our example, in the OpenVPN settings under Android, we will set the server value for "RDN (common name)" either "RDN prefix", while "Complete DN", it makes sense to use it if the server name is set to FQDN.
! You have to answer Y to the two questions above, otherwise when starting the server there will be an error in the logs like this: openvpn: Cannot load certificate file /etc/openvpn/keys/server.crt: error:0906D06C:PEM routines:PEM_read_bio:no start line: error:140AD009:SSL routines:SSL_CTX_use_certificate_file:PEM lib

Let's protect ca.key on the server

Immediately after, we protect ca.key in case the server is compromised so that the attacker does not release his key.
[root@vpnserver]# cd ./keys
[root@vpnserver keys]# zip -e -r ca.key.zip ca.key
[root@vpnserver keys]# sha1sum ca.key.zip
[root@vpnserver keys]# shred -u ca.key
[root@vpnserver keys]# cd ..
[root@vpnserver]#
The zip archive itself, its checksum, the password for the archive must be recorded and put in a safe place.

Generating a Diffie-Hellman Key

The Diffie-Hellman algorithm allows two parties to obtain a common secret key, which is used for further symmetric data encryption.
[root@vpnserver]# ./build-dh
[root@vpnserver]# ls keys/
ca.crt  ca.key.zip  dh2048.pem  index.txt  serial  server.crt  server.csr  server.key

We generate a key for TLS authentication

[root@vpnserver]# openvpn --genkey --secret keys/ta.key # This file is secret
[root@vpnserver]# ls keys/
ca.crt  ca.key.zip  dh2048.pem  index.txt  serial  server.crt  server.csr  server.key  ta.key

Transfer the generated server keys and files to the necessary directories

[root@vpnserver 2.0]# mkdir /etc/openvpn/keys
[root@vpnserver 2.0]# mkdir /etc/openvpn/keys/addon/
[root@vpnserver 2.0]# mkdir /etc/openvpn/ccd
[root@vpnserver 2.0]# cd ./keys/
[root@vpnserver keys]# mv -iv ca.crt server.crt server.key ta.key dh2048.pem \
    /etc/openvpn/keys/
[root@vpnserver keys]# mv -iv * /etc/openvpn/keys/addon/
Our final server file structure looks something like this:
[root@vpnserver]# find /etc/openvpn/keys -type f |sort -r
/etc/openvpn/keys/ta.key
/etc/openvpn/keys/server.key
/etc/openvpn/keys/server.crt
/etc/openvpn/keys/dh2048.pem
/etc/openvpn/keys/ca.crt
/etc/openvpn/keys/addon/server.csr
/etc/openvpn/keys/addon/serial.old
/etc/openvpn/keys/addon/serial
/etc/openvpn/keys/addon/index.txt.old
/etc/openvpn/keys/addon/index.txt.attr
/etc/openvpn/keys/addon/index.txt
/etc/openvpn/keys/addon/ca.key.zip
/etc/openvpn/keys/addon/ca.key
/etc/openvpn/keys/addon/01.pem

We copy an example of a server config

We look at the description for each option in the example config.
cp -ia /usr/share/doc/openvpn*/sample/sample-config-files/server.conf  /etc/openvpn/
cp -ia /etc/openvpn/server.conf /etc/openvpn/server.conf.orig

Configure the server OpenVPN config file server.conf

port 11911

# The address of the interface on which the openvpn server will listen.
;local 1.2.3.4

;proto tcp
proto udp

;dev tap
dev tun

ca /etc/openvpn/keys/ca.crt
cert /etc/openvpn/keys/server.crt
key /etc/openvpn/keys/server.key  # This file should be kept secret

dh /etc/openvpn/keys/dh2048.pem

server 10.8.0.0 255.255.255.0

ifconfig-pool-persist ipp.txt

# Push the client to routing to specific addresses strictly via VPN
push "route 3.3.3.3 255.255.255.255"

# Push the default routing through the VPN to the client.
push "redirect-gateway def1"
# You may have to specify just push "redirect-gateway"
# if in client routings the network will be 128.0.0.0/1, more on that below.

# Push the DNS server to the client (several lines are possible).
push "dhcp-option DNS 8.8.8.8"  #push DNS entries to client 

# Directory for individual settings of each client (about it below).
client-config-dir /etc/openvpn/ccd

# Every 15 seconds send a ping, after a timeout of 60 seconds, restart the tunnel
keepalive 15 60

# The second parameter should be '0'
# on the server and '1' on the clients.
tls-auth /etc/openvpn/keys/ta.key 0 # This file is secret

# To see available and secure protocols: openvpn --show-ciphers
# The selected protocol must be supported on the server and client side.
;cipher BF-CBC        # Blowfish (default)
;cipher AES-128-CBC   # AES
;cipher DES-EDE3-CBC  # Triple-DES
cipher AES-256-CBC

comp-lzo

;max-clients 100
max-clients 30

# You can uncomment this out on
# non-Windows systems.
user nobody
group nobody

# persist-key Do not touch the tun device when restarting the openvpn server
persist-key
#persist-tun Не перечитывать файлы ключей при перезапуске туннеля
persist-tun

status openvpn-status.log

# 0 is silent, except for fatal errors
# 4 is reasonable for general usage
# 5 and 6 can help to debug connection problems
# 9 is extremely verbose
verb 3

Per-client server configuration files

Assigning a specific address to a specific client
10.8.0.16 IP on the client side on tun0, 10.8.0.15 - destination on the client side on tun0.
[root@vpnserver]# vi /etc/openvpn/ccd/client1
ifconfig-push 10.8.0.16 10.8.0.15
! client1 is the client name used to generate the client certificate, more on that below.

Masquerade Setting

We mask all outgoing packets with the address assigned to the eth0 interface.
[root@vpnserver]# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
[root@vpnserver]# chkconfig iptables on
[root@vpnserver]# /etc/init.d/iptables save
[root@vpnserver]# /etc/init.d/iptables reload
[root@vpnserver]# iptables -L POSTROUTING -nv -t nat
At the bottom of the page there are still examples with iptables how to secure OpenVPN clients from each other.

Launch OpenVPN Server

[root@vpnserver]# chkconfig openvpn on
[root@vpnserver]# chkconfig --list|fgrep openvpn
openvpn         0:off   1:off   2:on    3:on    4:on    5:on    6:off
[root@vpnserver]# service openvpn start
Startup errors should be viewed in /var/log/messages .

We provide customers with the files necessary to generate their keys

/etc/openvpn/keys/ta.key # This file is secret!!!!!
/etc/openvpn/keys/ca.crt
/etc/openvpn/keys/addon/ca.key.zip # This file is secret!!!!!

We generate keys at the client

[root@vpnclient1]# cd /usr/share/easy-rsa/2.0/

[root@vpnclient1 2.0]# vi ./vars
export CA_EXPIRE=3650	# expiration date of the root certificate
export KEY_EXPIRE=3650   # key validity period

can be set to 100 years (3650).

[root@vpnclient1 2.0]# source ./vars

[root@vpnclient1 2.0]# ./clean-all

[root@vpnclient1 2.0]# cp -ia /full/patch/to/file/from/server/{ca.crt,ca.key.zip} ./keys/
[root@vpnclient1 2.0]# cd ./keys/
[root@vpnclient1 keys/]# unzip ca.key.zip # Enter password here
[root@vpnclient1 keys/]# cd ..
[root@vpnclient1 2.0]# 

[root@vpnclient1 2.0]# ./build-key client1
...
Common Name (eg, your name or your server's hostname) [client1]: 
...
A challenge password []: #If you specify - it will be requested when connecting.
...
Sign the certificate? [y/n]:y
...
1 out of 1 certificate requests certified, commit? [y/n]y

[root@vpnclient1 2.0]# ls keys/
ca.key   ca.crt  client1.csr  client1.crt  client1.key
! On these two questions you need to answer Y.
! client1 Here it is, the same Common Name of the client for which on the server we created a separate configuration file in the ccd directory.
! client1.key # This file is secret

We generate a key for TLS authentication (on the client)

You need to take the server ta.key , this file is secret, so transmit it secretly.
Where to put it is written below.

Generate a Diffie-Hellman key (on the client)

[root@vpnclient1 2.0]# ./build-dh

We transfer the keys and files generated on the client to the necessary directories

[root@vpnclient1 2.0]# mkdir /etc/openvpn/server1/
[root@vpnclient1 2.0]# mkdir /etc/openvpn/server1/addon/
[root@vpnclient1 2.0]# cd keys/
[root@vpnclient1 keys]# mv -iv ca.crt client1.crt client1.key dh2048.pem /etc/openvpn/server1/
[root@vpnclient1 keys]# mv -iv * /etc/openvpn/server1/addon/
[root@vpnclient1 keys]# cp -ia /usr/share/doc/openvpn/sample/sample-config-files/client.conf \
   /etc/openvpn/server1.conf
[root@vpnclient1 keys]# cd /etc/openvpn/
[root@vpnclient1 openvpn]# cp -ia server1.conf server1.conf.orig

[root@vpnclient1 openvpn]# cp -ia /full/patch/to/ta.key /etc/openvpn/server1/ta.key
Our final client file structure looks like this:
[root@vpnclient1]# find /etc/openvpn/ -type f |sort -r
/etc/openvpn/server1/ta.key
/etc/openvpn/server1/dh2048.pem
/etc/openvpn/server1/client1.key
/etc/openvpn/server1/client1.crt
/etc/openvpn/server1/ca.crt
/etc/openvpn/server1/addon/serial.old
/etc/openvpn/server1/addon/serial
/etc/openvpn/server1/addon/index.txt.old
/etc/openvpn/server1/addon/index.txt.attr
/etc/openvpn/server1/addon/index.txt
/etc/openvpn/server1/addon/client1.csr
/etc/openvpn/server1/addon/ca.key
/etc/openvpn/server1/addon/ca.key.zip
/etc/openvpn/server1/addon/02.pem
/etc/openvpn/server1.conf.orig
/etc/openvpn/server1.conf

We configure the client OpenVPN config file server1.conf

client

;dev tap
dev tun

# Same on the server.
;proto tcp
proto udp

# This line needs to be commented out, by default it is "enabled".
#remote my-server-1 1194

#IP address and port on which the server listen.
remote 1.2.3.4 11911

resolv-retry infinite

nobind

# Downgrade privileges after initialization (non-Windows only)
# We don’t use it, because then we won’t be able to add some routes pro'push from the server.
;user nobody
;group nobody

# Try to preserve some state across restarts.
persist-key
persist-tun

ca /etc/openvpn/server1/ca.crt # This is a file copied from the server.
dh /etc/openvpn/server1/dh2048.pem # This is a local file generated on the client.
cert /etc/openvpn/server1/client1.crt # This is a local file generated on the client.
key /etc/openvpn/server1/client1.key  # This file is secret #Store only on the client.

# If a tls-auth key is used on the server
# then every client must also have the key.
# The second parameter should be '0'
# on the server and '1' on the clients.
tls-auth /etc/openvpn/server1/ta.key 1 # This is a file copied from the server.

# Select a cryptographic cipher.
# If the cipher option is used on the server
# then you must also specify it here.
# Same as on server.
# Note on security and on available ciphers see above in the server example config.
cipher AES-256-CBC

comp-lzo

verb 3

# This parameter is enough to specify on the server only.
#keepalive 15 240

Delete the secret file from the server ca.key and ca.key.zip on the client

This file, as we recall, came to us from the server, along with ca.ctr and and ta.key.
This is a secret file, we will delete it so that the thief cannot smoke it from the client and make a certificate for himself without our knowledge.
shred -u /etc/openvpn/server1/addon/ca.key /etc/openvpn/server1/addon/ca.key.zip
touch -u /etc/openvpn/server1/addon/ca.key_from_server_was_here

Checking OpenVPN connection on the client

openvpn --config /etc/openvpn/server1.conf
If you see the line in the output (strange route):
... /usr/sbin/ip route del 128.0.0.0/1 ....
then on the server you need to change:
;push "redirect-gateway def1"
push "redirect-gateway"
After that, you need to restart the server:
[root@vpnserver]# service openvpn restart

List of modified / created files / directories

For server:
/etc/rc.modules
/etc/sysctl.conf
/usr/share/easy-rsa/2.0/vars
/etc/openvpn/
/etc/sysconfig/iptables
For client:
/etc/openvpn/

Secret files that must remain in the context of the machine on which they are generated

For server:
server.key (Server Key)
ca.key (Root CA key)
ta.key (Must securely copy to the client)
For client:
client1.key (Client1 Key)

Protecting OpenVPN Clients from Each Other

All data exchange between clients is that the package exits and enters the same interface tun0.
If you need to make OpenVPN clients not see each other, but can only go outside:
iptables -A FORWARD -i tun0 -o tun0 -j DROP
Here is a more comprehensive example (excerpt from the /etc/sysconfig/iptables file):
...
# Allow already established connections in the context of conntrack rules set below
#-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

# And here is an example of such a conntrack rule.
# Allow communication between 10.8.0.16 and 10.8.0.18,
# but only if the connection initiated 10.8.0.16 (but not vice versa).
# -A FORWARD -s 10.8.0.16 -d 10.8.0.18 -m conntrack --ctstate NEW -j ACCEPT

# And here is the same example above, but only on a specific TCP port.
# -A FORWARD -s 10.8.0.16 -d 10.8.0.18 -m conntrack -p tcp --dport 3333 --ctstate NEW -j ACCEPT

# Allow two-way (full) interaction 10.8.0.16 and 10.8.0.18.
# -A FORWARD -s 10.8.0.16 -d 10.8.0.18 -j ACCEPT
# -A FORWARD -s 10.8.0.18 -d 10.8.0.16 -j ACCEPT

-A FORWARD -i tun0 -o tun0 -j DROP
...
Note that in the more comprehensive example above, we did not use the -i tun0 -o tun0 modifiers.
If you want, you can add them, they will not hurt.
Use -p tcp and -p udp, --dport, --sport and even - -src-range 1.2.3.4-1.2.3.6.

You can also think about the situation, what will happen if the interface name changes from tun0 to tun1.
Perhaps this is paranoia, but the interaction between customers in this case is better to prohibit:
...
-A FORWARD -i tun0 -o tun0 -j DROP
-A FORWARD -i tun1 -o tun1 -j DROP
-A FORWARD -i tun2 -o tun2 -j DROP
-A FORWARD -i tun3 -o tun3 -j DROP
-A FORWARD -i tun4 -o tun4 -j DROP
-A FORWARD -i tun5 -o tun5 -j DROP
Remember that all iptables rules are applied in the order they are followed, set permissions first, then bans. And be careful with the prohibitions so as not to lose remote access to the VPN server.
At the end of a successful setup, be sure to make /etc/init.d/iptables save.

Detailed instructions for setting up the Android OpenVPN application (de.blinkt.openvpn)

Launch the application.

In the main menu, the SETTINGS tab.
Show logn window - off.
Reconnect on network change - on.

In the main menu, the PROFILES tab.
Click the (+) icon at the top of the main window.
In the Add Profile window: Enter a name identifying the new Profile -
enter a profile name of type "server1". Click OK.

In the server1 profile settings.
In the BASIC tab.
LZO Compression - on.
Type drop-down menu set "Certificates".
Point CA Certificate, click the Select button and select the file ca.crt
Client Certificate item, click the Select button and select the file client1.crt
The Client Certificate Key item, click the Select button and select the file client1.key

In the SERVER LIST tab.
Server Address:  (it makes sense to enter here IP, not the host name)
Server Port: 1194 (or the port number that you specified on the server side).
Protocol: UDP (all settings in this article were UDP protocol compliant)
Custom Options - off.

In the IP AND DNS tab.
Pull Settings - on.
No local binding - off.
Override DNS Setting by Server - on.
searchDomain - "localhost"
DNS Server: 8.8.8.8
Backup DNS Server: 8.8.4.4

In the ROUTING tab.
Ignores pushed routes - off.
Bypass VPN ofr local network - on.
IPv4 Use default Route - on.
IPv6 Use default Route - on.

In the AUTHENTICATION / ENCRYPTION tab
Expect TLS server certificate - on.
Certificate Hostname Check - on.

Remote certificate subject: RDN (common name): server1
# the name that was passed to the ./build-key-server .. command on the server.

Use TLS Authentication - on.
TLS Auth File select the file  ta.key 
TLS Direction: 1 # for client 1, for server 2, look above in the article on TLS.
Encryption cipher - "AES-256-CBC" # same as on server, see article on AES-256-CBC above

In the ADVANCED tab
Persistent tun - on.
Push Peer info - off.
Connection retries - Five reconnection retries.
Seconds between connections - "15"
Random Host Prefix - off.
Allow floating server - off.
Override MSS value of TCP - off
Enable Custom Options - on.
Custom Options - leave blank.

To save the profile settings, just exit the profile with the back button on the phone.

How to use only one OpenVPN connection on several PC.

  1. Setup LXC, QEMU, VBOX instance with OpenVPN client connectd to the OpenVPN server.
  2. Assign non-NAT'ed IP address to it across your local network to this virtualized instance.
  3. sysctl -w net.ipv4.ip_forward=1
  4. iptables -t nat -A POSTROUTING -s LOCALNET/24 -j MASQUERADE
  5. Now you just make default GW in your local network to route traffic to it.