Open-VPN HowTo

Virtual Private Network

Yves-Gwenael Bourhis <[email protected]>, Mandriva SA, Paris
(C) 2006 Yves-Gwenael Bourhis -- Distribute freely without change -- leave Copyright Note intact


References : Official Open VPN Howto,
Installation et configuration d'OpenVPN2 sur un système GNU/Linux (in French).

There is also a usefull book : "OpenVPN: Building and Integrating Virtual Private Networks " from PACKT Publishing : OpenVPN: Building and Integrating Virtual Private Networks

Table of contents:

Server (PC1) Configuration:
urpmi openvpn
cd /etc/openvpn/
cp -r /usr/share/openvpn/easy-rsa/ /etc/openvpn/
in case of self build rpm, replace the last command from above by:
cp -r /usr/share/doc/openvpn-2.x.x/easy-rsa/ /etc/openvpn/
Then:
cp /usr/share/openvpn/sample-config-files/server.conf /etc/openvpn/
or, in case of self build rpm, replace the last command from above by:
cp /usr/share/doc/openvpn-2.x.x/sample-config-files/server.conf /etc/openvpn/
cd /etc/openvpn/easy-rsa
or, if openvpn version is >= 2.1.x:
cd /etc/openvpn/easy-rsa/1.0/
Now edit the /etc/openvpn/easy-rsa/vars file and set the KEY_COUNTRY, KEY_PROVINCE, KEY_CITY, KEY_ORG, and KEY_EMAIL parameters. Don't leave any of these parameters blank.

Next, initialize the PKI:
source vars
./clean-all
./build-ca
Each time you need to create new keys using easy-rsa, launch the source vars command first.
The ./clean-all command is to be used only the first time, because it deletes the ca and all keys.
Answer to the interactive questions when building the CA and answer yes when prompted to auto sign the certificate.
The above command creates a certificate of authority: /etc/openvpn/easy-rsa/keys/ca.crt and /etc/openvpn/easy-rsa/keys/ca.key.

Then, create a /keys/server.key:
./build-key-server $SERVER
replace $SERVER with the name you want to give to the server certificate.
the command could be:
./build-key-server server

create a client key (for PC2):
./build-key client1 ( or any name other than "client1" )

And create a client key to revoke ( for revocation list ):
./build-key revokekey ( or any name other than "revokekey" )
and run :
./revoke-full revokekey
This builds a /etc/openvpn/easy-rsa/keys/crl.pem file.
ln keys/crl.pem /etc/openvpn/
Beware, create a hardlink as shown above (ln without the -s option).
OpenVPN needs to have the crl.pem file in a world readable directory because OpenVPN executes as nobody:nogroup once launched , and it checks this file on each client connection . You do not wish to set /etc/openvpn/easy-rsa/keys/ world readable.


Build the Diffie-Hellman parameters for the server side:
./build-dh

Then edit the server configuration file and modify the following elements in /etc/openvpn/server.conf this way:
(before change -->> after change)
ca ca.crt -->> ca /etc/openvpn/easy-rsa/keys/ca.crt
cert server.crt -->> cert /etc/openvpn/easy-rsa/keys/server.crt
key server.key -->> key /etc/openvpn/easy-rsa/keys/server.key
dh dhxxx.pem -->> dh /etc/openvpn/easy-rsa/keys/dhxxx.pem
Replace the above /etc/openvpn/easy-rsa by the correct path (i.e /etc/openvpn/easy-rsa/1.0/ for openvpn >= 2.0).

Add the following lines:
# CRL (certificate revocation list) verification
crl-verify /etc/openvpn/crl.pem

And continue with these changes:
;user nobody -->> user nobody
;group nobody -->> group nogroup

Don't forget to delete the : and to change nobody to nogroupin the lines just above.
Save the file.


Now, you may desire to configure the server to push the routes of your lan to the client. If you have the following configuration:
                       _________
                      | OpenVPN |
WAN(IP=81.82.83.84)---| Server  |---LAN(192.168.0.X/255.255.255.0)
                      |_________|
                      
