OpenVPN

From Segfault
Jump to navigation Jump to search

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


References