openvpn-server-pki-setup
OpenVPN-server and PKI setup
- Openvpn is used to create secure ssl/tls vpn tunnels which provies secure access to remote servers and other programs running on those servers
- It largely reduces ssh brute broke attacks by droping he connection request at initial phase
- Create own certificate authority using easy-rsa for issuing certs to clients and servers
- This note is for setting up Openvpn on bastion and access other servers via bastion. Tested on OCI vm's
- 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
-
This setup is tested on ubuntu 22.04, 20.04 and ubuntu based lxc containers
-
Install Openvpn
apt install openvpn -y
- Download
easy-rsafrom 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
- Create pki using easy-rsa
./easyrsa init-pki
- 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"
- Build CA without paspharse
./easyrsa build-ca nopass
./easyrsa gen-dh
- Req key for a Openvpn server without passphrase
./easyrsa gen-req ovpn-server nopass
- Sign the key of Openvon server as a server with CA
./easyrsa sign-req server ovpn-server
- Request a key for a client without passphrase
./easyrsa gen-req example-laptop nopass
- SIgn the key of clients as client with CA.
./easyrsa sign-req client example-laptop
- Run the safe ssl cmd
./easyrsa make-safe-ssl
- Generate the ta.key file using the cmd which is essential to block brute-force attacks
openvpn --genkey secret ta.key
-
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
-
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
- 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
-
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 -
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,
- 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
- 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>
-
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
-
Start the OpenVPN and set to start on boot
systemctl enable --now openvpn
- If everything works well you will see a new bridge adapter in 10.8.0.1/24 segment
ip a
- 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
- https://community.openvpn.net/openvpn/wiki/HOWTO#Linux
- https://github.com/OpenVPN/easy-rsa/blob/master/README.quickstart.md
- https://www.digitalocean.com/community/tutorials/how-to-set-up-and-configure-an-openvpn-server-on-ubuntu-22-04
TODO
- Check easy-rsa make-safe-ssl command
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:
- If you going to use OpenVPN inside LXC conatiner add these lines at the end of the
lxc-container-id.conffile 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
- 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)
- Install openvpn using cmd
apt insatll openvpn -yand place the client.conf file in the/etc/opencpndirectory - Set openvpn to start on boot using cmd
systemctl enable --now openvpn
Windows:
- 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