you will configure /etc/openvpn/server.conf as follows:
# Push routes to the client to allow it
# to reach other private subnets behind
# the server.  Remember that these
# private subnets will also need
# to know to route the OpenVPN client
# address pool (10.8.0.0/255.255.255.0)
# back to the OpenVPN server.
push "route 192.168.0.0 255.255.255.0"
If you wish to redirect the gateway threw the vpn uncomment the following line:
push "redirect-gateway"
and you may also wish to push DNS and WINS servers:
# Certain Windows-specific network settings
# can be pushed to clients, such as DNS
# or WINS server addresses.  CAVEAT:
# http://openvpn.net/faq.html#dhcpcaveats
push "dhcp-option DNS 10.8.0.1"
push "dhcp-option WINS 10.8.0.1"

Also, the clients will by default only see the server. If you wish the clients to see each other, uncomment the following line:
client-to-client

Select a cryptographic cipher:
Last but not least, default encryption is cipher BF-CBC (Blowfish 128 bits)
If you wish to use another cryptographic cipher, or more then 128 bits, read the following. Otherwize if the default is OK for you, go to the next section : Configure Shorewall, or to the Client (PC2) Configuration, or back to the Table of contents.

In the following section of /etc/openvpn/server.conf:
# Select a cryptographic cipher.
# This config item must be copied to
# the client config file as well.
;cipher BF-CBC        # Blowfish (default)
;cipher AES-128-CBC   # AES
;cipher DES-EDE3-CBC  # Triple-DES
Leaving everything commented (as is), is identical as uncommenting the following line:
cipher BF-CBC        # Blowfish (default)
The result is the same.
But you may wish to use another type of encryption such as this one:
cipher AES-256-CBC
With the above line, you will the have 256-bit version of AES (Advanced Encryption Standard).
When using another encryption type then the default cipher BF-CBC, you will need to set the same on the client side.

To obtain a list of the different types of encryption supported by openvpn, type the following command:
openvpn --show-ciphers
The displayed result will look like this:
The following ciphers and cipher modes are available
for use with OpenVPN.  Each cipher shown below may be
used as a parameter to the --cipher option.  The default
key size is shown as well as whether or not it can be
changed with the --keysize directive.  Using a CBC mode
is recommended.

DES-CBC 64 bit default key (fixed)
IDEA-CBC 128 bit default key (fixed)
RC2-CBC 128 bit default key (variable)
DES-EDE-CBC 128 bit default key (fixed)
DES-EDE3-CBC 192 bit default key (fixed)
DESX-CBC 192 bit default key (fixed)
BF-CBC 128 bit default key (variable)
RC2-40-CBC 40 bit default key (variable)
CAST5-CBC 128 bit default key (variable)
RC5-CBC 128 bit default key (variable)
RC2-64-CBC 64 bit default key (variable)
AES-128-CBC 128 bit default key (fixed)
AES-192-CBC 192 bit default key (fixed)
AES-256-CBC 256 bit default key (fixed)

if you want to change the default keysize chose a cipher mode with variable key size from the list above, and do as the following example in /etc/openvpn.server.conf:
cipher BF-CBC
keysize 512
But don't forget to set the same in the client configuration file.


Now, start the server:
service openvpn start 
Run : ifconfig
You can see a new interface tun0 : this is the vpn interface

Note on pkcs#11: (you can skip this part if not interested and go to the next part: Configure Shorewall, or go back to the Table of contents).

With the Beta 2.1 of OpenVPN and on a cooker or Mandriva 2007 you can generate pkcs11 certificates.
2006 can work with these certitficates, but not generate them.
To generate pkcs#11 certificates on a cooker or Mandriva 2007 use one of the apropriate openvpn-2.1 rpms here:
RPMs
And then do as follows:
urpmi opensc engine_pkcs11 openct openvpn-2.1_beta14-1.i586.rpm
service openct start

Then :
cp -r /usr/share/doc/openvpn-2.1_beta14/easy-rsa/ /etc/openvpn/
cd /etc/openvpn/easy-rsa/2.0/
In /etc/openvpn/easy-rsa/2.0/ edit openssl.cnf and modify this section:
[ engine_section ]
#
# If you are using PKCS#11
# Install engine_pkcs11 of opensc (www.opensc.org)
# And uncomment the following
# verify that dynamic_path points to the correct location
#
#pkcs11 = pkcs11_section

