Windows doesn't actually support it, but MinGW provides it. However, with some versions of
MinGW it doesn't work correctly. Instead, we vsnprintf() to a local buffer and xstrdup() the
results.
Fix combination of Mode = router and DeviceType = tap on Linux.
I believe I have found a bug in tinc on Linux when it is used with
Mode = router and DeviceType = tap. This combination is useful because
it allows global broadcast packets to be used in router mode. However,
when tinc receives a packet in this situation, it needs to make sure its
destination MAC address matches the address of the TAP adapter, which is
typically not the case since the sending node doesn't know the MAC
address of the recipient. Unfortunately, this is not the case on Linux,
which breaks connectivity.
Tinc now strictly limits incoming connections from the same host to 1 per
second. For incoming connections from multiple hosts short bursts of incoming
connections are allowed (by default 100), but on average also only 1 connection
per second is allowed.
When an incoming connection exceeds the limit, tinc will keep the connection in
a tarpit; the connection will be kept open but it is ignored completely. Only
one connection is in a tarpit at a time to limit the number of useless open
connections.
Guus Sliepen [Fri, 31 May 2013 16:50:34 +0000 (18:50 +0200)]
Add the LocalDiscoveryAddress option.
When LocalDiscovery is enabled, tinc normally sends broadcast packets during
PMTU discovery to the broadcast address (255.255.255.255 or ff02::1). This
option lets tinc use a different address.
At the moment only one LocalDiscoveryAddress can be specified.
Guus Sliepen [Thu, 30 May 2013 14:53:16 +0000 (16:53 +0200)]
Better optional argument handling.
Some options can take an optional argument. However, in this case GNU getopt
requires that the optional argument is right next to the option without
whitespace inbetween. If there is whitespace, getopt will treat it as a
non-option argument, but tincd ignored those without a warning. Now tincd will
allow optional arguments with whitespace inbetween, and will give an error when
it encounters any other non-option arguments.
The tinc binary now requires that all options for itself are given before the
command.
Guus Sliepen [Wed, 29 May 2013 16:31:10 +0000 (18:31 +0200)]
Add an invitation protocol.
Using the tinc command, an administrator of an existing VPN can generate
invitations for new nodes. The invitation is a small URL that can easily
be copy&pasted into email or live chat. Another person can have tinc
automatically setup the necessary configuration files and exchange keys
with the server, by only using the invitation URL.
The invitation protocol uses temporary ECDSA keys. The invitation URL
consists of the hostname and port of the server, a hash of the server's
temporary ECDSA key and a cookie. When the client wants to accept an
invitation, it also creates a temporary ECDSA key, connects to the server
and says it wants to accept an invitation. Both sides exchange their
temporary keys. The client verifies that the server's key matches the hash
in the invitation URL. After setting up an SPTPS connection using the
temporary keys, the client gives the cookie to the server. If the cookie
is valid, the server sends the client an invitation file containing the
client's new name and a copy of the server's host config file. If everything
is ok, the client will generate a long-term ECDSA key and send it to the
server, which will add it to a new host config file for the client.
The invitation protocol currently allows multiple host config files to be
send from the server to the client. However, the client filters out
most configuration variables for its own host configuration file. In
particular, it only accepts Name, Mode, Broadcast, ConnectTo, Subnet and
AutoConnect. Also, at the moment no tinc-up script is generated.
When an invitation has succesfully been accepted, the client needs to start
the tinc daemon manually.
Guus Sliepen [Tue, 28 May 2013 11:36:26 +0000 (13:36 +0200)]
Annotate the xalloc functions.
Most important is the annotation of xasprintf() with the format attribute,
which allows the compiler to give warnings about the format string and
arguments.
Guus Sliepen [Sat, 11 May 2013 12:13:23 +0000 (14:13 +0200)]
Don't free ephemeral ECDH keys twice.
ecdh_compute_shared() was changed to immediately delete the ephemeral key after
the shared secret was computed. Therefore, the pointer to the ecdh_t struct
should be zeroed so it won't be freed again when a struct sptps_t is freed.
Guus Sliepen [Sat, 11 May 2013 12:04:39 +0000 (14:04 +0200)]
Fix check for presence of ECDSA public key for outgoing connections.
At this point, c->config_tree may or may not be NULL, but this does not tell us whether it is an
outgoing connection or not. For incoming connections, we do not know the peer's name yet,
so we always have to claim ECDSA support. For outgoing connections, we always need to check
whether we have the peer's ECDSA public key, so that if we don't, we correctly tell the peer that
we want to upgrade.
Guus Sliepen [Wed, 1 May 2013 15:17:22 +0000 (17:17 +0200)]
Use conditional compilation for cryptographic functions.
This gets rid of the rest of the symbolic links. However, as a consequence, the
crypto header files have now moved to src/, and can no longer contain
library-specific declarations. Therefore, cipher_t, digest_t, ecdh_t, ecdsa_t
and rsa_t are now all opaque types, and only pointers to those types can be
used.
Drop packets forwarded via TCP if they are too big (CVE-2013-1428).
Normally all requests sent via the meta connections are checked so that they
cannot be larger than the input buffer. However, when packets are forwarded via
meta connections, they are copied into a packet buffer without checking whether
it fits into it. Since the packet buffer is allocated on the stack, this in
effect allows an authenticated remote node to cause a stack overflow.
Guus Sliepen [Wed, 6 Feb 2013 14:12:53 +0000 (15:12 +0100)]
Check for writability when waiting for a socket to finish connecting.
We were checking only for readability, which is not a problem for normal
connections, since the server side of a connection will always send an ID
request. But when using a proxy, the proxy server doesn't send anything before
the client, so tinc would not see that its connection to the proxy had already
been established.
Guus Sliepen [Thu, 31 Jan 2013 14:58:33 +0000 (15:58 +0100)]
Detect increases in PMTU.
Tinc never restarts PMTU discovery unless a node becomes unreachable. However,
it can be that the PMTU was very low during the initial discovery, but has
increased later. To detect this, tinc now tries to send an extra packet every
PingInterval, with a size slightly higher than the currently known PMTU. If
this packet is succesfully received back, we partially restart PMTU discovery
to find out the new maximum.
Guus Sliepen [Mon, 21 Jan 2013 12:47:46 +0000 (13:47 +0100)]
Fix datagram SPTPS.
Commit dd07c9fc1f37bed8d1f67ffe7b203f61e7914edf broke the reception of datagram
SPTPS packets, by undoing the conversion of the sequence number to host byte
order before comparison. This caused error messages like "Packet is 16777215
seqs in the future, dropped (1)".
Guus Sliepen [Thu, 17 Jan 2013 10:21:18 +0000 (11:21 +0100)]
Fix the minimum spanning tree algorithm.
Tinc uses Kruskal's algorithm to calculate a MST. However, this was broken in
commit 6e80da3370249caa1082c23c3ef55f338d1e9e74. Revert back to the working
algorithm from tinc 1.0.
Guus Sliepen [Wed, 16 Jan 2013 15:31:56 +0000 (16:31 +0100)]
Estimate RTT, bandwidth and packet loss between nodes.
Without adding any extra traffic, we can measure round trip times, estimate the
bandwidth and packet loss between nodes. The RTT and bandwidth can be measured
by timing the MTU probe packets. The RTT is the difference between the time a
burst of MTU probes was sent and when the first reply is received. The
bandwidth can be estimated by multiplying the size of the probe packets by the
time between succesive received probe replies of the same burst. The packet
loss can be estimated for incoming traffic by comparing how many packets have
actually been received to the increase in the sequence numbers.
The estimates are not perfect. Especially bandwidth is difficult to measure,
the only accurate way is to continuously send as much data as possible, but
that is obviously not desirable. The packet loss rate is also almost always
a few percent when sending a lot of data over the VPN via TCP, since TCP
*needs* packet loss to work properly.
Guus Sliepen [Tue, 15 Jan 2013 12:33:16 +0000 (13:33 +0100)]
Count the number of correctly received UDP packets.
Keep track of the number of correct, non-replayed UDP packets that have been
received, regardless of their content. This can be compared to the sequence
number to determine the real packet loss.