If you have not decided on using OpenConnect yet, I recommend you check out Wireguard instead.
This post explains how to set up an OpenConnect VPN server (OCServ) as a pseudo bridge, which makes VPN clients appear like local ones to the network.
The following is based on the CentOS 7 Proxmox Template but can of course be applied to different CentOS installations.
In this example a home network with a local address range of
192.0.2.0/24 is assumed. The router also functions as a DNS resolver and DHCP server at
192.0.2.1. Local devices are assigned an IP address via DHCP in the range of
192.0.2.100-200. The router acts as a DynDNS client and can be accessed via
home.example.com. The router forwards port 443 to the OpenConnect VM. If port 80 was also forwarded, a valid Let’s Encrypt certificate could be acquired and used. To use that one or any other valid certificate the parameters
server-key need to be set.
The VPN clients are supposed to use an IP from the network
192.0.2.80/28 which allows a range of
192.0.2.81-94 (including the server) and doesn’t conflict with any previous IPs or IP ranges.
At first ocserv needs to be installed and set up to start automatically on system boot.
yum install ocserv -y systemctl enable ocserv
The following configuration changes prepare the system for file-based password-authentication plus timed one-time passwords (TOTP). Other authentication methods include RADIUS, PAM, Kerberos and more. Any option not listed stays with it’s default value.
# /etc/ocserv/ocserv.conf auth = "plain[passwd=/etc/ocserv/passwd,otp=/etc/ocserv/passwd.oath]" # authentication using password-file and otp listen-host-is-dyndns = true # client should resolve hostname on reconnect default-domain = home.example.com ipv4-network = 192.0.2.80/28 # network for the clients, first IP (192.0.2.81) will be used by the server tunnel-all-dns = true # resolve using internal DNS resolver dns = 192.0.2.1 # set router as DNS resolver ping-leases = true # ping IPs before assigning an IP to a client route = default # route all traffic through VPN, equals 0.0.0.0/0 # optional: max-clients = 13 # limit clients to the number of IPs available, 13 in this case
To allow packets to be forwarded by the server and to let the server answer requests to other systems on the same network, IP forwarding and proxy ARP need to be activated.
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf echo "net.ipv4.conf.all.proxy_arp = 1" >> /etc/sysctl.conf sysctl -p # apply wihout rebooting
ocpasswd can be used to generate new login credentials. If OTP is enabled, an empty password can be used.
ocpasswd -c /etc/ocserv/passwd <username>
To generate the TOTP secret, some pseudo-random data needs to be generated and written to the OTP file in a special format.
KEY=$(head -10 /dev/urandom | md5sum | cut -b 1-8) # use 1-30 for more complex keys echo "HOTP/T30 <username> - $KEY" >> /etc/ocserv/passwd.oath
Finally the base32 representation of the key can be found in the verbose output of
-w 5 prints the next five one time passwords to match with the Google Authenticator (or similar) generated passwords.
yum install oathtool -y oathtool --totp --verbose -w 5 $KEY # Base32 secret: ...
An easy way to get this key to a mobile device is to generate the corresponding QR code inside the terminal. Depending on the terminal configuration
ANSIUTF8 might not work. In that case the following types can also be used to display the code:
yum install qrencode -y qrencode -t ANSIUTF8 "otpauth://totp/<some identifier>?secret=<Base32 Secret>"
If all else fails, the base32 secret can still be entered manually. This secret hast to be handeled like a password.
Ready to go
What is left is to start the service and test a successful connection using the OpenConnect client or Cisco’s AnyConnect. An invalid (self-signed) certificate will be presented to the clients (which can be trusted manually) as no certificate has been installed yet.
systemctl start ocserv