[ pkcs11_section ]
engine_id = pkcs11
dynamic_path = /usr/lib/engines/engine_pkcs11.so
MODULE_PATH = $ENV::PKCS11_MODULE_PATH
PIN = $ENV::PKCS11_PIN
init = 0
to make it like this:
[ engine_section ]
#
# If you are using PKCS#11
# Install engine_pkcs11 of opensc (www.opensc.org)
# And uncomment the following
# verify that dynamic_path points to the correct location
#
pkcs11 = pkcs11_section

[ pkcs11_section ]
engine_id = pkcs11
#dynamic_path = /usr/lib/engines/engine_pkcs11.so
dynamic_path = /usr/lib/openssl/engines/engine_pkcs11.so
#MODULE_PATH = $ENV::PKCS11_MODULE_PATH
MODULE_PATH = /usr/lib/opensc-pkcs11.so
#PIN = $ENV::PKCS11_PIN
init = 0
Do not forget to comment out pkcs11 = pkcs11_section as shown above.

Now, do as with the normal pki (as described previously), but from /etc/openvpn/easy-rsa/2.0/ instead of /etc/openvpn/easy-rsa/ or /etc/openvpn/easy-rsa/1.0/.
If you wish to create a certificate directly in a usb token, use the --pkcs11 option to the easy-rsa scripts.
But I'd recommend to build certificates localy, and to place the keys in the usb token manualy.
To do so, do as follows:

Initialise the usb token if it has not been done:
pkcs15-init --erase-card -T
pkcs15-init --create-pkcs15 -T
pkcs15-init --store-pin --auth-id 0 --label "YourLabelToTheKey"

To store a CA do as follows:
pkcs15-init --store-certificate keys/ca.crt --authority --label "Mandriva CA" --id "D1:FB:AF:27:EB:B7:34:99:52:20:D2:33:19:C0:E8:69:51:7A:ED:B6" --auth-id 0
In the above example, I decided to use the key's fingerprint as an id, but you can use omit this and automatic default id's will be set (i.e. id "46" is a standard).
The --auth-id 0 is compulsary parameter.
How did I previously read the id of my CA? Well with this command:
openssl x509 -noout -text -in keys/ca.crt | less
Do the same the read the other certificates ids.

To store a public key do as follows:
pkcs15-init --store-certificate keys/client1.crt --label "Client1" --id "DC:EF:ED:19:74:73:DA:44:B6:A4:EE:F5:8B:1F:C5:43:33:2D:1F:A0" --auth-id 0

To store a private key, first store the public key as explained above, and then store the private key as follows:
pkcs15-init --store-private-key keys/client1.key --public-key-label "Client1" --label "Client1 Private Key" --id "DC:EF:ED:19:74:73:DA:44:B6:A4:EE:F5:8B:1F:C5:43:33:2D:1F:A0" --auth-id 0
Important : the --id has to be the exact same as the one you used to store the client1.crt (here:DC:EF:ED:19:74:73:DA:44:B6:A4:EE:F5:8B:1F:C5:43:33:2D:1F:A0)

Now, to access the key with openvpn you can use the following commands:
openvpn --show-pkcs11-slots /usr/lib/opensc-pkcs11.so
openvpn --show-pkcs11-objects /usr/lib/opensc-pkcs11.so 0
Note this part of the output (example from my test key):
You can access this token using
--pkcs11-slot-type "label" --pkcs11-slot "OpenSC Card (PKyves)" options.
And note also the subject for the client1 keyring. which in my example is:
Object
        Type:                   Certificate
        CKA_ID:
                dc ef ed 19 74 73 da 44 b6 a4 ee f5 8b 1f c5 43
                33 2d 1f a0
        CKA_LABEL:              Client1
        subject:                /C=FR/ST=Ile-de-France/L=Paris/O=Mandriva/CN=client1/[email protected]
        serialNumber:           03
        notBefore:              060621144856Z
