OpenVPN
Installation
OpenVPN should be available for most distributions. Helpful links for other systems may include:
- Tunnelblick - OpenVPN for MacOS 10.3 and later
- TUN/TAP driver for MacOS 10.3 and later
- VTUN - Tunnel suite for various *nix systems (last update 2016-09-18)
PKI
To use OpenVPN in TLS mode, we will need keys an certificates. While we could build our own CA with OpenSSL, the easy-rsa tools may be the better choice here. First, initialize a directory for easy-rsa
and build our own CA. This is best done on a machine not involved with the actual OpenVPN connections.
make-cadir testca && cd testca ./easyrsa init-pki
We no longer have to source the vars
file, but we still may need adjust a few things:
$ grep ^set vars set_var EASYRSA_REQ_COUNTRY "US" set_var EASYRSA_REQ_PROVINCE "California" set_var EASYRSA_REQ_CITY "San Francisco" set_var EASYRSA_REQ_ORG "Foobar Inc." set_var EASYRSA_REQ_EMAIL "ca@example.net" set_var EASYRSA_REQ_OU "Foobar CA" set_var EASYRSA_KEY_SIZE 2048 set_var EASYRSA_REQ_CN "Foobar CA"
Some random seed may be needed[1]
openssl rand -writerand pki/.rnd
Actually create the CA key and certificate:
./easyrsa --batch build-ca nopass
Generate requests for both server and client(s):
./easyrsa gen-req server0 nopass ./easyrsa gen-req client1 nopass ./easyrsa gen-req client2 nopass
Sign all requests and generate certificates:
./easyrsa sign-req server server0
./easyrsa sign-req client client1
./easyrsa sign-req client client2
Generate DH parameters:
./easyrsa gen-dh
Since we will be using tls-auth
later on, all SSL/TLS handshake packets get an additional HMAC signature for integrity verification. For this to work we need a secret key, to be shared with all involved parties:
openvpn --genkey --secret pki/private/ta.key && chmod 0400 pki/private/ta.key
Once all this is done, we should have the following:
$ ls -go pki/ca.crt pki/dh.pem pki/issued/* pki/private/*key
-rw------- 1 1196 Mar 22 22:18 pki/ca.crt
-rw------- 1 424 Mar 22 22:28 pki/dh.pem
-rw------- 1 4592 Mar 22 22:21 pki/issued/server0.crt
-rw------- 1 4485 Mar 22 22:21 pki/issued/client1.crt
-rw------- 1 4485 Mar 22 22:21 pki/issued/client2.crt
-rw------- 1 1675 Mar 22 22:18 pki/private/ca.key # Only necessary for easy-rsa
-r-------- 1 636 Mar 22 22:39 pki/private/ta.key
-rw------- 1 1708 Mar 22 22:20 pki/private/server0.key
-rw------- 1 1708 Mar 22 22:21 pki/private/client1.key
-rw------- 1 1708 Mar 22 22:21 pki/private/client2.key
Copy and transfer all needed files to the server and client, e.g.:
cp -p pki/dh.pem pki/private/ta.key pki/ca.crt pki/issued/server0.crt pki/private/server0.key /etc/openvpn/ scp -p pki/dh.pem pki/private/ta.key pki/ca.crt pki/issued/client1.crt pki/private/client1.key client1:/etc/openvpn/ scp -p pki/dh.pem pki/private/ta.key pki/ca.crt pki/issued/client2.crt pki/private/client2.key client2:/etc/openvpn/
Configuration
TLS-Auth
For TLS-Auth we can use the keys and certificates generated above.
A simple server configuration, for many clients to connect to:
# local 192.168.0.10 # Can be used to listen on a specific interface port 1194 proto udp # Use udp as it provides better protection against # DoS attacks and port scanning than tcp. dev tun # TUN works with IP, TAP works with Ethernet frames. # See Documentation/networking/tuntap.txt tls-server ca ca.crt cert alice.crt key alice.key dh dh2048.pem tls-auth ta.key 0 # Set to 0 on the server and 1 on the clients cipher AES-128-GCM # See --show-ciphers auth SHA256 # See --show-digests server 10.1.0.0 255.255.255.0 # The server will take 10.1.0.1 # ifconfig-pool-persist ipp.txt 0 # Maintain a (readonly) list of client <=> virtual IP addresses keepalive 10 120 # Send keepalive messages every 10 seconds, assume timeout after 120 seconds max-clients 10 # Allow 10 clients to connect concurrently # compress lz4 # Disabled due to security considerations user nobody # Drop root privileges after initialization group nogroup persist-key # After restarting the tunnel, try to avoid accessing files that persist-tun # may no longer be available after dropping privileges # client-to-client # Route client-to-client traffic internally, not over the TUN/TAP interface # Push default route, name servers # push "redirect-gateway def1 bypass-dhcp" # push "dhcp-option DNS 208.67.222.222" # push "dhcp-option DNS 208.67.220.220" status /var/log/openvpn/openvpn-status.log log /var/log/openvpn/server.log # Use log-append to append rather than truncating the logfile verb 3 # Verbosity (0-9) # mute 20 # Silence repeating (20) messages
On the client side:
client dev tun # Same as the server proto udp # Same as the server remote 192.168.0.10 1194 # See local and port on the server tls-client ca ca.crt cert client.crt key client.key tls-auth ta.key 1 # Set to 1 as we are a client cipher AES-128-GCM # See --show-ciphers auth SHA256 # See --show-digests remote-cert-tls server # Verify the remote certificate has been issued with # extendedKeyUsage=serverAuth[2] # ns-cert-type server # Verify that nsCertType is set to server[3] to prevent # MITM attacks # compress lz4 # Disabled due to security considerations nobind # We don't need to bind to a specific port number # resolv-retry infinite # Try indefinitely to resolve the server's hostname user nobody # Drop root privileges after initialization group nogroup persist-key # Try to preserve some state across restarts. persist-tun # dhcp-option DNS 192.168.0.1 # Add a local DNS server, so that clients can be resolved # dhcp-option DOMAIN mydomain.org # Add a local domain name, so that clients can be resolved w/o their FQDN log client.log # Use log-append to append rather than truncating the logfile writepid client.pid # Ignored on Android verb 3 # Verbosity (0-9) # mute 20 # Silence repeating (20) messages # mute-replay-warnings # Silence duplicate packet warnings (for WiFi networks)
Note: while these dhcp-option
[4] directives appear to be useful, they will cause (if used as above) DNS leaks[5][6]. Be sure you know what you're doing before using these options!
Static
For a static host-to-host configuration[7], we'll use a single key file for both server and client:
openvpn --genkey --secret test.key
Server configuration:
dev tun ifconfig 172.16.0.1 172.16.0.2 secret test.key keepalive 10 60 ping-timer-rem persist-tun persist-key cipher AES-128-CBC auth SHA256 engine rdrand ncp-disable verb 3 user nobody group nogroup # daemon
Client configuration:
remote 192.168.0.10 dev tun ifconfig 172.16.0.2 172.16.0.1 secret test.key keepalive 10 60 ping-timer-rem persist-tun persist-key cipher AES-128-CBC auth SHA256 # engine rdrand ncp-disable verb 3 user nobody group nogroup # daemon
Usage
On the server:
openvpn --config /etc/openvpn/server.conf
This will create a tunnel device:
$ ip addr show dev tun0 6: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 100 link/none inet 10.1.0.1 peer 10.1.0.2/32 scope global tun0
On the client:
openvpn --config client.conf
The tunnel device on the client:
$ ifconfig tun0 tun0: flags=8851<UP,POINTOPOINT,RUNNING,SIMPLEX,MULTICAST> mtu 1500 inet 10.1.0.6 --> 10.1.0.5 netmask 0xffffffff open (pid 8584)
Notes:
- The peer address (10.1.0.2 resp. 10.1.0.5) seems to be a virtual address only and cannot be reached via ping(8).
- On a systemd machine, one has to enable and start the correct service:
- systemctl enable openvpn@server
- systemctl start openvpn@server
Links
- How To Set Up an OpenVPN Server on Ubuntu 14.04 (2015-01-28)
- OpenVPN for a single application on Linux (2014-12-17)
References
- ↑ Debian #898470 - openssl says "Can't load /root/.rnd into RNG"
- ↑ OpenSSL: x509
- ↑ Help with TLS handshake errors (2016-02-28)
- ↑ openvpn(8)
- ↑ DNS leak test
- ↑ ipleak.net
- ↑ Static Key Mini-HOWTO