OpenVPN creates secure point-to-point or site-to-site connections in routed or bridged configurations and remote access facilities. It uses TLS to establish a (mutually) authenticated connection, over which material to derive the symmetric keys for packet encryption is exchanged.
The goal of this project is to provide:
- A pure library implementing the protocol logic, and the OpenVPN config file format to enable interoperabilty and a smooth transition for existing deployments.
- A MirageOS unikernel that acts as an OpenVPN client.
Our goal is not to implement the complete protocol, but rather a small useful subset with modern crypto and the latest key exchange methods, without deprecated or redundant features (embodying the philosophy of nqsb-tls). An initial draft of the network setup is depicted in the diagram below:
Since OpenVPN is not detailed in a protocol specificaton specified, apart from comments in the header files, we have written a specification document in Markdown, still work in progress:
Our OpenVPN configuration parser can be tested with an OpenVPN configuration file:
./_build/default/app/openvpn_config_parser.exe my.openvpn.conf
Included in this repository is a unix program that will connect to an
OpenVPN server, open a tun
interface, and tunnel packets between
the two.
There are two ways to open tun
interfaces:
- Using a dynamically allocated interface (
dev tun
). In order to dynamically allocate atun
interface, the process will need privileges to do so. Either by running the client asroot
or with theCAP_NET_ADMIN
privilege. You would then adddev tun
to your configuration file. - Using a preallocated interface (
dev tunX
) This is the recommend configuration. To allocate such an interface fortun5
you can use this command:You would then addsudo ip tuntap add mode tun user MYUSERNAME name tun5
dev tun5
to your configuration file.
dune build
# Bestowing the binary with CAP_NET_ADMIN if using dynamic tun allocation:
sudo setcap cap_net_admin=ep ./_build/default/app/openvpn_client_lwt.exe
./_build/default/app/openvpn_client_lwt.exe -v MY-CONFIG-FILE.CONF
Our goal has been to implement a usable subset (as found in various real-world configuration files available to us during the implementation phase).
As far as possible we have strived to derive a representation that does not
permit ambiguity or conflicting options to be present in the parsed config.
Consult the type 'a k
declaration in openvpn_config.mli
for more
information.
This does not mean that conflicting options cannot be accepted from an on-disk
configuration file, but rather that such conflicts are explicitly handled in
the parser code (specifically in the resolve_conflict
function).
Here is a list of configuration directives supported by this parser.
NB: These are supported by the parser, not necessarily supported by the unikernel or client executables. TODO document that subset somewhere, and maybe check upon initialization that we understand all the options given?
Directives that call for an external file to be read (or can be
supplied inline with the [inline]
stanza):
auth-nocache
auth-user-pass FILE-PATH
ca FILE-PATH
cert FILE-PATH
connection FILE-PATH
key FILE-PATH
pkcs12 FILE-PATH
tls-auth FILE-PATH
tls-auth FILE-PATH 0
tls-auth FILE-PATH 1
# the 0/1 here is the keydirection: 0 for CN_OUTGOING; 1 for CN_INCOMING
Other supported directives:
nobind
bind
lport PORT
local HOSTNAME
local IP
cipher CIPHER
comp-lzo
dev null
dev tun
dev tap
dev tunNUMBER
dev tapNUMBER
dhcp-option disable-nbt
dhcp-option domain DOMAIN
dhcp-option ntp IP
dhcp-option dns IP
hand-window SECONDS
tran-window SECONDS
ping SECONDS
# Send a control channel ping after SECONDS of inactivity.
# Defaults to 0, which means no pings will be sent.
ping-exit SECONDS
ping-restart SECONDS
mssfix SIZE
link-mtu SIZE
tun-mtu SIZE
float
ifconfig-nowarn
mute-replay-warnings
passtos
persist-key
persist-tun
remote-random
auth-retry nointeract
proto tcp
proto tcp4
proto tcp4-server
proto tcp4-client
proto tcp6
proto tcp6-server
proto tcp6-client
proto udp
proto udp4
proto udp6
pull
client
tls-client
tls-server
remote-cert-tls server
remote-cert-tls client
reneg-bytes BYTES
reneg-pkts PACKET-COUNT
reneg-sec SECONDS
# renegotiate data channel key after N items > sent-items + received-items
replay-window LOW-SECONDS HIGH-SECONDS
connect-retry LOW-SECONDS HIGH-SECONDS
keepalive LOW-SECONDS HIGH-SECONDS
connect-retry-max unlimited
connect-retry-max TIMES
# Configures the maximum amount of times to retry each remote/connection
# before giving up. Defaults to "unlimited".
connect-timeout SECONDS
# a.k.a. --server-poll-timeout SECONDS
# defaults to: connect-timeout 120
resolv-retry infinite
resolv-retry SECONDS
# defaults to: resolv-retry infinite
route-delay N-SECONDS W-SECONDS
# TODO describe these
route NETWORK [NETMASK [GATEWAY [METRIC]]]
# specification of network/netmask/gateway/metric is implemented.
# NETWORK: "net_gateway" or "remote_host" or or "vpn_gateway" or an IP address.
# NETMASK: "default" or CIDR format ("A.B.C.D/PREFIX")
# GATEWAY: "default" or an IP address.
# METRIC: may be "default" or an integer between 0 and 255, inclusively.
route-gateway default
route-gateway dhcp
route-gateway IP
route-metric METRIC
# METRIC: may be "default" or an integer between 0 and 255, inclusively.
tls-timeout SECONDS
# resend control data packets after not receivin an ACK for SECONDS
# TODO should this only apply to UDP?
tls-version-min 1.1
tls-version-min 1.2
tls-version-min 1.3
tls-version-min 1.1 or-highest
tls-version-min 1.2 or-highest
tls-version-min 1.3 or-highest
topology net30
topology p2p
topology subnet
verb LEVEL
The following directives are ignored. Either because they were not deemed useful, or because we have not had a use for them yet:
inactive
ip-win32
rcvbuf
redirect-gateway
remote-cert-ku
rport
sndbuf
socket-flags
up
# string containing shell command to run ?
dh
# TODO path to a PEM file
port
# TODO influences Bind and Remote
socks-proxy
dhcp-option
# DHCP options not listed in "Supported directives" above are ignored.
engine ENGINE-NAME
# select OpenSSL hw crypto backend; we don't use OpenSSL and so this doesn't
# make sense to parse.
allow-recursive-routing
ping-timer-rem
secret FILE
# static key