after having noted these down, I will modifie the client's configuratin file (/etc/openvpn.client.conf) by removing the cert and key lines, and I'll replace them with what follows:
pkcs11-providers /usr/lib/opensc-pkcs11.so
pkcs11-slot-type "label"
pkcs11-slot "OpenSC Card (PKyves)"
pkcs11-id-type subject
pkcs11-id "/C=FR/ST=Ile-de-France/L=Paris/O=Mandriva/CN=client1/[email protected]"
Now, each time the client is started, the PIN key will be asked before connection.

Next, Configure Shorewall or go back to the Table of contents


Client (PC2) Configuration:
urpmi openvpn
cd /etc/openvpn/
cp -r /usr/share/openvpn/sample-config-files/client.conf /etc/openvpn/
in case of self build rpm, replace the last command from above by:
cp -r /usr/share/doc/openvpn-2.x.x/sample-config-files/client.conf /etc/openvpn/

You will need some PKI Certificates from the server.
Go back to PC1(server) and type:
scp /etc/openvpn/easy-rsa/keys/ca.crt user@ip:/etc/openvpn/
scp /etc/openvpn/easy-rsa/keys/client1.crt root@PC2ip:/etc/openvpn/
scp /etc/openvpn/easy-rsa/keys/client1.key root@PC2ip:/etc/openvpn/
Where PC2ip is the client's IP.
Then, Go back to PC2

On PC2 (client), edit the client's /etc/openvpn/client.conf configuration file and bring the following changes:
(before change -->> after change)
remote server -->> remote "server ip" port ( ex: remote 192.168.1.100 1194 )
The default port is 1194

:user nobody -->> user nobody
:group nobody -->> group nogroup

ca ca.crt -->> ca /etc/openvpn/ca.crt
cert client1.crt -->> cert /etc/openvpn/client1.crt
key client1.key -->> key /etc/openvpn/client1.key

:ns-cert-type server -->> ns-cert-type server
save it !

Also, if you do not use the default cipher BF-CBC Blowfish 128 bits encryption, add the same as on the server side.
i.e.:
cipher AES-256-CBC
or like this:
cipher BF-CBC
keysize 512

Now, start the client:
Service openvpn start
Run : ifconfig
You can see a new interface tun0 : this is the vpn interface

Next, Configure Shorewall or go back to the Table of contents


Shorewall Configuration:
If you have shorewall installed and running, you need to allow connections to the vpn.
References : Official Shorewall Open VPN Howto

First, declare the VPN zone in /etc/shorewall/zones as follows if you have shorewall 2.x.x:
#ZONE           DISPLAY           COMMENTS
vpn             VPN               Remote subnet
Or as follows in /etc/shorewall/zones if you have shorewall 3.x.x:
#ZONE   TYPE            OPTIONS         IN                      OUT
#                                       OPTIONS                 OPTIONS
vpn     ipv4

In /etc/shorewall/interfaces add the tun0 interface:
#ZONE      INTERFACE        BROADCAST     OPTIONS
vpn        tun0

and define the following in /etc/shorewall/tunnels :
# TYPE                  ZONE    GATEWAY         GATEWAY
#                                               ZONE
generic:udp:1194        net     0.0.0.0/0       vpn
You can also do the following:
# TYPE                  ZONE    GATEWAY         GATEWAY
#                                               ZONE
openvpn        net     0.0.0.0/0       vpn
But I prefer the generic:udp:1194 syntax because as you can see in /etc/openvpn/server.conf or /etc/openvpn/client.conf, you can easily define any port and protocol (udp or tcp).
With the generic:udp:1194 syntax you easily reflect the server configuration. the openvpn syntax is only for the standard openvpn protocol on udp port 1194.


Now edit /etc/shorewall/policy and add policies as follows:
#SOURCE        DEST          POLICY          LOG LEVEL
loc            vpn           ACCEPT
vpn            loc           ACCEPT
Where loc is the interface to the local network.
If you configure shorewall on a "Standalone" Client, you would rather do the following:
#SOURCE        DEST          POLICY          LOG LEVEL
fw            vpn            ACCEPT
vpn           fw             ACCEPT

