This guide will walk you through the process of installing an OpenVPN server on FreeBSD 13 amd64. The server configuration will support both IPv4 and IPv6 connections and handle authentication for remote users.
Execute all commands as the user ‘root’.
Before we begin, make sure the ports tree is updated.
$ portsnap fetch extract
$ portsnap update
Next is to set the server’s local time. You can run the following command manually or install OpenNTPD from ports or pkg. If you just want to get the time sync up and running quickly, then the manual way is preferred:
$ cd /etc
$ mv localtime localtime_DEFAULT
$ ln -s /usr/share/zoneinfo/Asia/Kuala_Lumpur localtime
$ ntpdate -b asia.pool.ntp.org
Now that the server time is configured, let’s start installing OpenVPN:
$ cd /usr/ports/security/openvpn
$ make config

These are the options I use. Let’s finish the installation.
$ make install clean
Next, create and populate the OpenVPN directory:
$ mkdir /usr/local/etc/openvpn
$ cd /usr/local/etc/openvpn # <- Do everything within this directory from now on..
$ cp -R /usr/local/share/easy-rsa .
$ touch openvpn.conf < -- Create an empty server configuration file
$ touch ipp.txt
Open openvpn.conf with your editor of choice and place the following:
local 1.2.3.4 <-- Server public IP
port 1194 <-- Change this if you want to.
proto udp
dev tun
tls-server
ca /usr/local/etc/openvpn/server/ca.crt
cert /usr/local/etc/openvpn/server/server.crt
key /usr/local/etc/openvpn/server/server.key
dh /usr/local/etc/openvpn/server/dh.pem
tls-auth /usr/local/etc/openvpn/server/ta.key 0
topology subnet
server 10.1.99.0 255.255.255.0
server-ipv6 fded:dead:beef:1::/112
client-config-dir /usr/local/etc/openvpn/ccd
tmp-dir /usr/local/etc/openvpn/tmp
ifconfig-pool-persist /usr/local/etc/openvpn/ipp.txt
keepalive 10 60
user nobody
group nobody
persist-key
persist-tun
cipher AES-256-GCM
status /var/log/openvpn/status.log
log-append /var/log/openvpn/server.log
explicit-exit-notify 1
auth sha512
remote-cert-tls client
verb 2
max-clients 10
mute-replay-warnings
auth-user-pass-verify "/usr/local/lib/openvpn/openvpn-auth-file.pl /usr/local/etc/openvpn/clients/passwd" via-env
push "route-ipv6 2000::/3"
push "route-ipv6 fded:dead:beef:1::/112"
push "redirect-gateway ipv6 def1 bypass-dhcp"
push "dhcp-option DNS 1.1.1.1"
push "dhcp-option DNS 8.8.8.8"
script-security 2
username-as-common-name
We are using topology-subnet here for both IPv4 and IPv6. Because I have a single /64 IPv6 block from my provider, I will be using ULA address fd00::/8 for the IPv6 subnet.
Now that the server configuration is done, we move on to creating SSL certificates and keys for the server and client. The server and client will have a cert/key pair. We are also using inline cert/key for the client configuration so that we can just use one cert/key pair instead of creating individual cert/key for each connecting clients.
$ cd easy-rsa
$ ./easyrsa.real init-pki
$ ./easyrsa.real build-ca nopass
$ ./easyrsa.real gen.dh
$ ./easyrsa.real build-server-full server.domain.com nopass
$ ./easyrsa.real build-client-full client nopass
$ `which openvpn` --genkey secret pki/ta.key
$ cd /usr/local/etc/openvpn
Create the server directory and copy these files in:
$ mkdir server
$ cd server
$ cp ../easy-rsa/pki/ca.crt .
$ cp ../easy-rsa/pki/ta.key .
$ cp ../easy-rsa/pki/dh.pem .
$ cp ../easy-rsa/pki/issued/server.crt .
$ cp ../easy-rsa/pki/private/server.key .
The server directory will look like this:
$ ls -l server
total 48
-rw------- 1 root wheel 1168 Aug 2 08:38 ca.crt
-rw------- 1 root wheel 424 Aug 2 08:37 dh.pem
-rw------- 1 root wheel 4571 Aug 2 08:37 server.crt
-rw------- 1 root wheel 1675 Aug 2 08:47 server.key
-rw------- 1 root wheel 636 Aug 2 08:38 ta.key
Almost done. Let’s create the remaining directories:
$ cd /usr/local/etc/openvpn
$ mkdir clients ccd tmp
- clients <– holds the client.ovn configuration and htpasswd file
- ccd <– per-client tunnel configuration
- tmp <– temporary directory
Client configuration – clients/client.ovpn:
client
dev tun
proto udp
remote 1.2.3.4 1194 # Change to the OpenVPN server public IP and port
explicit-exit-notify
resolv-retry infinite
nobind
cipher AES-256-GCM
key-direction 1
auth SHA512
verb 2
persist-key
persist-tun
reneg-sec 0
tls-client
remote-cert-tls serverq
auth-user-pass
pull
fast-io
script-security 2
Next create the user auth file:
$ touch clients/passwd
$ chmod 0640 clients/passwd
$ openssl passwd -apr1
<enter password>
$ echo 'user1:<password>' > clients/passwd
Repeat steps #3 and #5 for each user. Next prepare the tunnel configuration for the user in the ccd directory:
cd ccd
cat <<- _EOF > user1
ifconfig-push 10.1.99.3 255.255.255.0 # Assign IPv4 IP to VPN user
ifconfig-ipv6-push fded:dead:beef:1::3/112 fded:dead:beef:1::1 # Assign IPv6 IP to VPN user
_EOF
The final bits is to include the ca.crt, ta.key, client.crt and client.key into client.ovpn. This is done by using cat(1) command and copy/paste the output at the BOTTOM of client.ovpn. For example:
# OpenVPN configuration lines
# Add certificate and keys BELOW this line..
#
<ca>
encrypted text
</ca>
<tls-auth>
encrypted text
</tls-auth>
<cert>
encrypted text
</cert>
<key>
encrypted text>
</key>
The opening and closing tags are important. Double-check for typo’s and make sure there is no extra spaces.
Next activate the OpenVPN server:
$ sysrc openvpn_enable="YES"
$ service openvpn start
We’ll also need to enable PF with NAT and add some rules into /etc/pf.conf and then enable and start PF. Since we are using topology-subnet this is necessary because we are routing the private subnets out the Public interface:
cat << _EOF > /etc/pf.conf
ext_if='em0'
ext_ip='1.2.3.4'
ext_ip6='2001:db8:11:11::1'
vpn_net='10.1.99.0/24'
vpn_net6='fded:dead:beef:1::/64'
set optimization normal
set block-policy return
set state-policy if-bound
set require-order yes
set skip on lo
scrub in
nat on $ext_if inet from $vpn_net to any -> $ext_ip
nat on $ext_if inet6 from $vpn_net6 to any -> $ext_ip6
antispoof for $ext_if
_EOF
Activate PF, PFLOG and enable IP Forwarding for IPv4 and IPv6.
$ sysrc pf_enable="YES"
$ sysrc pflog_enable="YES"
$ sysrc gateway_enable="YES"
$ sysrc ipv6_gateway_enable="YES"
$ service pflog start
$ service pf start
$ sysctl net.inet.ip.forwarding=1
$ sysctl net.inet6.ip6.forwarding=1
At this point the setup is done and you can start distributing the client.ovpn configuration file to users.
Users can download one of the following OpenVPN client software:
I hope this guide has helped some of you. Good luck.
drl _@ _ bsd_dot_my