Organization of remote work SMB organization on OpenVPN

Formulation of the problem


The article describes the organization of remote access for employees on open source products and can be used both to build a fully autonomous system and will be useful for expansion when there is a lack of licenses in an existing commercial system or its performance is insufficient.

The purpose of the article is to introduce a complete system for providing remote access to an organization, which is slightly more than “installing OpenVPN in 10 minutes”.

As a result, we get a system in which certificates and (optionally) Active Directory corporate directory will be used for user authentication. T.O. we get a system with two verification factors - what I have (certificate) and what I know (password).

A sign that the user is allowed to connect is his membership in the myVPNUsr group. Certificate Authority will be used standalone.

The cost of implementing the solution is only small hardware resources and 1 hour of work of the system administrator.

We will use a virtual machine with OpenVPN and Easy-RSA 3rd version on CetntOS 7, which based on 100 connections issued 4 vCPU, 4 GiB RAM.

In the example, the network of our organization is 172.16.0.0/16, in which the VPN server with the address 172.16.19.123 is located in the segment 172.16.19.0/24, the DNS servers are 172.16.16.16 and 172.16.17.17, and the subnet 172.16.20.0/23 is allocated for VPN clients .

To connect from the outside, a connection is used on port 1194 / udp, and in DNS for our server an A-record gw.abc.ru is created.

It is strongly not recommended to disable SELinux! OpenVPN works without disabling security policies.

Content


  1. OS and application software installation
  2. Cryptography Setting
  3. Configure OpenVPN
  4. Authentication in AD
  5. Launch and Diagnostics
  6. Issue and revocation of certificate
  7. Network configuration
  8. What's next


OS and application software installation


We use the distribution kit CentOS 7.8.2003. We need to install the OS in a minimal configuration. It is convenient to do this using kickstart , cloning a previously installed OS image, and other means.

After installing, assigning an address to the network interface (according to the conditions of task 172.16.19.123), we update the OS:

$ sudo yum update -y && reboot

It is also necessary to make sure that time synchronization is performed on our machine.
To install the application software, you need the openvpn, openvpn-auth-ldap, easy-rsa and vim packages as the main editor (you will need the EPEL repository).

$ sudo yum install epel-release
$ sudo yum install openvpn openvpn-auth-ldap easy-rsa vim

For a virtual machine, it is useful to install a guest agent:

$ sudo yum install open-vm-tools

for VMware ESXi hosts, or for oVirt

$ sudo yum install ovirt-guest-agent


Cryptography Setting


Go to the easy-rsa directory:

$ cd /usr/share/easy-rsa/3/

Create a variable file:

$ sudo vim vars

the following content:

export KEY_COUNTRY="RU"
export KEY_PROVINCE="MyRegion"
export KEY_CITY="MyCity"
export KEY_ORG="ABC LLC"
export KEY_EMAIL="admin@abc.ru"
export KEY_CN="allUsers"
export KEY_OU="allUsers"
export KEY_NAME="gw.abc.ru"
export KEY_ALTNAMES="abc-openvpn-server"
export EASYRSA_CERT_EXPIRE=3652

The parameters for the conditional organization of ABC LLC are described here. You can correct them for real or leave them as an example. The most important thing in the parameters is the last line, which determines the certificate validity period in days. In the example, the value of 10 years is used (365 * 10 + 2 leap years). This value will need to be adjusted before issuing user certificates.

Next, set up a standalone certification authority.

Configuration includes exporting variables, initializing the CA, issuing the root key and the CA certificate, the Diffie-Hellman key, the TLS key, as well as the server key and certificate. The certificate authority key must be carefully guarded and kept secret! All parameters at requests can be left by default.

cd /usr/share/easy-rsa/3/
. ./vars
./easyrsa init-pki
./easyrsa build-ca nopass
./easyrsa gen-dh
./easyrsa gen-req myvpngw nopass
./easyrsa sign-req server myvpngw
./easyrsa gen-crl
openvpn --genkey --secret pki/ta.key

On this, the main part of the cryptographic mechanism setup is completed.

Configure OpenVPN


Go to the OpenVPN directory, create service directories and add a link to easy-rsa:

cd /etc/openvpn/
mkdir /var/log/openvpn/ /etc/openvpn/ccd /usr/share/easy-rsa/3/client
ln -s /usr/share/easy-rsa/3/pki/ /etc/openvpn/

Create the main OpenVPN configuration file:

$ sudo vim server.conf

the following content