Also, on the server side, the clients on the LAN will receive traffic on the LAN(i.e. 192.168.0.0/255.255.255.0) from the VPN(i.e. 10.8.0.0/255.255.255.0).
But, there is no way the LAN clients will guess how to reply to 10.8.0.0/255.255.255.0 unless they have the route to this network.
You have 3 solutions :
Reconfigure the DHCP server of your LAN to add routes to the 10.8.0.0/255.255.255.0 zone, but that's not trivial.
Use a Bridged server, to do so, OpenVPN also needs to be reconfigured, as described in this howto : Open-VPN Ethernet Bridging HowTo.
Or the most simple way is to NAT the VPN zone to your LAN from the server. To do so, edit /etc/shorewall/masq (on the OpenVPN server) as follows:
#INTERFACE              SUBNET          ADDRESS         PROTO   PORT(S) IPSEC
eth0    10.8.0.0/24
This above example is supposing eth0 is on your LAN.

Now, restart Shorewall :
service shorewall restart

Back to the Table of contents

PAM Authentication with Open VPN
References : Using alternative authentication methods with Open VPN

You may which to add PAM authentication to Open VPN.
To do so, add the following in /etc/openvpn/server.conf :
# tell the OpenVPN server to validate the username/password
# entered by clients using the login PAM module
plugin /usr/lib/openvpn/openvpn-auth-pam.so /etc/pam.d/login

Create the users and give each one a password:
useradd client1 -M -s /bin/false
passwd client1
Changing password for user client1.
New UNIX password:
Retype new UNIX password:
passwd: all authentication tokens updated successfully.
The -M option of useradd is to create no /home/client1 directory. The -s /bin/false is to give no shell to the user on the server for security reasons because we only want to have PAM checking the login and password, and that is all.

Restart the server:
service openvpn restart

Then, the client must also prompt for the user login and password. To do so, add the following in /etc/openvpn/client.conf :
# This will direct the OpenVPN client to query the user for a username/password,
# passing it on to the server over the secure TLS channel:
auth-user-pass
Restart the Client:
service openvpn restart
Type your login and password when prompted to do so.

Each time you start the client, you will be prompted for a login and password. So you may wish to launch it manually instead of at boot time.
To see if it is launched at boot type the following :
chkconfig --list openvpn
If you see this :
openvpn         0:off   1:off   2:on    3:on    4:on    5:on    6:off
run :
chkconfig openvpn off
If you see this:
openvpn         0:off   1:off   2:off   3:off   4:off   5:off   6:off
You have nothing to do.
To then launch the client run:
service openvpn start
and stop it with:
service openvpn stop

ALSO, you may have multiple clients, in which case you will want to launch only specific ones manually and the others at boot time.
To do so, run :
chkconfig openvpn on
And change the .conf extension to something else such as .config.
OpenVPN's init script only launches whatever ends by .conf and which is in /etc/openvpn.
To manually launch a client you will need to type this kind of command:
openvpn --daemon --config /etc/openvpn/clientconf.config
Where /etc/openvpn/clientconf.config is the name you gave to the client file but it can be something else.

To stop the client, list on which PID it is runing:
ps ax
25305 ?        S<s    0:00 openvpn --daemon --config /etc/openvpn/clientconf.config
And kill it:
kill 25305


Using username/password authentication as the only form of client authentication

By default, using auth-user-pass-verify or a username/password-checking plugin on the server will enable dual authentication, requiring that both client-certificate and username/password authentication succeed in order for the client to be authenticated.
While it is discouraged from a security perspective, it is also possible to disable the use of client certificates, and force username/password authentication only. On the server:
    client-cert-not-required
Such configurations should usually also set:
    username-as-common-name
which will tell the server to use the username for indexing purposes as it would use the Common Name of a client which was authenticating via a client certificate.
Note that client-cert-not-required will not obviate the need for a server certificate, so a client connecting to a server which uses client-cert-not-required may remove the cert and key directives from the client configuration file, but not the ca directive, because it is necessary for the client to verify the server certificate.

