Organization of remote work of 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 completely autonomous system, and it will be useful for expansion when there is a shortage of licenses in an existing commercial system or its performance is insufficient.

The purpose of the article is to implement a complete system for providing remote access to an organization, which is a little more than "installing OpenVPN in 10 minutes."

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

A sign that a user is allowed to connect is their membership in the myVPNUsr group. The CA will be used offline.

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

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

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 an A-record gw.abc.ru has been created for our server in DNS.

Disabling SELinux is strongly discouraged! OpenVPN works without disabling security policies.

Content

  1. OS and application software installation
  2. Cryptography setup
  3. OpenVPN setup
  4. Authentication in AD
  5. Startup and diagnostics
  6. Issuing and revoking a certificate
  7. Network configuration
  8. What's next

OS and application software installation

We use the CentOS 7.8.2003 distribution. 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 installation, 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

We also need to make sure that time synchronization is running 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 setup

Change 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="[email protected]"
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

Here the parameters for the conditional organization ABC LLC are described, you can correct them for real ones or leave them from the example. The most important thing in the parameters is the last line, which defines the validity period of the certificate in days. The example uses the value 10 years (365*10+2 leap years). This value will need to be adjusted before user certificates are issued.

Next, set up a standalone certification authority.

Configuration includes exporting variables, initializing the CA, issuing the CA root key and certificate, Diffie-Hellman key, TLS key, and server key and certificate. The CA key must be carefully guarded and kept secret! All query parameters can be left as 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

This completes the main part of setting up the cryptographic mechanism.

OpenVPN setup

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 parameters:

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

*The range of addresses selected in the example will allow up to 127 clients to connect at the same time. /23 network is selected, and OpenVPN creates a /30 subnet for each client.
If necessary, the port and protocol can be changed, however, be aware that changing the port of the port number will cause SELinux to be configured, and using the tcp protocol will increase overhead, because. control of delivery of tcp packets is already performed at the level of packets encapsulated in the tunnel.

**If authentication in AD is not needed, comment them out, skip the next section, and in the template remove the auth-user-pass line.

Authentication in AD

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

We need an account in the domain with ordinary user rights and a group whose membership will determine connectivity.

We 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>

The main parameters:

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

Startup and diagnostics

Now we can try to enable and start our server:

$ sudo systemctl enable [email protected]
$ sudo systemctl start [email protected]

Launch check:

systemctl status [email protected]
journalctl -xe
cat /var/log/messages
cat /var/log/openvpn/*log

Issuing and revoking a certificate

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

Add the contents of the root certificate (ca.crt) and TLS key (ta.key) files to the profile.

Before issuing user certificates don't forget to set the required validity period of the certificates in the parameter file. You should not make it too large, 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:

  • lines PUSH YOUR… change to content своих certificates;
  • specify the name/address of your gateway in the remote directive;
  • the auth-user-pass directive is used for additional external authentication.

In the home directory (or other convenient place), 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 we can issue our first certificate.

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

Write Your Review

In case of compromise of the certificate (loss, theft), it is necessary to revoke this certificate:

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

View issued and revoked certificates

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

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

Explanation:

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

Network configuration

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

Allowing 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 subnetting and we need to tell the router(s) how to send packets destined for our VPN clients. In the command line, execute the command in the following manner (depending 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.

In case the organization has strict security rules, a firewall must also be configured on our VPN server. In my opinion, setting up iptables for FORWARD chains gives you the most flexibility, although setting them up is less convenient. A little more about setting them up. To do this, it is most convenient to use "direct rules" - direct rules stored in the file /etc/firewalld/direct.xml. The current configuration of the rules can be found as follows:

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

Before modifying a file, make a backup copy of it:

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

The approximate content of the file is 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>

Explanation

They are essentially regular iptables rules packaged differently since the advent of firewalld.

The destination interface with default settings is tun0, while the external one for the tunnel may be different, eg ens192, depending on the platform used.

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

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

Apply settings is a common firewalld command to reread settings:

$ sudo firewall-cmd --reload

Dropped packets can be viewed like this:

grep forward_fw /var/log/messages

What's next

This completes the setup!

It remains to install the client software on the client side, import the profile and connect. For OS type Windows, the distribution is located at developer site.

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

Stable connection!

Source: habr.com

Add a comment