port 1194
proto udp
dev tun
ca /etc/openvpn/pki/ca.crt
cert /etc/openvpn/pki/issued/myvpngw.crt
key /etc/openvpn/pki/private/myvpngw.key
crl-verify /etc/openvpn/pki/crl.pem
dh /etc/openvpn/pki/dh.pem
server 172.16.20.0 255.255.254.0
ifconfig-pool-persist ipp.txt
push "route 172.16.0.0 255.255.255.0"
push "route 172.17.0.0 255.255.255.0"
client-config-dir ccd
push "dhcp-option DNS 172.16.16.16"
push "dhcp-option DNS 172.16.17.17"
keepalive 10 120
cipher AES-256-CBC
user nobody
group nobody
persist-key
persist-tun
status /var/log/openvpn/openvpn-status.log
log-append  /var/log/openvpn/openvpn.log
verb 3
explicit-exit-notify 1
username-as-common-name
plugin /usr/lib64/openvpn/plugin/lib/openvpn-auth-ldap.so /etc/openvpn/ldap.conf

Some notes on the parameters:

  • if a different name was indicated when issuing the certificate, indicate it;
  • specify the address pool for your tasks *;
  • routes and DNS servers can be one or more;
  • The last 2 lines are needed to implement authentication in AD **.

* 127 , .. /23, OpenVPN /30.
, , SELinux, tcp , .. tcp- .

** AD , , — , auth-user-pass.


AD


To support the second factor, we will use account verification in AD.

We need an account in the domain with the rights of an ordinary user and a group, the membership of which will determine the ability to connect.

Create a configuration file:

/etc/openvpn/ldap.conf

the following content

<LDAP>
        URL             "ldap://ldap.abc.ru"
        BindDN          "CN=bindUsr,CN=Users,DC=abc,DC=ru"
        Password        b1ndP@SS
        Timeout         15
        TLSEnable       no
        FollowReferrals yes
</LDAP>
<Authorization>
        BaseDN          "OU=allUsr,DC=abc,DC=ru"
        SearchFilter    "(sAMAccountName=%u)"
        RequireGroup    true
        <Group>
                BaseDN          "OU=myGrp,DC=abc,DC=ru"
                SearchFilter    "(cn=myVPNUsr)"
                MemberAttribute "member"
        </Group>
</Authorization>

Main parameters:

  • URL "ldap: //ldap.abc.ru" - the address of the domain controller;
  • BindDN “CN = bindUsr, CN = Users, DC = abc, DC = ru” - the canonical name for binding to LDAP (UZ - bindUsr in the container abc.ru/Users);
  • Password b1ndP @ SS - user password for binding;
  • BaseDN "OU = allUsr, DC = abc, DC = ru" - the path from which to start the user search;
  • BaseDN “OU = myGrp, DC = abc, DC = ru” - the container of the allowing group (the group myVPNUsr in the container abc.ru \ myGrp);
  • SearchFilter "(cn = myVPNUsr)" is the name of the resolving group.


Launch and Diagnostics


Now we can try to turn on and start our server:

$ sudo systemctl enable openvpn@server.service
$ sudo systemctl start openvpn@server.service

Launch Check:

