set-up for openvpn (server and client) - no easy-rsa required

OpenVPN is a software that can create complex vpn configuration. In this guide I will reduce it's configuration for two use-case: tunnelling internet traffic from a machine to another, create a virtual network between machines in different lan.
Before starting, I usually generate the keys on my home computer instead of remote vps server, as it has more entropy sources and is faster to gather the needed random bits. Then I copy the generated files on the server as needed.

Server set-up

  1. Create the Certification Authority (CA):

    cd /etc/openvpn
    openssl req -new -newkey rsa:4096 -utf8 -sha256 -days 3650  -nodes -x509 -subj "/CN=server-cname" -keyout ca.key -out ca.crt
              

    This command will generate the private key (ca.key) and the public key (ca.crt); highlighted parts can be edited to specify better security settings (key type, key length, algorithm, shorter expiration) and to customize the cname (usually I just go with the machine hostname).
    To simplify the configuration I will use the same certificate for the CA and the server. To make two distinct certs see the client certificate generation section.

  2. Create the shared secret key:

    openvpn --genkey --secret ta.key
            

    This key is used for tls-auth (hardened configuration).

  3. Create the Diffie-Hellman parameters:

    openssl dhparam -out dh.pem 4096
            

    The Diffie-Hellman parameters is used for hardening the configuration (seeds openssl key exchange with a prime and a generator).

  4. Sample server configuration:

    port 1194
    proto udp
    dev tun
    ca ca.crt
    cert ca.crt
    key ca.key
    dh dh.pem
    server 10.8.0.0 255.255.255.0
    topology subnet
    ifconfig-pool-persist ipp.txt
    client-to-client
    keepalive 10 120
    tls-auth ta.key 0
    cipher AES-256-CBC
    persist-key
    persist-tun
    status openvpn-status.log
    log-append openvpn.log
    verb 4
            

    Short and simple configuration for the server, using the previously generated files; place the above directives in a file, I usually go for /etc/openvpn/server.conf.
    client-to-client enable the ability for clients to see each other.
    For a better understanding of the directives check the comments on the example files (in my distribution are found in /usr/share/openvpn/examples) and the man pages linked at the bottom of the page.
    The logging directives are optional, but useful for diagnosing a networking issue. Once the network is up and running they can be commented out. The same apply for the client configuration.

  5. Start the service.
    Check your linux distribution or operating system manual on how to start an openvpn server daemon and load the proper configuration file.
    For reference, in Arch Linux with systemd init the commands are:

    systemctl start openvpn@server # to start the server
    systemctl enable openvpn@server # to persist the start of the service across reboots
            

    The part after the "@" sign is the name of the .conf file without the extension.

Client set-up

  1. Create the client key and sign request:

    cd /etc/openvpn
    openssl req -new -newkey rsa:4096 -utf8 -sha256 -days 3650 -nodes -subj "/CN=client-cname" -keyout client.key -out client.csr
            

    Issue this command on the client, and copy the generated client.csr file on the /etc/openvpn directory on the server. Do not move the client.key file on the server, as the point is to keep the key secret on the machine and exchange only the public key.

  2. Sign the request on the server:

    openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -out client.crt -CAcreateserial
            

    Copy back on the client the generated client.crt file with ca.crt and ta.key.

  3. Sample client configuration (tested on linux client):

    client
    dev tun
    remote server_host 1194
    proto udp
    resolv-retry infinite
    nobind
    persist-key
    persist-tun
    ca ca.crt
    cert client.crt
    key client.key
    tls-auth ta.key 1
    cipher AES-256-CBC
    status openvpn-status.log
    log-append openvpn.log
    verb 4
    redirect-gateway def1
            

    I usually go for /etc/openvpn/client.conf; replace the highlighted part with the server hostname or the server ip address and port and protocol according to the server configuration.
    The redirect-gateway directive add proper routes to forward all the client machine traffic through the vpn tunnel; removing it will still have the virtual network functional.

  4. Start the service.
    Check your linux distribution or operative system manual on how to start and openvpn client daemon and load the proper configuration file.
    Again, as for the server, in Arch Linux with systemd the commands are:

    systemctl start openvpn@client # to start the client service
    systemctl enable openvpn@client # to persist the start of the service across reboots
            

Create .ovpn files

This part explain how to create a .ovpn file, for windows clients. A .ovpn file is a bundle of the configuration with the required keys and certificates.
I usually generate the keys on my linux desktop machine and bundle an .ovpn file if needed for my windows devices.

A typical .ovpn contains:

Windows specific tweaking

Windows client software can be downloaded in the links at the bottom. To start the client service right click on the .ovpn file and select "Start OpenVPN on this config file."
Windows specific tweak is to change the network location from Public to Private. See this tutorial.

An example .ovpn file for windows (bold for the differences with the client configuration seen before):

client
dev tun
remote server_host 1194
proto udp
resolv-retry infinite
nobind
persist-key
persist-tun
ca [inline]
cert [inline]
key [inline]
tls-auth [inline] 1
cipher AES-256-CBC
status openvpn-status.log
log-append openvpn.log
verb 4
key-direction 1
<ca>
[...content of ca.crt...]
</ca>
<cert>
[...content of client.crt...]
</cert>
<key>
[...content of client.key...]
</key>
<tls-auth>
[...content of ta.key...]
</tls-auth>
    

Android specific tweaking

On Android 7.1.1 I can't get working this configuration with the official app OpenVPN Connect in Play Store (I was connected, I got the address and the routes working, but no connectivity); I could get a successful session with OpenVPN for Android, installed via f-droid store.
The android specific tweak remove the [inline] parts of the configuration in the .ovpn file.
Here is how an example .ovpn for android looks like:

client
dev tun
remote server_host 1194
proto udp
resolv-retry infinite
nobind
persist-key
persist-tun
cipher AES-256-CBC
status openvpn-status.log
log-append openvpn.log
verb 4
key-direction 1
<ca>
[...content of ca.crt...]
</ca>
<cert>
[...content of client.crt...]
</cert>
<key>
[...content of client.key...]
</key>
<tls-auth>
[...content of ta.key...]
</tls-auth>
    


Check these scripts for OS differences and .ovpn generation differences between them:

links

OpenVPN HOWTO
OpenVPN Hardening
OpenVPN Man Page
OpenVPN installer downloads (for windows clients)