openvpn-server-pki-setup

OpenVPN-server and PKI setup

  1. Openvpn is used to create secure ssl/tls vpn tunnels which provies secure access to remote servers and other programs running on those servers
  2. It largely reduces ssh brute broke attacks by droping he connection request at initial phase
  3. Create own certificate authority using easy-rsa for issuing certs to clients and servers
  4. This note is for setting up Openvpn on bastion and access other servers via bastion. Tested on OCI vm's
  5. As a best practice the CA is created and Openvpn server is created on different servers but for simplicity ank lack of resource availability we create both on the same server

Openvpn tunnel formation

+------------+---------------+                              +-----------------+-----------+
|            |public ip      |                              |  Public ip of   |           |
|            |of ovpn server |                              |  openvpn client |           |
|            +---------------+------------------------------+-----------------+           |
|                |                                                        |               |
|    Openvpn     |+------------------------------------------------------+|   Openvpn     |
|    server      |                  Openvpn private tunnel                |   client      |
|                |+------------------------------------------------------+|               |
|                |                                                        |               |
|                +----------+------------------------------------+-------+|               |
|                |          |           Public vpn tunnel        |        |               |
|                |          +------------------------------------+        |               |
|                |                                                        |               |
+----------------+                                                        +---------------+	

Openvpn server and pki setup

  1. This setup is tested on ubuntu 22.04, 20.04 and ubuntu based lxc containers

  2. Install Openvpn

apt install openvpn -y
  1. Download easy-rsa from github and place it in /etc/openvpn/ folder
wget https://github.com/OpenVPN/easy-rsa/releases/download/v3.1.7/EasyRSA-3.1.7.tgz -O /tmp/easy-rsa; tar xzvf /tmp/easy-rsa; mv /tmp/EasyRSA-3.1.7 /etc/openvpn/easy-rsa
  1. Create pki using easy-rsa
./easyrsa init-pki
  1. Add the following to the pki/vars file.
set_var EASYRSA_REQ_COUNTRY    "INDIA"
set_var EASYRSA_REQ_PROVINCE   "Tamilnadu"
set_var EASYRSA_REQ_CITY       "Tirupur"
set_var EASYRSA_REQ_ORG        "name"
set_var EASYRSA_REQ_EMAIL      "example@gmail.com"
set_var EASYRSA_REQ_OU         "Example Infra Team"
  1. Build CA without paspharse
./easyrsa build-ca nopass
./easyrsa gen-dh
  1. Req key for a Openvpn server without passphrase
./easyrsa gen-req ovpn-server nopass
  1. Sign the key of Openvon server as a server with CA
./easyrsa sign-req server ovpn-server
  1. Request a key for a client without passphrase
./easyrsa gen-req example-laptop nopass
  1. SIgn the key of clients as client with CA.
./easyrsa sign-req client example-laptop
  1. Run the safe ssl cmd
./easyrsa make-safe-ssl
  1. Generate the ta.key file using the cmd which is essential to block brute-force attacks
openvpn --genkey secret ta.key
  1. Copy the ca.crt, dh.pem ovpn-server.crt and ovpn-server.key from /etc/openvpn-easy-rsa/pki to the /etc/openvpn folder. ovpn-server.key and ovpn-server.crt can be found inside the pki/issued and pki/private folder

  2. Stop the openvpn and create config file for Openvpn server

systemctl stop openvpn

mkdir /etc/openvpn/ccd

cp /etc/openvpn/easy-rsa/pki/{ca.crt,dh.pem,ta.key} /etc/openvpn
cp /etc/openvpn/easy-rsa/pki/issued/ovpn-server.crt /etc/openvpn
cp /etc/openvpn/easy-rsa/pki/private/ovpn-server.key /etc/openvpn

chmod 400 *.key *.crt
# OpenVPN config
# Filename: /etc/openvpn/server.conf
# Authentication is using client certs, user/pass and 2FA.
# Further, certificate common_name and username are pinned, to prevent
# users from sharing certificates.

# Ubuntu systemd runs openvpn with restricted capabilities and cannot run
# client connect/disconnect scripts to send email notifications. To fix:
# in /lib/systemd/system/openvpn@.service uncomment the LimitNPROC line
# and increase the default value from 10 to 100 processes
# Run systemctl daemon-reload and service openvpn restart

port 1194
proto udp
dev tun

dh dh.pem
ca ca.crt
tls-crypt ta.key
cert ovpn-server.crt
key  ovpn-server.key

server 10.8.0.0 255.255.255.0
topology subnet

ifconfig-pool-persist ipp.txt

# Route OCI-SF site-to-site via the tunnel
route 10.10.0.0 255.255.0.0
# Route OCI-HYD site-to-site via the tunnel
route 10.20.0.0 255.255.0.0

# Set this to internal network
#push "route 172.30.0.0 255.255.0.0"
#push "route 10.20.0.0  255.255.0.0"

# Set this if internal DNS is to be used
#push "dhcp-option DNS 10.10.4.51"
#push "dhcp-option DNS 10.10.4.52"

# Permit mutiple clients with same client cert
# duplicate-cn

keepalive 10 120

# Notify the client when the server restarts so it can auto reconnect
explicit-exit-notify 1

cipher AES-256-CBC
data-ciphers 'AES-256-CBC'
data-ciphers-fallback 'AES-256-CBC'

