Ubuntu/OpenVPN Server: Difference between revisions
From charlesreid1
| Line 149: | Line 149: | ||
But what DNS server will the new VPN use? Do we need a new DHCP server too? Can we handle DNS for tun1 too? Do we need to set up another dnsmasq instance? | But what DNS server will the new VPN use? Do we need a new DHCP server too? Can we handle DNS for tun1 too? Do we need to set up another dnsmasq instance? | ||
No network management needed, OpenVPN handles assigning IPs, so if it is a standalone plain network, nope, no new servers needed. | |||
==Configure PAM== | ==Configure PAM== | ||
Revision as of 07:35, 8 July 2020
Server Prep
Install OpenVPN
Update and install, this should have been completed earlier for the PIA VPN tunnel:
sudo apt update sudo apt -y install openvpn
Install EasyRSA
Obtain and install EasyRSA to create a certificate authority and certificates for the server:
wget -qO- https://github.com/OpenVPN/easy-rsa/releases/download/2.2.2/EasyRSA-2.2.2.tgz | tar xvz -C /opt/ cp -R /opt/EasyRSA-2.2.2 /opt/easy-rsa ln -fs /opt/easy-rsa/openssl-1.0.0.cnf /opt/easy-rsa/openssl.cnf
Setup OpenVPN Server
Set local EasyRSA variables for the certificate.
/opt/easy-rsa/local_vars
export KEY_COUNTRY="US" export KEY_PROVINCE="CA" export KEY_CITY="Santa Cruz" export KEY_ORG="charlesreid1.com" export KEY_OU="bespin VPN" export KEY_EMAIL="" export KEY_NAME="bespin VPN key"
Set permissions and ownership:
chmod 0644 /opt/easy-rsa/local_vars chown root:root /opt/easy-rsa/local_vars
Prepare to generate secrets:
cd /opt/easy-rsa
Clean keys directory:
test -e /opt/easy-rsa/clean-all . /opt/easy-rsa/vars;. /opt/easy-rsa/local_vars;/opt/easy-rsa/clean-all
Build certificate - make script non-interactive, then run:
test -e /opt/easy-rsa/build-ca sed -i 's/--interact//g' /opt/easy-rsa/build-ca . /opt/easy-rsa/vars;. /opt/easy-rsa/local_vars;/opt/easy-rsa/build-ca
Build DH parameters:
test -e /opt/easy-rsa/build-dh . /opt/easy-rsa/vars;. /opt/easy-rsa/local_vars;/opt/easy-rsa/build-dh
Build key - make script non-interactive, then run:
test -e /opt/easy-rsa/build-key-server sed -i 's/--interact//g' /opt/easy-rsa/build-key-server . /opt/easy-rsa/vars;. /opt/easy-rsa/local_vars;/opt/easy-rsa/build-key-server server
Make keys directory:
mkdir -p /opt/easy-rsa/keys cd /opt/easy-rsa/keys
Generate static TLS secret:
openvpn --genkey --secret statictlssecret.key
Configure VPN Server
Here we configure the VPN so that VPN IP addresses are in the CIDR block 10.10.10.0/24.
/etc/openvpn/server.conf
port 1194 proto udp dev tun server 10.101.0.0 255.255.255.0 # enable this line to tunnel all client traffic thru vpn #push "redirect-gateway def1" # use dnsmasq as a dns server push "dhcp-option DNS 10.10.10.1" ca /opt/easy-rsa/keys/ca.crt cert /opt/easy-rsa/keys/server.crt key /opt/easy-rsa/keys/server.key dh /opt/easy-rsa/keys/dh2048.pem tls-auth statictlssecret.key 0 # use pam for auth plugin /usr/lib/x86_64-linux-gnu/openvpn/plugins/openvpn-plugin-auth-pam.so openvpn # custom client configurations client-config-dir /etc/openvpn/clients
Configure VPN Server Startup Service
Run this command to update the openvpn@ startup service to send separate logs for separate openvpn networks into their own log files:
sed -i 's|^ExecStart=.*|& --log-append /var/log/openvpn.%i.log|' /lib/systemd/system/openvpn@.service
A Note on the OpenVPN Startup Service
Quick side note to explain /lib/systemd/system/openvpn@.service:
This is a TEMPLATED startup service that allows you to run multiple startup services for multiple instances of openvpn for multiple VPNs. If you run service openvpn@myvpn start, it will start OpenVPN with the configuration file myvpn.conf.
Enable and Start VPN Server Service
Given that our OpenVPN server config file is in server.conf in /etc/openvpn, we can start an OpenVPN service with this config file like this:
systemctl enable openvpn@server.service systemctl start openvpn@server.service
Configure iptables
The way we plan on doing this, we're just going to use the VPN tunnel to be able to reach bespin. There is no need to share networks.
But what DNS server will the new VPN use? Do we need a new DHCP server too? Can we handle DNS for tun1 too? Do we need to set up another dnsmasq instance?
No network management needed, OpenVPN handles assigning IPs, so if it is a standalone plain network, nope, no new servers needed.
Configure PAM
PAM is the pluggable authentication module in Linux. It provides a variety of methods for authenticating users in various contexts (for example, when you log into a desktop computer).
In the OpenVPN server config file, we included the following line to use PAM for authentication:
# use pam for auth plugin /usr/lib/x86_64-linux-gnu/openvpn/plugins/openvpn-plugin-auth-pam.so openvpn
This corresponds to a configuration file /etc/pam.d/openvpn that contains directives telling PAM how OpenVPN wants to authenticate users.
We can use Unix usernames/passwords to authenticate users:
/etc/pam.d/openvpn
auth required pam_unix.so
Adding MFA to VPN Access
To add MFA to the VPN access (note: this will require changes to how users are created below), first install the Google Authenticator PAM library and other utilities:
apt-get -y install libpam-google-authenticator libqrencode3 qrencode
Now modify the contents of /etc/pam.d/openvpn to replace the Unix login with Google Authenticator as a method of authentication:
/etc/pam.d/openvpn
auth required /lib/x86_64-linux-gnu/security/pam_google_authenticator.so secret=/etc/openvpn/google-authenticator/${USER} user=gauth try_first_pass
Also need to create a gauth user to handle Google Authenticator stuff:
addgroup gauth && useradd -g gauth gauth
Create the Google Authenticator directory:
mkdir /etc/openvpn/google-authenticator
Set ownership and permissions:
chown gauth:gauth /etc/openvpn/google-authenticator chmod 0700 /etc/openvpn/google-authenticator
Starting the OpenVPN Server
If your OpenVPN server config file is at /etc/openvpn/server.conf then you can enable and start the service with these commands:
sudo systemctl enable openvpn@server sudo systemctl start openvpn@server
Verify the service starts okay by monitoring the syslog in another window:
sudo tail -f /var/log/syslog
Verify the tun0 interface came up
Client Prep
Setup OpenVPN Client
Fix up the build key script so that it is non-interactive and has correct paths:
sed -i 's/--interact//g' /opt/easy-rsa/build-key sed -i 's+export EASY_RSA=.*+export EASY_RSA="/opt/easy-rsa"+' /opt/easy-rsa/build-key
Add a custom client config directory:
mkdir -p /etc/openvpn/clients
Configure OpenVPN Client
Configure the OopenVPN client by creating a client config file:
/opt/easy-rsa/openvpn_client.conf
client dev tun proto udp remote REMOTEIPOFOPENVPNSERVERGOESHERE 1194 nobind pull persist-key persist-tun remote-cert-tls server ca ca.crt cert clientuser.crt key clientuser.key tls-auth statictlssecret.key 1 auth-user-pass
Create Utility Scripts
We are going to create a couple of scripts to accomplish the task of registering users for the OpenVPN network.
First let's install some utilities that we will use.
Install Utility Helpers
sudo apt-get -y install zip unzip
Generate OpenVPN Profile
/opt/easy-rsa/gen_ovpn_profile.sh
#!/bin/bash
# Called by gen_client.sh
# Usage: ./gen_ovpn_profile.sh [USERNAME]
set -e
test "$#" -eq "1" || { echo "Provide 1 argument (username)"; exit 1; }
test -e /opt/openvpn/openvpn_client.conf || { echo "client config openvpn_client.conf not found!"; exit 1; }
test -e /opt/easy-rsa/keys/${1}.key || { echo "client key ${1} not found!"; exit 1; }
test -e /opt/easy-rsa/keys/ca.crt || { echo "server certificate ca.crt not found!"; exit 1; }
(cat /opt/openvpn/openvpn_client.conf
echo '<key>'
cat /opt/easy-rsa/keys/${1}.key
echo '</key>'
echo '<cert>'
cat /opt/easy-rsa/keys/${1}.crt
echo '</cert>'
echo '<ca>'
cat /opt/easy-rsa/keys/ca.crt
echo '</ca>'
) > /opt/easy-rsa/keys/openvpn_${1}.ovpn
Set ownership and permissions:
chmod 0700 /opt/easy-rsa/gen_ovpn_profile.sh chown root:root /opt/easy-rsa/gen_ovpn_profile.sh
Zip Client Files
/opt/easy-rsa/zip_client_files.sh
#!/bin/bash
# Called by gen_client.sh
# Usage: ./zip_client_files.sh [USERNAME]
set -e
test "$#" -eq "1" || { echo "Provide 1 argument (username)"; exit 1; }
FILES="/opt/easy-rsa/keys/ca.crt
/opt/easy-rsa/keys/statictlssecret.key
/opt/easy-rsa/keys/${1}.key
/opt/easy-rsa/keys/${1}.crt
/opt/easy-rsa/keys/openvpn_${1}.ovpn
/opt/easy-rsa/README
/opt/easy-rsa/keys/${1}_password.txt"
cat /opt/easy-rsa/README_LOGIN > /opt/easy-rsa/README
for fname in ${FILES}; do
test -e ${fname} || { echo "File ${fname} not found!"; exit 1; }
done
cd /opt/easy-rsa/keys
zip -j ${1}.zip $FILES
rm -f /opt/easy-rsa/README
Set ownership and permissions:
chmod 0700 /opt/easy-rsa/zip_client_files.sh chown root:root /opt/easy-rsa/zip_client_files.sh
Zip Client Files MFA Version
If you are setting up MFA, change the scripts as follows:
/opt/easy-rsa/zip_client_files.sh
#!/bin/bash
# Called by gen_client.sh
# Usage: ./zip_client_files.sh [USERNAME]
# Set the MFA_DISABLED env var to any value to use script for non-MFA clients
set -e
test "$#" -eq "1" || { echo "Provide 1 argument (username)"; exit 1; }
FILES="/opt/easy-rsa/keys/ca.crt
/opt/easy-rsa/keys/statictlssecret.key
/opt/easy-rsa/keys/${1}.key
/opt/easy-rsa/keys/${1}.crt
/opt/easy-rsa/keys/openvpn_${1}.ovpn
/opt/easy-rsa/README"
if [ -z "${MFA_DISABLED}" ]; then
FILES="${FILES}
/etc/openvpn/google-authenticator/${1}_qr.png
/etc/openvpn/google-authenticator/${1}_backup_codes.txt"
cat /opt/easy-rsa/README_MFA > /opt/easy-rsa/README
else
FILES="${FILES}
/opt/easy-rsa/keys/${1}_password.txt"
cat /opt/easy-rsa/README_LOGIN > /opt/easy-rsa/README
fi
for fname in ${FILES}; do
test -e ${fname} || { echo "File ${fname} not found!"; exit 1; }
done
cd /opt/easy-rsa/keys
zip -j ${1}.zip $FILES
rm -f /opt/easy-rsa/README
Generate and Delete Client Scripts
Generate Client Script
/opt/easy-rsa/gen_client.sh
#!/bin/bash
# Create new client and files required by new client.
# Usage: ./gen_client.sh [USERNAME]
set -e
test "$#" -eq "1" || { echo "Provide 1 argument (username)"; exit 1; }
# Run build-key
test -e /opt/easy-rsa/build-key || { echo "build-key not found!"; exit 1; }
test -e /opt/easy-rsa/gen_ovpn_profile.sh || { echo "gen_ovpn_profile.sh not found!"; exit 1; }
. /opt/easy-rsa/vars
. /opt/easy-rsa/local_vars
/opt/easy-rsa/build-key ${1}
# Generate .ovpn profile
test -e /opt/easy-rsa/keys/${1}.crt || { echo "client certificate ${1} not found!"; exit 1; }
/opt/easy-rsa/gen_ovpn_profile.sh ${1}
# Register unix user and set a password
useradd -s /bin/nologin "${1}"
# Login user needs password
head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 > /opt/easy-rsa/keys/${1}_password.txt
echo "${1}:$(cat /opt/easy-rsa/keys/${1}_password.txt)" | chpasswd
# Zip up all the client's files
/opt/easy-rsa/zip_client_files.sh ${1}
rm -f /opt/easy-rsa/keys/${1}_password.txt
Set ownership and permissions:
chmod 0700 /opt/easy-rsa/gen_client.sh chown root:root /opt/easy-rsa/gen_client.sh
Generate Client Script MFA Version
If you are using MFA to protect the VPN, change the generate client script to the following:
/opt/easy-rsa/gen_client.sh
#!/bin/bash
# Create new client and files required by new client.
# Usage: ./gen_client.sh [USERNAME]
# Set the MFA_DISABLED env var to any value to use script for non-MFA clients
set -e
test "$#" -eq "1" || { echo "Provide 1 argument (username)"; exit 1; }
# Run build-key
test -e /opt/easy-rsa/build-key || { echo "build-key not found!"; exit 1; }
test -e /opt/easy-rsa/gen_ovpn_profile.sh || { echo "gen_ovpn_profile.sh not found!"; exit 1; }
. /opt/easy-rsa/vars
. /opt/easy-rsa/local_vars
/opt/easy-rsa/build-key ${1}
# Generate .ovpn profile
test -e /opt/easy-rsa/keys/${1}.crt || { echo "client certificate ${1} not found!"; exit 1; }
/opt/easy-rsa/gen_ovpn_profile.sh ${1}
# Register unix user and set a password
useradd -s /bin/nologin "${1}"
if [ -n "${MFA_DISABLED}" ]; then
# Login user needs password
head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 > /opt/easy-rsa/keys/${1}_password.txt
echo "${1}:$(cat /opt/easy-rsa/keys/${1}_password.txt)" | chpasswd
else
# MFA user does not need password
echo "${1}:$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13)" | chpasswd
# Generate MFA client info
MFA_LABEL="Dockstore VPN"
sudo -H -u gauth google-authenticator -t -w3 -e10 -d -r3 -R30 -f -l "${MFA_LABEL}" -s /etc/openvpn/google-authenticator/${1} > /etc/openvpn/google-authenticator/${1}.log
# Text file with MFA backup codes
tail -n10 /etc/openvpn/google-authenticator/${1} > /etc/openvpn/google-authenticator/${1}_backup_codes.txt
# Generate QR image
AUTH_ID="$( head -n1 /etc/openvpn/google-authenticator/${1} )"
qrencode -o /etc/openvpn/google-authenticator/${1}_qr.png -d 300 -s 10 "otpauth://totp/${1}?secret=${AUTH_ID}&issuer=${MFA_LABEL}"
fi
# Zip up all the client's files
/opt/easy-rsa/zip_client_files.sh ${1}
if [ -n "${MFA_DISABLED}" ]; then
rm -f /opt/easy-rsa/keys/${1}_password.txt
fi
Delete Client Script
/opt/easy-rsa/del_client.sh
#!/bin/bash
# Delete a client by deleting their client files and unix user.
# Usage: ./del_client.sh [USERNAME]
set -e
test "$#" -eq "1" || { echo "Provide 1 argument (username"; exit 1; }
# Revoke client files
. /opt/easy-rsa/vars
. /opt/easy-rsa/local_vars
/opt/easy-rsa/revoke-full ${1}
# Delete client openvpn files
rm -f /opt/easy-rsa/keys/${1}.zip
rm -f /opt/easy-rsa/keys/${1}.key
rm -f /opt/easy-rsa/keys/openvpn_${1}.ovpn
# Delete unix user
deluser --remove-home ${1}
echo "User account ${1} has been deleted"
Set ownership and permissions:
chmod 0700 /opt/easy-rsa/del_client.sh chown root:root /opt/easy-rsa/del_client.sh
Delete Client Script MFA Version
/opt/easy-rsa/del_client.sh
#!/bin/bash
# Delete a client by deleting their client files and unix user.
# Usage: ./del_client.sh [USERNAME]
set -e
test "$#" -eq "1" || { echo "Provide 1 argument (username"; exit 1; }
# Revoke client files
. /opt/easy-rsa/vars
. /opt/easy-rsa/local_vars
/opt/easy-rsa/revoke-full ${1}
# Delete client openvpn files
rm -f /opt/easy-rsa/keys/${1}.zip
rm -f /opt/easy-rsa/keys/${1}.key
rm -f /opt/easy-rsa/keys/openvpn_${1}.ovpn
# Delete client MFA files (if they exist)
rm -f /etc/openvpn/google-authenticator/${1}
rm -f /etc/openvpn/google-authenticator/${1}.log
rm -f /etc/openvpn/google-authenticator/${1}_qr.png
rm -f /etc/openvpn/google-authenticator/${1}_backup_codes.txt
# Delete unix user
deluser --remove-home ${1}
echo "User account ${1} has been deleted"
Using the VPN
Process for clients to use the VPN:
- Sign up a client using the
gen_client.shscript. You specify the username with the first argument, and that's it. - The gen client script will produce a zip file with the username of the client. This zip file should be securely transferred to the client.
- Clients unzip the file and use the contents to connect to the OpenVPN server. Use the .ovpn profile to connect, and use the username_password.txt file to log in.
Example: Create a New User
To create a new user:
cd /opt/easy-rsa/ ./gen_client.sh <username>
Example: Create MFA and Non-MFA Users
If you have used the MFA versions of the scripts above, you can create an MFA user like so:
MFA_DISABLED="" ./gen_client.sh <username>
Similarly you can create a non-MFA user like so:
MFA_DISABLED="yes" ./gen_client.sh <username>