systemctl status openvpn@server.service
journalctl -xe
cat /var/log/messages
cat /var/log/openvpn/*log

Issue and revocation of certificate


Because in addition to the certificates themselves, you need keys and other settings, it is very convenient to wrap all this in one profile file. This file is then transferred to the user and the profile is already imported on the OpenVPN client. To do this, create a configuration template and a script that forms the profile.

In the profile, you need to add the contents of the root certificate files (ca.crt) and the TLS key (ta.key).

Before issuing user certificates, be sure to set the required certificate validity period in the parameter file. You should not make it too big, I recommend limiting it to a maximum of 180 days.

vim /usr/share/easy-rsa/3/vars

...
export EASYRSA_CERT_EXPIRE=180

vim /usr/share/easy-rsa/3/client/template.ovpn

client
dev tun
proto udp
remote gw.abc.ru 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-CBC
verb 3
auth-user-pass

<ca>
-----BEGIN CERTIFICATE-----
PUT YOUR CA CERT (ca.crt) HERE
-----END CERTIFICATE-----
</ca>

key-direction 1
<tls-auth>
-----BEGIN OpenVPN Static key V1-----
PUT YOUR TA KEY (ta.key) HERE
-----END OpenVPN Static key V1-----
</tls-auth>

Notes:

  • PUT YOUR ... strings are changed to the contents of their certificates;
  • in the directive remote specify the name / address of your gateway;
  • The auth-user-pass directive is used for additional external authentication.

In the home directory (or other convenient place) we create a script for requesting a certificate and creating a profile:

vim ~/make.profile.sh

#!/bin/bash

if [ -z "$1" ] ; then
 echo Missing mandatory client name. Usage: $0 vpn-username
 exit 1
fi

#Set variables
basepath=/usr/share/easy-rsa/3
clntpath=$basepath/client
privpath=$basepath/pki/private
certpath=$basepath/pki/issued
profile=$clntpath/$1.ovpn

#Get current year and lowercase client name
year=`date +%F`
client=${1,,}
echo Processing $year year cert for user/device $client

cd $basepath

if [  -f client/$client* ]; then
    echo "*** ERROR! ***"
    echo "Certificate $client already issued!"
    echo "*** ERROR! ***"
    exit 1
fi

. ./vars
./easyrsa --batch --req-cn=$client gen-req $client nopass
./easyrsa --batch sign-req client $client

#Make profile
cp $clntpath/template.ovpn $profile

echo "<key>" >> $profile
cat $privpath/$1.key >> $profile
echo "</key>" >> $profile

echo -e "\n" >> $profile
openssl x509 -in $certpath/$1.crt -out $basepath/$1.crt

echo "<cert>" >> $profile
cat $basepath/$1.crt >> $profile
echo "</cert>" >> $profile
echo -e "\n" >> $profile

#remove tmp file
rm -f $basepath/$1.crt

echo Complete. See $profile file.

cd ~

We make the file executable:

chmod a+x ~/make.profile.sh

And you can issue our first certificate.

~/make.profile.sh my-first-user


Feedback


If the certificate is compromised (loss, theft), this certificate must be revoked:

cd /usr/share/easy-rsa/3/
./easyrsa revoke my-first-user
./easyrsa gen-crl


View issued and revoked certificates


To view the issued and revoked certificates, just view the index file:

cd /usr/share/easy-rsa/3/
cat pki/index.txt

Explanations:

  • the first line is the server certificate;
  • first character
    • V (Valid) - valid;
    • R (Revoked) - recalled.


Network configuration


The last steps are setting up a transmission network - routing and firewalls.

Permission for connections in the local firewall:

$ sudo firewall-cmd --add-service=openvpn
$ sudo firewall-cmd --add-service=openvpn --permanent

Next, enable IP traffic routing:

$ sudo sysctl net.ipv4.ip_forward=1
$ sudo echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/50-sysctl.conf

In a corporate environment, there is probably a division into subnets and we need to tell the router (s) how to send packets addressed to our VPN clients. At the command line, execute the command in the manner (depends on the equipment used):

# ip route 172.16.20.0 255.255.254.0 172.16.19.123

and save the configuration.

In addition, on the interface of the border router, where the external address gw.abc.ru is served, it is necessary to allow the passage of udp / 1194 packets.

If your organization has strict security rules, you must also configure a firewall on our VPN server. In my opinion, setting up iptables FORWARD chains gives the most flexibility, although setting them up is less convenient. A bit more about setting them up. For this, it is most convenient to use “direct rules” - direct rules stored in the /etc/firewalld/direct.xml file . The current rule configuration can be found out as follows:

$ sudo firewall-cmd --direct --get-all-rule

Before changing the file, make a backup copy of it:

cp /etc/firewalld/direct.xml /etc/firewalld/direct.xml.`date +%F.%T`.bak

The approximate contents of the file are as follows:

<?xml version="1.0" encoding="utf-8"?>
<direct>
 <!--Common Remote Services-->
  <!--DNS-->
    <rule priority="0" table="filter" ipv="ipv4" chain="FORWARD">-i tun0 -o ens192 -p udp --dport 53 -j ACCEPT</rule>
  <!--web-->
    <rule priority="0" table="filter" ipv="ipv4" chain="FORWARD">-i tun0 -o eth0 -p tcp -d 172.16.19.200 --dport 80 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT</rule>
    <rule priority="0" table="filter" ipv="ipv4" chain="FORWARD">-i tun0 -o eth0 -p tcp -d 172.16.19.201 --dport 443 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT</rule>
  <!--Some Other Systems-->
    <rule priority="0" table="filter" ipv="ipv4" chain="FORWARD">-i tun0 -o eth0 -p udp -d 172.16.19.100 --dport 7000 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT</rule>
  <!--just logging-->
    <rule priority="1" table="filter" ipv="ipv4" chain="FORWARD">-i tun0 -o eth0 -j LOG --log-prefix 'forward_fw '</rule>
</direct>

Explanations


Essentially, these are the usual iptables rules, otherwise packaged after the appearance of firewalld.

The destination interface at the default settings is tun0, and the external one for the tunnel may be different, for example, ens192, depending on the platform used.

The last line is for logging dropped packets. For logging to work, you need to change the debugging level in the firewalld configuration:

vim /etc/sysconfig/firewalld
FIREWALLD_ARGS=--debug=2

Apply settings - the usual firewalld command to re-read settings:

$ sudo firewall-cmd --reload

Discarded packets can be viewed as follows:

grep forward_fw /var/log/messages


What's next


The setup is done!

It remains on the client side to install the client software, import the profile and connect. For an OS such as Windows, the distribution is available on the developer's site .

In conclusion, we connect our new server to monitoring and archiving systems, and do not forget to regularly install updates.

Stable connection!

All Articles