auth SHA256

max-clients 100
user nobody
group nogroup

persist-key
persist-tun

status openvpn-status.log
verb 3

client-config-dir ccd

# Authentiate users with both password and google-authenticator 2FA
# Clients have to enter password and 2fa token in the password prompt
#plugin /usr/lib/x86_64-linux-gnu/openvpn/plugins/openvpn-plugin-auth-pam.so openvpn

# Email root on user connct/disconnect
#script-security 2
#client-connect    /etc/openvpn/client-connect.sh
#client-disconnect /etc/openvpn/client-disconnect.sh

# Ensure username and certificate name are same, users cannot share certs
#auth-user-pass-verify /etc/openvpn/auth-cn-user.sh via-env
  1. Allow ipv4 traffic forwarding
# Filename: /etc/sysctl.d/99-enable-ipv4.conf
# Purpose: enable ipv4 forwarding to access other servers routed via bastion
net.ipv4.ip_forward=1
  1. Note: If you provisioned vm's on OCI disable src/des check on bastion vnic and add a route to the subnet that you want to access via bastion using bastion vnic ip

  2. Make a ipp.txt file which assigns static ip to the openvpn clients and servers

example-laptop,10.8.0.2,
pve,10.8.0.3,
  1. Create a ccd directory where we put the routes for other Openvpn servers
# Oracle Cloud Hyderabad VCN subnet
iroute 10.20.0.0 255.255.0.0
  1. Sample client.conf.template file. Place this file in /etc/openvpn with corresponding values so can be used later when issuing certs to the clients. Windows clients uses a file extension client.ovpn
; Example OpenVPN client config

client

dev tun
proto udp

remote customs.example.in

tls-crypt [inline]

resolv-retry infinite
nobind

persist-key
persist-tun

mute-replay-warnings

; auth-user-pass
auth-nocache
reneg-sec 0

remote-cert-tls server
cipher AES-256-CBC
data-ciphers 'AES-256-CBC'
data-ciphers-fallback 'AES-256-CBC'

auth SHA256

verb 3

<ca>
-----BEGIN CERTIFICATE-----

-----END CERTIFICATE-----
</ca>

<cert>
TODO: client certificate
</cert>

<key>
TODO: client key
</key>

<tls-crypt>
#
# 2048 bit OpenVPN static key
#
-----BEGIN OpenVPN Static key V1-----

-----END OpenVPN Static key V1-----
</tls-crypt>
  1. Create a dns record for the public ip of your bastion for the value you put in the remote session of the client.ovpn or client.conf file

  2. Start the OpenVPN and set to start on boot

systemctl enable --now openvpn
  1. If everything works well you will see a new bridge adapter in 10.8.0.1/24 segment
ip a
  1. Revoke a certificate and add to a certificate revocation list
  ./easyrsa revoke zz-test2
  ./easyrsa gen-crl
  
  cp pki/crl.pem /etc/openvpn
  vim /etc/openvpn/server.conf #add: crl-verify /etc/openvpn/crl.pem
  /etc/init.d/openvpn reload

References

TODO

IP Forwarding and NAT

Enable IP Forwarding

# Sysctl config fragment to enable IP forwarding
# Filename: /etc/sysctl.d/enable-ipforward.conf
# Run `sysctl -p /etc/sysctl.d/enable-forwarding.conf` to take effect
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1

Most likely the OpenVPN environment will not have route set for OpenVPN subnet and this requires the OpenVPN server to NAT traffic headed to the remote LAN.

#!/bin/sh
# Filename: /usr/local/sbin/fw-on.sh
#
# IPTables firewall rules to enable NAT all traffic from
# OpenVPN subnet with LAN IP of this host
# Run `netfilter-persistent save` to auto load the iptables rules on boot

# Network interface to NAT
# Ensure the network interface ex: 'eth0'
LANIF='enp3s0'

# Clear all iptables rules
iptables -t nat -F
iptables -t mangle -F
iptables -F
iptables -X

# NAT OpenVPN clients to local IP
iptables -t nat -A POSTROUTING -s 10.8.0.0/16 -o "${LANIF}" -j MASQUERADE

Start OpenVPN Server on Boot

In /etc/default/openvpn ensure AUTOSTART="all" is set. Then systemctl start openvpn.service and confirm that the openvpn is service is starting with the server.conf config file.

#TODO creating openvpn client users

OpenVPN client setup:

  1. If you going to use OpenVPN inside LXC conatiner add these lines at the end of the lxc-container-id.conf file which can be located in the /etc/pve/lxc/100.conf
# allow /dev/tun access
lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file
  1. Create a openvpn conf file for client. Sample template can be found on this file openvpn-server-and-pki-setup

OpenVPN installation on clients:

OpenVPN client config file naming convention.

machine filename
openvpn server /etc/openvpn/server.conf
openvpn client (linux) /etc/openvpn/client.conf
openvpn client (windows) example-homelab.ovpn

Ubuntu (apt)

  1. Install openvpn using cmd apt insatll openvpn -y and place the client.conf file in the /etc/opencpn directory
  2. Set openvpn to start on boot using cmd systemctl enable --now openvpn

Windows:

  1. Download and install the openvpn windows client from [openvpn.net](OpenVPN Connect Client | Our Official VPN Client | OpenVPN) and import the example-homelab.ovpn file

Refernces: