this is obsolete doc -- see http://doc.nethence.com/ instead

Setting up a OpenVPN server and Windows clients 

on FreeBSD v9 

 

Introduction 

Install the openvpn package (PKGNG), 

pkg install openvpn

 

Setup defaults for certificates 

Setup some defautlts, 

cp -i /etc/ssl/openssl.cnf /etc/ssl/openssl.cnf.dist
vi /etc/ssl/openssl.cnf
dir             = /etc/ssl/CA
default_days    = 3650 # 10 years
default_bits  = 2048
countryName_default             = FR
stateOrProvinceName_default     = IDF
+localityName_default            = Paris
#0.organizationName_default     = Internet Widgits Pty Ltd

 

SSL certification authority 

Create your own CA, 

mkdir -p /etc/ssl/CA/
cd /etc/ssl/CA/
mkdir -p certs/
mkdir -p crls/
mkdir -p newcerts/
mkdir -p private/
touch index.txt
echo 01 > serial
echo 01 > crlnumber
openssl req -nodes -new -x509 -keyout private/cakey.pem -out cacert.pem
#-days 3650

Common Name (e.g. server FQDN or YOUR name) []:cahost.example.com 

Email Address []:email@example.com 

ls -l private/cakey.pem

note. not sure it's mandatory but I would recommend to use the real hostname of the CA server here (with PTR). 

and revocation, 

openssl ca -gencrl -out crls/crl.pem
chown root:nogroup crls/crl.pem
ls -l crls/crl.pem

 

SSL request 

Create a certificate request, 

cd /etc/ssl/CA/certs/

openssl req -nodes -new -keyout ssl.example.com.key -out ssl.example.com.csr 

Common Name (e.g. server FQDN or YOUR name) []: ssl.example.com 

(no extra attributes...)

 

Then sign the certificate request with your own CA, 

openssl ca -out ssl.example.com.crt -in ssl.example.com.csr -policy policy_anything
(check the expire date)
sign and commit

 

Generate Diffie-Hellman parameters for the keys exchange, 

openssl dhparam -out dh2048.pem 2048

 

Check that you've got everything, 

cd /etc/ssl/CA/
ls -l cacert.pem
ls -l private/cakey.pem
cd /etc/ssl/CA/certs/
ls -lkF

there should be, 

dh2048.pem
the crt
the csr
the key

 

Configuration 

Setup OpenVPN, 

mkdir -p /usr/local/etc/openvpn/
cd /etc/
ln -s /usr/local/etc/openvpn
cd /etc/openvpn/
cp /usr/local/share/examples/openvpn/sample-config-files/server.conf openvpn.conf.dist
cp /usr/local/share/examples/openvpn/sample-config-files/server.conf openvpn.conf
chmod u+w openvpn.conf
vi openvpn.conf

e.g. 

local IP_ADDRESS_INTERFACE_LISTEN
port 1194
proto udp

 

# (see "pkcs12" directive in man page).
ca /etc/ssl/CA/cacert.pem
cert /etc/ssl/CA/certs/ssl.nethence.com.crt
key /etc/ssl/CA/certs/ssl.nethence.com.key
crl-verify /etc/ssl/CA/crls/crl.pem
dh /etc/ssl/CA/certs/dh2048.pem

 

dev tun
;dev tap
server 10.8.0.0 255.255.255.0

 

ifconfig-pool-persist ipp.txt
;push "route 192.168.2.0 255.255.255.0"
keepalive 10 120
cipher BF-CBC
comp-lzo
user nobody
group nobody
persist-key
persist-tun
status openvpn-status.log
verb 6
mute 20
;verb 3

Note. eventually enable route push for the VPN client to access the network behind the VPN server (here 192.168.2.0/24). 

 

Enabling the service 

Enable and start the daemon, 

echo 'openvpn_enable="YES"' >> /etc/rc.conf
/usr/local/etc/rc.d/openvpn start

and watch the logs. 

 

Check the vpn interface, 

ifconfig tun0

 

Open the 1194 port for UDP on your listening network device. 

 

Creating client certificates 

Enter the certs (not CA certs) folder and generate a request for a vpn client, 

cd /etc/ssl/certs/
openssl req -nodes -new -keyout sslclient.key -out sslclient.csr

Common Name (e.g. server FQDN or YOUR name) []:public_fqdn_not_mandatory? 

Email Address []:email@example.com 

(you can specify a password here, it won't be asked when connecting anyway, or no extra attributes...)

Note. You don't have to use your client's public FQDN here (unless tls verify is enabled?) http://ip.nethence.com/ 

 

Increment the CA serial, 

cat /etc/ssl/CA/serial
#echo 02 > /etc/ssl/CA/serial
echo 03 > /etc/ssl/CA/serial

 

Sign the request with your own CA, 

  cd /etc/ssl/certs/
openssl ca -out sslclient.crt -in sslclient.csr -policy policy_anything

 

Secure the files a little bit, 

chown root:nogroup /etc/ssl/CA/cacert.pem
chown root:nogroup /etc/ssl/CA/certs/ssl*
chmod 600 /etc/ssl/CA/certs/ssl*.key

 

Preparing the Windows OpenVPN client 

On the VPN server, prepare those files to send them to the client, 

/etc/ssl/CA/certs/sslclient.crt 

/etc/ssl/CA/certs/sslclient.key 

/etc/ssl/CA/cacert.pem

e.g., 

tar czf clientcert.tar.gz sslclient.crt sslclient.key ../cacert.pem
(send this to the client host)

 

Fetch and install [OpenVPN for Windows](https://openvpn.net/index.php/open-source/downloads.html). 

 

Open a command line prompt and proceed, 

cd "C:\Program Files\OpenVPN\config\"

  notepad sslclient.ovpn 

containing, 

client
dev tun
proto udp
remote ssl.example.com 1194
nobind
user nobody
group nobody
persist-key
persist-tun
ca cacert.pem
cert sslclient.crt
key sslclient.key
cipher BF-CBC
comp-lzo
:verb 3
verb 6
mute 20

 

Linking the networks 

Local network on the client side: 192.168.1.0/24 

System's IP on that network: 192.168.1.3 

Local network on the server side: 192.168.2.0/24 

System's IP on that network: 192.168.2.1 

 

For the VPN client to connect to the VPN server's network, the push rule in openvpn.conf is enought (and eventually enable ip fwd on the server -- it's not mandatory to access only the server's IP). Verify the routes on the client, on Windows, 

#route add 192.168.2.0 mask 255.255.255.0 10.8.0.5 metric 1 if 10.8.0.6 DOES NOT WORK MANUALLY
route print

you should have, 

      192.168.2.0    255.255.255.0         10.8.0.5        10.8.0.6       1

then try to ping the server's IP on its local network, 

ping 192.168.2.1

 

For the VPN server to connect to the VPN client's network,  

cd /etc/openvpn/
mkdir -p ccd/
vi openvpn.conf
client-config-dir ccd
route 192.168.1.0 255.255.255.0

  echo "iroute 192.168.1.0 255.255.255.0" > ccd/client 

note. client here corresponds to the common name in the client's certificate, change it accordingly depending on what you entered during the certificate creation. 

note. both route directives are necessary, the server one tells to use tun0 and openvpn, the client one redirects from openvpn to the client. 

restart the daemon and restart the client connection, then try to ping the client local IP from the server, 

ping 192.168.1.3

check the route, on BSD systems, 

netstat -rn -f inet

Ref. http://doc.ubuntu-fr.org/openvpn 

 

Troubleshooting 

If you get this error in the client logs, 

Cannot load certificate file ssl-heg.crt: error:0906D06C:PEM routines:PEM_read_bio:

==> make sure the file is readable and has a non binary content (contains --- CERTIFICATE) 

==> make sure the cert filename points to the right one 

 

If you get this error in the client logs, 

read UDPv4: Connection reset by peer (WSAECONNRESET) (code=10054)

==> make sure firewall is open on the server side 

ref https://forums.openvpn.net/topic7624.html 

 

If you get this error in the clients logs, 

TLS_ERROR: BIO read tls_read_plaintext error: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
TLS Error: TLS object -> incoming plaintext read error
TLS Error: TLS handshake failed

==> you got some restrictive option (probably remote-cert-tls) which indicates that there is something wrong with the certificates, maybe use easy-rsa instead of making it all manually? 

https://forums.openvpn.net/topic10261.html 

 

In any case, if you have to enable IP forwarding on the FreeBSD VPN server, 

sysctl -w net.inet.ip.forwarding=1 (temporarily)

and if you have to enable IP forwarding on Windows XP side, 

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\IPEnableRouter
1

 

References 

Installation d’un serveur VPN sous FreeBSD: http://blog.nicolargo.com/2009/04/installation-dun-serveur-vpn-sous-freebsd.html 

 

Other resources 

http://forum.hardware.fr/hfr/reseauxpersosoho/Reseaux/openvpn-connecte-trafic-sujet_23020_1.htm 

 

TODO 

- try bridge mode (tap)