Older version (0.10.11) is avaliable in ubuntu repos and it seems to work fine,
but I've built 0.12.1 from sources. This is not neccessary, but might be useful.
Describing building from source is out of scope of these instructions.
apt install ocserv
ocserv has some issues with UDP socket from systemd, so we'll disable it
systemctl mask ocserv.socket
sed -ie 's/^\(.*ocserv.socket\)$/#\1/' /lib/systemd/system/ocserv.service
systemctl daemon-reload
# CHANGE ME!
DOMAIN=yourvpnaddress.example.com
ORG=someorg
CACN=YetAnotherCA
cd /etc/ocserv/
cat >ca.tmpl <<_EOF_
cn = "$CACN"
organization = "$ORG"
serial = 1
expiration_days = 3650
ca
signing_key
cert_signing_key
crl_signing_key
_EOF_
cat >server.tmpl <<_EOF_
cn = "$DOMAIN"
organization = "$ORG"
serial = 2
expiration_days = 3650
signing_key
encryption_key
tls_www_server
dns_name = "$DOMAIN"
_EOF_
certtool --generate-privkey --outfile ca-key.pem
certtool --generate-self-signed --load-privkey ca-key.pem --template ca.tmpl --outfile ca-cert.pem
certtool --generate-privkey --outfile server-key.pem
certtool --generate-certificate --load-privkey server-key.pem --load-ca-certificate ca-cert.pem --load-ca-privkey ca-key.pem --template server.tmpl --outfile server-cert.pem
Change/add/check/ignore following lines to /etc/ocserv/ocserv.conf:
# Use certificates for auth
auth = "certificate"
# Or use username/password auth:
#auth = "plain[passwd=/etc/ocserv/ocpasswd]"
# Ports to use
tcp-port = 443
udp-port = 443
# server's cert and key, should be trusted by clients
server-cert = /etc/ocserv/server-cert.pem
server-key = /etc/ocserv/server-key.pem
# cert of ca issuing client certificates used for auth
ca-cert = /etc/ocserv/ca-cert.pem
# Use common name field in certificate for username
cert-user-oid = 2.5.4.3
# Tunnel device name
device = ocserv_vpns
# IPv4 subnet for clients
ipv4-network = 10.0.1.0
ipv4-netmask = 255.255.255.0
# dns server for clients
dns = 1.1.1.1
I'd cover certificate and password auth. I recommend certificates.
Use following script:
#!/usr/bin/env bash
#!/usr/bin/env bash
set -euo pipefail
user="$1"
if [ -z "${user}" ]; then
echo "Usage: $0 username"
exit 1
fi
if [ -f "${user}.p12" ]; then
echo "${user}.p12 already exists!"
exit 1
fi
# cn is used for username
# don't forget to set cert-user-oid to 2.5.4.3 in ocserv conf
cat >"${user}.tmpl" << _EOF_
cn = "${user}"
unit = "admins"
expiration_days = 365
signing_key
tls_www_client
_EOF_
certtool --generate-privkey \
--outfile "${user}-key.pem"
certtool --generate-certificate \
--load-privkey "${user}-key.pem" \
--load-ca-certificate /etc/ocserv/ca-cert.pem \
--load-ca-privkey /etc/ocserv/ca-key.pem \
--template "${user}.tmpl" \
--outfile "${user}-cert.pem"
certtool --to-p12 \
--load-privkey "${user}-key.pem" \
--load-certificate "${user}-cert.pem" \
--outfile "${user}.p12" \
--p12-name="${user}-key" \
--outder
rm "${user}-key.pem" "${user}-cert.pem" "${user}.tmpl"
echo "${user}.p12 generated"
it would ask for password, which you would need to enter on certificate import, and generate p12 file to import on client
See man ocpasswd
.
To add user "testuser":
ocpasswd -c /etc/ocserv/ocpasswd testuser
I have ufw disabled.
NATting is needed for vpn to work.
# Either enable masquerading
# iptables -t nat -A POSTROUTING -j MASQUERADE
# Or, preferred, SNAT:
# Where 10.0.1.0/24 is subnet used for openconnect (see ipv4-network and ipv4-netmask options)
# And $public_ip is public ipv4 address of server to be used for openconnect
iptables -t nat -A POSTROUTING -s 10.0.1.0/24 ! -d 10.0.1.0/24 -j SNAT --to $public_ip
# you might need to explicitly accept packets on ocserv's ports:
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -p udp --dport 443 -j ACCEPT
You might want to use some iptables-save/restore like thing to apply it on boot.
Uncomment/add following to /etc/sysctl.conf:
net.ipv4.ip_forward=1
run sysctl -p
to apply.
I have OpenVPN on the same server, and with normal setup openvpn clients would be able to access openconnect clients, and vica versa.
So, it might be useful to add following iptables rules:
iptables -A FORWARD -s subnet1 -d subnet2 -j REJECT
iptables -A FORWARD -d subnet1 -s subnet2 -j REJECT
Where subnet1 and subnet2 are ocserv and openvpn subnets (i.e. 10.0.1.0/24 and 10.8.0.0/24) Once again, you might want to make those rules persist