Back to the Table of contents

Build your own rpm from the tarball
References : Mandriva RPM HOWTO and RPM Setup Script (for i586 arch).

If you wish to build rpms from the tarball (i.e. you need to do testing on a development version), first do the following as root on the building machine:
urpmi rpm-build libpam0-devel liblzo2_2-devel
Then, as a normal user and at the root of your home directory (i.e.:/home/$USER/ where $USER is your username on the machine), create a file (i.e. call it Rpmsetup.sh) and paste this script in it : RPM Setup Script (for i586 arch).
Make it executable:
chmod a+x Rpmsetup.sh
And launch it:
./Rpmsetup.sh

Then, download the OpenVPN tarball and the GnuPG signature here : http://openvpn.net/download.html
Import James Yonan's (OpenVPN Author) signature:
gpg --recv-keys 1FBF51F3
Verify the package:
gpg --verify openvpn-2.1_beta14.tar.gz.asc
(replace openvpn-2.1_beta14.tar.gz.asc by the version you are testing)

extract the tarball:
tar -xvzf openvpn-2.1_beta14.tar.gz
modify the openvpn-2.1_beta14/openvpn.spec file and when you see:
%if "%{_vendor}" == "MandrakeSoft"
%{!?without_lzo:BuildRequires: liblzo1-devel >= 1.07}
%{!?without_lzo:Requires:      liblzo1       >= 1.07}
%else
%{!?without_lzo:BuildRequires: lzo-devel >= 1.07}
%{!?without_lzo:Requires:      lzo       >= 1.07}
add requires for the Mandriva distribution this way:
%if "%{_vendor}" == "MandakeSoft"
%{!?without_lzo:BuildRequires: liblzo1-devel >= 1.07}
%{!?without_lzo:Requires:      liblzo1       >= 1.07}
%else
%if "%{_vendor}" == "Mandriva"
%{!?without_lzo:BuildRequires: liblzo2_2-devel >= 2.01}
%{!?without_lzo:Requires:      liblzo2_2       >= 2.01}
%else
%{!?without_lzo:BuildRequires: lzo-devel >= 1.07}
%{!?without_lzo:Requires:      lzo       >= 1.07}
create a new tarball with the modifications:
mv openvpn-2.1_beta14.tar.gz openvpn-2.1_beta14.tar.gz.orig
tar -cvzf openvpn-2.1_beta14.tar.gz openvpn-2.1_beta14
and finally build your rpm (as a user):
rpmbuild -tb openvpn-2.1_beta14.tar.gz
Eventually install (as root) the missing dependencies and relaunch (as a user) the rpmbuild.
You will find your new rpm in /home/$USER/rpm/RPMS/i586/ (i.e. openvpn-2.1_beta14-1.i586.rpm) and now you just need to distribute it to the other machines for testing.


Non Mandriva official RPMs, but self build rpms using the above methode:

WARNING: These RPMs are examples provided by the above method, they are Not Mandriva Official RPMs, there will be no official security updates and no support on these RPMs!

Mandriva 2006:
openvpn-2.1_beta14-1.i586.rpm (GnuPG Signature)
openvpn-2.0.7-1.i586.rpm (GnuPG Signature)
My GnuPG Public Key

Mandriva 2007.0:
Self build rpm using the above methode:
openvpn-2.1_beta14-1.i586.rpm (GnuPG Signature)

Build in the "official Mandriva way" but is still not an "official release" (for testing purpose only):
openvpn-2.1-0.rc1.1mdv2007.0.i586.rpm (GnuPG Signature)
openvpn-2.1-0.rc1.1mdv2007.0.x86_64.rpm (GnuPG Signature)

Mandriva 2007.1 and Cooker:
Since Mandriva 2007.1, simply launch edit-urpm-sources.pl in a terminal as root, add the distribution sources, and activate the "contrib/testing" repository to get newer versions of OpenVPN.

For the following packages, import James Yonan's (OpenVPN Author) signature:
gpg --recv-keys 1FBF51F3
Sources and Windows Installer:
Official OpenVPN Sources


Back to the Table of contents