I have always had a VPN of some kind at my homelab. Starting with the built-in Sophos VPN when I used Sophos XG. I moved to a Cisco VPN on an 1841 router shortly after just for fun but finally settled on a Windows Server RRAS solution as I had Server 2016 Datacentre and used AD.
But this was plagued with issues and was a pain to manage. the only good part is it was a seamless connection. no masquerading for NAT. it took a lot of system resources like RAM and L2TP over IPsec required 2 ports to be opened.
Needless to say, it worked well but caused issues outside of Windows/Android environment as I found when I got an iPhone.
I am a huge Cisco nerd. my whole network is Cisco their gear has always been solid for me. so I decided to find a solution that used the Cisco AnyConnect. At first, I was looking at a Cisco ASA but they're full of licensing issues I did not feel like chasing around. but then I found ocserv. a Linux package that gives you an AnyConnect compatible VPN server for the low price of £0
So I decided to take a look at it. Installation was very simple with 2 commands in CentOS my goto server OS
yum install epel-release -y
yum install ocserv -y
And there we go. that's it for this blog post... okay it's not that simple we still need to configure it.
For my setup, I will be using the default port 443 over both TCP and UDP which you can open with the firewalld firewall with the following commands
firewall-cmd --add-port=443/tcp --permanent
firewall-cmd --add-port=443/udp --permanent
You will also need to enable masquerade with the following firewalld command
firewall-cmd --permanent --add-masquerade
Now, this guide assumes that you have used letsencrypt before. If you have not then I would recommend reading up on certbot or acme.sh on how to issue certificates as we will need that to make our VPN work and be trusted by devices. I would recommend the DNS validation in Acme.sh as its fully automated and does not need a web server to validate it.
Now its time to edit our config file which is saved in /etc/ocserv/ocserv.conf to keep this guide simple we are going to be using PAM authentication which uses Linux users to authenticate. I would recommend using certificate authentication instead but that's out of the scope of this simple guide.
By default PAM is enabled but without a minium group ID. We will comment out the default and uncomment the line with a min group ID set
#auth = "pam"
auth = "pam[gid-min=1000]"
This will help the security a bit by denying root logins. now set your SSL certificates from letsencrypt
server-cert = /etc/ocserv/ssl.crt
server-key = /etc/ocserv/ssl.key
we also want to create a pool for where IP's will be given out. I chose the 172.16.16.0/24 pool as 192.168.1.x and 10.x.x.x are both in use on my home network and did not want to risk overlapping IP's
ipv4-network = 172.16.16.0/24
dns = 18.104.22.168 dns = 22.214.171.124
now you can save that file and start/enable the service
systemctl enable ocserv
systemctl start ocserv
For clients, you have 2x options. you have the official Cisco AnyConnect client which can be a royal pain but has a nice GUI and a mobile app. or the openconnect client which is made by the same people as ocserv.
I opted for the Cisco AnyConnect client which can be found online with some quick googling. you can often find it on university websites for download. it's available for Windows, Mac, and Linux believe it or not. Simply download and install making sure you only install the core VPN client and none of the web security stuff.
open the client and type in your domain that you setup your SSL certs for. it will ask for a valid username and password for your server.
you can add more by simply creating new users with
And that's all there is to it. A simple VPN setup using the free ocserv software. By far one of the easiest VPN's to setup and while it's not perfect it works well. I would love to do without the masquerading as it results in all requests showing up as coming from my VPN server which isn't a problem for web browsing as it will go through my router and be masqueraded a 2nd time but for accessing local servers it can cause weird issues but I think this a perfect solution for me despite this.