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.
- -p
expect an encrypted key file and read the key password either
from the environment variable VPN_PASSWD or, if this variable is
not set, from standard input.
- -P
expect an encrypted key file and read the key password from
/dev/tty
- -c <config-file>
specifies the pathname of the configuration file to be used, if
not specified /etc/vpnd2.conf is used instead.
- -K <keytype>
generate a new private key and associated public key using real
time privilege, the command line options must be followed by the
base pathname of the new key pair to be generated (.key will be
appended for the private key file and .pub will be appended for
the public key file)), valid key types are brainpoolp512r1,
brainpoolp384r1, brainpoolp256r1, secp521r1, secp384r1 and
secp256r1
- -k <keytype>
generate a new private key and associated public key, the
command line options must be followed by the base pathname of
the new key pair to be generated (.key will be appended for the
private key file and .pub will be appended for the public key
file), valid key types are brainpoolp512r1, brainpoolp384r1,
brainpoolp256r1, secp521r1, secp384r1 and secp256r1
- -d
become a daemon
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
- setuptimeout 1-10
Mandatory. Used by client and server. The maximum time that may
expire between a connection having been established and
authentication being complete. If this time expires without
authentication being complete the connection is aborted.
- listen <proto-of-first-following-table>
*|<listen-address> <port|socket-pathname>
[<option-of-second-following-table>]
Mandatory for server, ignored for client, can be specified
multiple times.
One of the following protocols:
tcp
|
standard tcp |
sctp-oo
|
standard sctp one to one |
sctp-om
|
standard sctp one to many |
udp
|
standard udp |
udplite
|
standard udp lite |
tcp-rtp
|
tcp encapsulated rtp frames that do
contain the vpn messages as payload |
sctp-oo-rtp
|
sctp one to one encapsulated rtp frames
that do contain the vpn messages as payload |
sctp-om-rtp
|
sctp one to many encapsulated rtp frames
that do contain the vpn messages as payload |
udp-rtp
|
udp rtp frames that do contain the vpn
messages as payload |
udplite-rtp
|
udplite rtp frames that do contain the
vpn messages as payload |
unix
|
communication via a unix domain socket in
SOCK_STREAM mode
|
packet-unix
|
communication via a unix domain socket in
SOCK_SEQPACKET mode
|
Note that tcp and sctp are ordered protocols, unix is assumed to
be and must be an ordered protocol, packet-unix is assumed to be
an unordered protocol and udp/udplite are unordered protocols.
Either * as an alias for all addresses or a specific numeric
IPv4 or IPv6 address must be specified, in case of a unix
domain socket * is the only valid value. Furthermore a listening
port number in the range of 1 to 65535 must be specified, in
case of a unix domain socket the socket pathname must be
specified instead of a port number.
One of the following protocol modifying options may be
specified:
small
|
Enable use of a small header which has
only 8 bytes of nonce instead of 12 bytes and which has
only 8 bytes of tag instead of 16 bytes. Should only be
used if bandwidth saving is a premium requirement as
this weakens the security of messages with respect to
tampering and as it causes increased cpu usage. If this
option is set a re-keying interval of no more than 3600
seconds must be specified. |
strip
|
Can only be specified for ordered
protocols. Enable removal of the nonce from the header
as the peer can calculate the expected value.
Recommended as it saves bandwidth without costing
anything. |
small+strip
|
A combination of both of the above
options. Can only be specified for for ordered
protocols.
|
If no option is specified the standard cryptography protocol is
used.
- key <path-of-private-key>
Mandatory for server, ignored for client. The pathname of the
private key of the server which is used for server
identification.
- newpub <path-of-future-public-key>
Optional for server, ignored for client.The pathname of the
future public key of the server to be distributed. Distribution
takes only place if the specified file exists and is readable.
If not specified no distribution takes place.
- revoke <path-of-previous-public-key>
Optional for server, ignored for client. The pathname of the
previous public key of the server to be revoked. Revocation
takes only place if the specified file exists and is readable.
If not specified no revocation takes place.
- setuplimit 512-4095
Mandatory for server, ignored for client. The maximum size of
cryptography control messages. The minimum is 512 if keys of up
to and including 384 bits are in use and 768 if larger keys are
in use. A safe maximum is 976 expecting a 20 byte IPv4 header, a
28 byte SCTP header and a minimum network MTU of 1024 for IPv4
between client and server. Cryptographic control messages must
fit into a single network packet, no matter if ordered or
unordered connections are in use.
- pendinglimit 1-262144
Optional for server, ignored for client. If given the total
amount of connections allowed that are pending but not yet
authenticated. If not specified there is no limit.
- keepalive 15-120
Optional for server and client. The time interval in seconds for
protocol based keep alive messages if there is no vpn traffic.
In case of unordered protocols a message without a payload is
sent. If not specified no keepalive sending and processing
happens. Ignored for helper, packet-helper, unix and packet-unix
protocols in which cases no keepalive sending and processing
happens.
- keysecp enable|disable
Optional for server, ignored for client. Enable SECP keys to be
used for the server private key as well as the client
authentication key. Default is disabled.
- keybrainpool enable|disable
Optional for server, ignored for client. Enable BRAINPOOL keys
to be used for the server private key as well as the client
authentication key. Default is disabled.
- keybitsmin 256-521
Optional for server, ignored for client. The minimum allowed
size of the server private key as well as the client
authentication key in bits. Default is no lower limit if not
specified.
- keybitsmax 256-521
Optional for server, ignored for client. The maximum allowed
size of the server private key as well as the client
authentication key in bits. Default is no upper limit if not
specified.
- x25519 enable|disable
Optional for server, ignored for client. Enable X25519 keys to
be used for ephemeral keys. Default is disabled.
- secp enable|disable
Optional for server, ignored for client. Enable SECP keys to be
used for ephemeral keys. Default is disabled.
- brainpool enable|disable
Optional for server, ignored for client. Enable BRAINPOOL keys
to be used for ephemeral keys. Default is disabled.
- bitsmin 256-521
Optional for server, ignored for client. The minimum allowed
size of ephemeral keys in bits. Default is no lower limit if not
specified.
- bitsmax 256-521
Optional For server, ignored for client. The maximum allowed
size of ephemeral keys in bits. Default is no upper limit if not
specified.
- dosysadm enable|disable
Optional for server and client. Enable CAP_SYS_ADMIN,
CAP_IPC_LOCK, CAP_SYS_NICE, CAP_SYS_RESOURCE, CAP_SYS_TIME and
CAP_KILL rights in addition to the always granted CAP_NET_ADMIN,
CAP_NET_BIND_SERVICE, CAP_NET_RAW and CAP_NET_BROADCAST for the
script being invoked. Use only if really necessary, e.g. when
working with network namespaces. Default is disabled.
- chgcaps enable|disable
Optional for server and client. Enable CAP_SETPCAP rights in
addition to the always granted CAP_NET_ADMIN,
CAP_NET_BIND_SERVICE, CAP_NET_RAW and CAP_NET_BROADCAST for the
script being invoked. Discouraged. Default is disabled.
- setugid enable|disable
Optional for server and client. Enable CAP_SETUID and CAP_SETGID
rights in addition to the always granted CAP_NET_ADMIN,
CAP_NET_BIND_SERVICE, CAP_NET_RAW and CAP_NET_BROADCAST for the
script being invoked. Strongly discouraged. Default is disabled.
- user <name-of-user-to-run-as>
Optional for server and client. Change uid and gid to the uid
and gid values of the specified user as soon as resource and
permission setup is complete. Default is no change of user.
- realtime enable|disable
- Optional for server and client. If enabled use realtime
scheduling in fifo mode and lock all memory from being swapped.
Default is disabled.
- padlimit 0-4095
Optional for server and client. The maximum vpn message size for
padding. Vpn messages are only padded up to this limit. Messages
greater or equal than this limit are not padded. If not
specified there is no limit.
- padding 0-4095
Optional for server and client. The maximum amount of padding
bytes to be appended to a vpn message. The actual amount of
padding is determined by a random value that ranges from 0 to
the specified limit. If this value is not specified no padding
takes place. Note that random padding of vpn messages is a
trade-off between bandwidth consumption and bandwidth costs on
the one hand and obfuscation to make a variety of attacks as
well as deep packet inspection more difficult on the other.
- sendbuf 1024-524288
Optional for server, ignored for client. The socket send buffer
size on bytes. If not specified the system default is used.
- maxseg 512-65535
Optional for server, ignored for client. The maximum segment
size for protocols that support segment configuration. If not
specified the system default is used.
- tcpdefer 1-60
Optional for server, ignored for client. If enabled the kernel
will notify the application of a new tcp connection only if
there is already incoming data pending or if the specified
timeout in seconds expires. Default is disabled which means that
the kernel will notify the application of a new tcp connection
immediately.
- tcpacktimeout 1-120
Optional for server and client. Set the maximum amount of
seconds that transmitted tcp data may remain unacknowledged
before the kernel will forcibly close the connection. Default is
disabled which means that standard kernel imposed timeout
processing takes place.
- fragments enable|disable
Optional for server, ignored for client. Enable fragmentation,
i.e. do not set the DF bit. Default is disabled. The use of this
option is strongly discouraged. Untested.
- minport 1024-65535
Optional for server and client. The minimum local port number
used for UDP/UDPLITE sockets. If not specified the system
default is used.
- maxport 1024-65535
Optional for server and client. The maximum local port number
used for UDP/UDPLITE sockets. Must be at least 16 greater than
the minimum value. If not specified the system default is used.
- altcrypto enable|disable
Optional for server and client. Use Camellia CFB8 instead of AES
CFB8 and use Chacha20/Poly1305 instead of AES GCM if enabled
(must be supported by the underlying cryptographic library).
Note that for private key encrypt/decrypt AES CFB is always
used.
- pidfile <path-of-pidfile>
Optional for server and client. Pathname of the pid file which
must be writable. Default is none in which case no pid file is
written.
[server] configuration options
- connection enable|disable
If disabled this server configuration is disabled, if enabled
this server configuration is enabled. Default is disabled.
- script <path-of-shell-script>
Pathname of a shell script that is invoked when the tun
interface came up, is going down, a peer connection was
established or a peer connection was lost. The first argument is
"up", "down", "connected" or "disconnected" and the second
argument is always the name of the tun interface. Default if not
specified is that no script is invoked.
- auth <path-of-public-key>
Mandatory. Pathname of the public key that is used for
authentication by the client.
- rohc enable|disable
If enabled Robust Header Compression is used for ordered
protocols when sending packets to the peer, if disabled only
uncompressed packets are sent. Default is disabled. Available
only when compiled with rohc support.
- rohccid 16-16383
The amount of CIDs (context identifiers, i.e. connections) the
ROHC library may use. Assume about 2MB memory usage for each
CID. Default if not specified is 256. The value must be
identical for both peers.
- rekey 60-86400
Local rekey interval in seconds. Rekeying only takes place when
the local rekey intervals of both peers expire. Default if not
specified is no re-keying (strongly discouraged).
- rekeyfail enable|disable
If enabled the connection is aborted if the rekey time passes
twice without a re-keying having happened, if disabled this
situation is ignored. Default is disabled.
[client] configuration options
- server <host>
Mandatory. Either a fully qualified host name or an IPv4 or IPv6
address specifying the peer to be connected.
- port 1-65535
Mandatory. The port number of the peer to be connected.
- proto <value-from-table-below>
Mandatory. One of the following protocols:
tcp
|
standard tcp
|
tcp-socks5
|
tcp via a socks 5 server that does name
server lookups (thus e.g. a tor proxy)
|
tcp-proxy
|
tcp via a http proxy that allows connect
requests and does server name lookups
|
sctp-oo
|
standard sctp one to one
|
sctp-om
|
standard sctp one to many
|
udp
|
standard udp
|
udplite
|
standard udp lite
|
tcp-rtp
|
tcp encapsulated rtp frames that do
contain the vpn messages as payload
|
sctp-oo-rtp
|
sctp one to one encapsulated rtp frames
that do contain the vpn messages as payload |
sctp-om-rtp
|
sctp one to many encapsulated rtp frames
that do contain the vpn messages as payload |
udp-rtp
|
udp rtp frames that do contain the vpn
messages as payload |
udplite-rtp
|
udplite rtp frames that do contain the
vpn messages as payload |
helper
|
communication via a helper process that
is connected via a socket pair in SOCK_STREAM mode and
started by vpnd2
|
packet-helper
|
communication via a helper process that
is connected via a socket pair in SOCK_SEQPACKET mode
and started by vpnd2 |
Note that tcp and sctp are ordered protocols, helper is assumed
to be and must be an ordered protocol, packet-helper is assumed
to be an unordered protocol and udp/udplite are unordered
protocols.
- dnstimeout 1-60
Mandatory. The time in seconds a DNS lookup of a host name may
take.
- connecttimeout 1-60
Mandatory. The time in seconds it may take to establish a
network connection to the server for an ordered protocol.
- retrydelay 1-60
Mandatory. The time in seconds to wait after an unsuccessful
connect attempt until the next connect attempt.
- key <path-of-private-key>
Mandatory. The pathname of the private key file used for client
authentication.
- keysecp enable|disable
Enable SECP keys to be used for the semi ephemeral private key
as well as the authentication key. Default is disabled.
- keybrainpool enable|disable
Enable BRAINPOOL keys to be used for the semi ephemeral private
key as well as the authentication key. Default is disabled.
- keybitsmin 256-521
Optional. The minimum allowed size of the semi ephemeral private
key as well as the authentication key in bits. Default is no
lower limit if not specified.
- keybitsmax 256-521
Optional. The maximum allowed size of the semi ephemeral private
key as well as the authentication key in bits. Default is no
upper limit if not specified.
- x25519 enable|disable
Enable X25519 keys to be used for ephemeral keys. Default is
disabled.
- secp enable|disable
Enable SECP keys to be used for ephemeral keys. Default is
disabled.
- brainpool enable|disable
Enable BRAINPOOL keys to be used for ephemeral keys. Default is
disabled.
- bitsmin 256-521
Optional. The minimum allowed size of ephemeral keys in bits.
Default is no lower limit if not specified.
- bitsmax 256-521
Optional. The maximum allowed size of ephemeral keys in bits.
Default is no upper limit if not specified.
- setuplimit 512-4095
Mandatory. The maximum size of cryptography control messages.
The minimum is 512 if keys of up to and including 384 bits are
in use and 768 if larger keys are in use. A safe maximum is 976
expecting a 20 byte IPv4 header, a 28 byte SCTP header and a
minimum network MTU of 1024 for IPv4 between client and server.
Cryptographic control messages must fit into a single network
packet, no matter if ordered or unordered connections are in
use.
- script <path-of-shell-script>
Pathname of a shell script that is invoked when the tun
interface came up, is going down, a peer connection was
established or a peer connection was lost. The first argument is
"up", "down", "connected" or "disconnected" and the second
argument is always the name of the tun interface. Default if not
specified is that no script is invoked.
- auth <path-of-public-key>
[<path-of-other-public-key>]
Mandatory. The pathname(s) of the public key(s) identifying the
server. If only one pathname is given The file must be readable
and the server cannot update its public key automatically. If
two pathnames are given, both must be absolute and writable and
at least one must exist and contain the currently valid public
key of the server. In this case the server can update its public
key automatically.
- rohc enable|disable
Enable or disable RObust Header Compression. Default is
disabled. Ignored for unordered protocols as the library used
for compression does not support reordering or packet loss.
- rohccid 16-16383
The amount of CIDs (context identifiers, i.e. connections) the
ROHC library may use. Assume about 2MB memory usage for each
CID. Default if not specified is 256. The value must be
identical for both peers.
- preferv4 enable|disable
If enabled prefer IPv4 addresses over IPv6 addresses during DNS
lookups, if both address types are available. Default is
disabled which means IPv6 addresses are preferred over IPv4
addresses.
- rekey 60-86400
The local rekey interval in seconds. Rekeying is disabled if not
specified (strongly discouraged). Rekeying takes only place when
the local rekey interval as well as the rekey interval of the
peer are expired.
- sendbuf 1024-524288
The socket send buffer size on bytes. If not specified the
system default is used.
- maxseg 512-65535
The maximum segment size for protocols that support segment
configuration. If not specified the system default is used.
- tcpskipack enable|disable
If enabled skip the ACK of the TCP SYN-SYNACK-ACK sequence and
start directly to send data. Default is the standard
SYN-SYNACK-ACK sequence.
- fragments enable|disable
Enable fragmentation, i.e. do not set the DF bit. Default is
disabled. The use of this option is strongly discouraged.
Untested.
- small enable|disable
Enable use of a small header which has only 8 bytes of nonce
instead of 12 bytes and which has only 8 bytes of tag instead of
16 bytes. Should only be used if bandwidth saving is a premium
requirement as this weakens the security of messages with
respect to tampering and as it causes increased cpu usage. If
this option is set a re-keying interval of no more than 3600
seconds must be specified. Default is disabled.
- strip enable|disable
Can only be specified for ordered protocols. If enabled the
nonce is stripped from the header as the peer can calculate the
expected value. Recommended as it saves bandwidth without
costing anything. Default is disabled.
- paranoia enable|disable
If enabled another re-keying step takes place after client
authentication to separate the actual data encryption from
authentication encryption. Default is disabled.
- noop enable|disable
If enabled send a noop cryptography control message every minute
if there is no vpn traffic . Required e.g. if a socks proxy is
in use to keep the connection alive. Default is disabled. It is
recommended to keep this option disabled when it is not
absolutely necessary to use payload based connection keep alive.
- socks host <host>
The host name of the socks5 proxy server to be used. There is no
default.
- socksport 1-65535
The port of the socks5 proxy server. There is no default.
- proxyhost <host>
The host name of the http proxy server to be used. There is no
default.
- proxy port 1-65535
The port of the http proxy server to be used. There is no
default.
- helpercmd <path-of-peer-connection-utility>
Pathname of the connection helper application to be started when
a connection is to be established. See the tlshelper source code
for an example how such a helper can be used. There is no
default.
- helperconf <per-connection-utility-configuration>
Optional. An argument for the helper application if specified,
e.g. a configuration file pathname. Passed as an argument to the
connection helper application. See the tlshelper source for an
example. There is no default.
- rekeyfail enable|disable
If enabled the connection to the peer is terminated if the local
rekey time is exceeded twice without a re-keying having
happened. Default is disabled.
- connection enable|disable
If disabled this client configuration is disabled, if enabled
this client configuration is enabled. Default if not specified
is disabled.
- sctpsrc enable|disable
- If enabled set the source address of the SCTP socket with
respect to the kernel routing tables. If disabled the default
source address list is used. Default is disabled. Should be
enabled if possible as the amount of SCTP source addresses is
reduced to the single source address required for the
connection. There may be however setups, where this will not
work e.g. due to policy based routing.
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:
- 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.
- Subtract 20 for an IPv4 connection to the server and 40 for an
IPv6 connection to the server (IP header without options)
- Subtract 8 for UDP and UDPLITE, 20 for TCP and 28 for SCTP
(protocol header without options)
- Subtract 2 if RTP encapsulation is in use and the transport is
TCP or SCTP (framing bytes)
- 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
- 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)
- 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.