vpnd2

(c) 2017 Andreas Steinmetz

vpnd2 is a vpn daemon based on tun devices that uses modern cryptographic methods and schemes (ECC including X25519, AES/GCM, ChaCha20/Poly1305, ...) and a variety of transports methods (TCP, SCTP, UDP, UDPLITE, RTP encapsulation). Using a proper processor it is well capable of saturating a 1000BASE-T link. It is designed to make deep packet inspection and blocking hard. If the included transport methods are not sufficient there are provisions for helpers that enable the use of transport methods not included in vpnd2 itself. Included is a TLS helper that allows to tunnel through a standard TLS connection to a web server (requires a supported TLS library to be installed (see tlshelper/Makefile for details) which supports all common proxies. As vpnd2 allows to use TCP over a Socks5 proxy with DNS performed by the proxy it is possible to use vpnd2 in combination with the Tor network. The use of TCP via a http proxy supporting the CONNECT method is possible, too.

Prerequisites

Using older stuff than that listed above might work but probably will not. In this case things are untested anyway. Kernels older than 4.9 are generally untested. If you want this code to run on anything else but linux feel free to start porting.

General

vpnd2 is not easy to configure. If you don't have a certain knowledge about networking, need a many to one solution or a plug and play solution vpnd2 is the wrong tool. On the other hand you can use vpnd2 as a base for a mesh network with flexible routing as well as for a simple point to point connection. With the help of some scripting vpnd2 allows for automated periodic server key replacement without user intervention on both client and server.

vpnd2 is supposed to be run as root (dropping privileges early) but it is not supposed to be installed suid root. Even though the code has some precautions to avoid the worst, installing vpnd2 suid root will be a security problem. If you need users other than root to run vpnd2 use stuff like sudo and don't allow arguments to be passed. Don't you say you haven't been warned.

License

vpnd2 is licensed under the GPL version 2 or any later version of this license. With regards to OpenSSL the usual OpenSSL exemption applies.

Building

Run make or make PROXY=<host>:<port> if you are located behind a http proxy to download all mandatory and optional additional components. Make will stop processing after the download. Have a look at the directory external and compile and install the optional components if you wish to do so. Then adapt the Makefile to your system setup. Run make again and if everything goes well vpnd2 will be compiled. Run make tlshelper if you want to build this utility.

Command Line Parameters

Usage: vpnd2 [-p|-P]  [-d] [-c <config-file>] or vpnd2 [-p|-P] -k|-K <keytype> <key-base-pathname>

The first form invokes regular operation whereas the second form generates a new key file pair.

Signals

vpnd2 terminates if it receives either of SIGINT, SIGHUP, SIGQUIT or SIGTERM.

If vpnd2 receives SIGUSR1 it terminates all server mode connections, re-reads the server key file and then continues to wait for client connections. This only happens if all configuration options required for automatic public key update are properly configured and only if the initial server key read from storage was not encrypted.

If vpnd2 receives SIGUSR2 it terminates all client mode connections, generates new semi ephemeral keys and then restarts the client connections.

Configuration File

A configuration file for vpnd2 has one [global] section and any amount of [client] and [server] sections. [server] sections specify per client specific data that are applied to an incoming connection after the client has authenticated. [client] sections specify all relevant parameters on how a client connects to a server. Note that the options listed below are neither sorted, nor are the defaults sane. You will need to read and configure properly.

[global] configuration options


[server] configuration options

[client] configuration options

Miscellaneous

TUN Interface MTU

One of the worse things to calculate is a proper MTU value for the TUN interface. In any case if optimizations are not relevant one can use any desired value if no UDP or UDPLITE based transport is used. In case UDP or UDPLITE is used as a transport or if an optimized MTU is desired some calculations and probably some tests are necessary:

  1. The path MTU to the vpn server host must be evaluated. Try to use the included mtucheck utility to discover the current path MTU value for a connection to the target host or make an educated guess, e.g. 1500 for a leased line or 1492 for a DSL connection. For IPv6 a minimum MTU of 1280 is mandatory, for IPv4 a minimum MTU of 1024 can be expected. Use the resulting value as your starting value.
  2. Subtract 20 for an IPv4 connection to the server and 40 for an IPv6 connection to the server (IP header without options)
  3. Subtract 8 for UDP and UDPLITE, 20 for TCP and 28 for SCTP (protocol header without options)
  4. Subtract 2 if RTP encapsulation is in use and the transport is TCP or SCTP (framing bytes)
  5. If RTP encapsulation is in use and the up to now resulting value is larger than 1288 set the value to be 1288 (RTP payload limit), if the resulting value is smaller than 1288 subtract 184 from 1288 until the calculated value is smaller than the up to now value, then use the calculated value
  6. Subtract 32 if small and strip are disabled, 20 if one of small or strip is enabled and 12 if both small and strip are enabled (vpnd2 message header size)
  7. Subtract 8 if ROHC is enabled and RTP encapsulation is in use (estimated possible ROHC overhead for initial packets of a connection)
The resulting value is the optimized MTU for the TUN interface.

You will need to do similar calculations if you use e.g. a connection via the tlshelper utility, in this case you have to know that the TLS message header consists of 5 bytes. Additional overhead may apply depending on the cipher used for the TLS connection. You can assume about 16 bytes for this.

Why all this stuff? Let's say you use TCP with an IPv6 connection between client and server and the optimal MTU would be 1424. Now, if you set the MTU to 1425 and do a file transfer the last byte of every message will not fit the external network transfer size. Thus another TCP segment is required which in turn needs to be ACKed which costs a total of 120 additional bytes for the single byte you need to transport. And for UDP as well as UDPLITE and RTP encapsulation the whole message to be transferred will be lost.
For SCTP things are even more interesting when ROHC is enabled. ROHC requires a few additional bytes for the first few packets of a new connection over the vpn. Then it will reduce e.g. the IP header by 13 to 16 bytes . On the other hand SCTP can bundle acknowledgement (SACK) chunks with DATA chunks into one packet if there is sufficient space left with regards to the path MTU. In the best case a SACK chunk requires 16 bytes. Thus it is worth trying to reduce the TUN MTU by another 4. This allows then for the typical initial ROHC overhead and gives the system the chance to bundle SACK chunks with DATA chunks which in turn saves the size of an IP header.
As for the few bytes difference to the actual path MTU limit - these are not lost as the external bandwidth stays the same. The result is that over time more packets are sent so the actual losses are only the headers of the additional packets.

If you blindly use the above calculation for your requirements first make sure that your network fits the above calculation. You most probably will need to adapt things to your situation. If possible use e.g. ping to send packets of the maximum MTU size through the TUN interface and observe the actual vpn traffic with e.g. tcpdump. Then make adjustments as required.

Send Buffer Size

In a perfect world the formula to calculate the send buffer size would be sendbuf=RTT*bandwidth/8 where RTT is the ping roundtrip time in seconds and bandwidth is is the bandwidth in send direction given as bits per second. In practice for very bandwidth limited links like DSL uplinks one needs to multiply the resulting value of the previous formula by at least 4 to get the expected throughput. The problem is, the larger the send buffer size, the worse the latency, the smaller the send buffer size, the worse the throughput. Use tools like netperf and test different settings until you can determine the proper value for your networking situation. And don't forget to modify the TX queue length of the TUN device, this queue adds to the latency.