Import Upstream version 1.1~pre7
This commit is contained in:
parent
26033edb96
commit
2ebbac3278
36 changed files with 1358 additions and 860 deletions
2
COPYING
2
COPYING
|
@ -1,4 +1,4 @@
|
|||
Copyright (C) 1998-2012 Ivo Timmermans, Guus Sliepen and others.
|
||||
Copyright (C) 1998-2013 Ivo Timmermans, Guus Sliepen and others.
|
||||
See the AUTHORS file for a complete list.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
|
|
17
ChangeLog
17
ChangeLog
|
@ -1,3 +1,20 @@
|
|||
Version 1.1pre7 April 22 2013
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Guus Sliepen (12):
|
||||
Use UDP when using sptps_test in datagram mode.
|
||||
Flush output buffers in the tap reader thread on Windows.
|
||||
Better default output file for generated public keys.
|
||||
Allow changing configuration with tincctl without the "config" keyword.
|
||||
Avoid calling time(NULL).
|
||||
Include README.android in the tarballs.
|
||||
Rename tincctl to tinc.
|
||||
Remove references to the config keyword.
|
||||
Describe the SPTPS protocol in the manual.
|
||||
Fix completion of add/del/get/set commands.
|
||||
Drop packets forwarded via TCP if they are too big (CVE-2013-1428).
|
||||
Releasing 1.1pre7.
|
||||
|
||||
Version 1.1pre6 February 20 2013
|
||||
------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ SUBDIRS = m4 src doc gui
|
|||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
EXTRA_DIST = have.h system.h COPYING.README
|
||||
EXTRA_DIST = have.h system.h COPYING.README README.android
|
||||
|
||||
ChangeLog:
|
||||
git log > ChangeLog
|
||||
|
|
|
@ -236,7 +236,7 @@ top_srcdir = @top_srcdir@
|
|||
AUTOMAKE_OPTIONS = gnu
|
||||
SUBDIRS = m4 src doc gui
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
EXTRA_DIST = have.h system.h COPYING.README
|
||||
EXTRA_DIST = have.h system.h COPYING.README README.android
|
||||
all: config.h
|
||||
$(MAKE) $(AM_MAKEFLAGS) all-recursive
|
||||
|
||||
|
|
14
NEWS
14
NEWS
|
@ -1,3 +1,17 @@
|
|||
Version 1.1pre7 April 22 2013
|
||||
|
||||
* Fixed large latencies on Windows.
|
||||
|
||||
* Renamed the tincctl tool to tinc.
|
||||
|
||||
* Simplified changing the configuration using the tinc tool.
|
||||
|
||||
* Added a full description of the ExperimentalProtocol to the manual.
|
||||
|
||||
* Drop packets forwarded via TCP if they are too big (CVE-2013-1428).
|
||||
|
||||
Thanks to Martin Schobert for auditing tinc and reporting the vulnerability.
|
||||
|
||||
Version 1.1pre6 February 20 2013
|
||||
|
||||
* Fixed tincd exitting immediately on Windows.
|
||||
|
|
10
README
10
README
|
@ -1,4 +1,4 @@
|
|||
This is the README file for tinc version 1.1pre6. Installation
|
||||
This is the README file for tinc version 1.1pre7. Installation
|
||||
instructions may be found in the INSTALL file.
|
||||
|
||||
tinc is Copyright (C) 1998-2013 by:
|
||||
|
@ -22,7 +22,7 @@ Please note that this is NOT a stable release. Until version 1.1.0 is released,
|
|||
please use one of the 1.0.x versions if you need a stable version of tinc.
|
||||
|
||||
Although tinc 1.1 will be protocol compatible with tinc 1.0.x, the
|
||||
functionality of the tincctl program may still change, and the control socket
|
||||
functionality of the tinc program may still change, and the control socket
|
||||
protocol is not fixed yet.
|
||||
|
||||
|
||||
|
@ -36,11 +36,11 @@ at your own risk.
|
|||
Compatibility
|
||||
-------------
|
||||
|
||||
Version 1.1pre6 is compatible with 1.0pre8, 1.0 and later, but not with older
|
||||
Version 1.1pre7 is compatible with 1.0pre8, 1.0 and later, but not with older
|
||||
versions of tinc.
|
||||
|
||||
When the ExperimentalProtocol option is used, tinc is still compatible with
|
||||
1.0.X and 1.1pre6 itself, but not with any other 1.1preX version.
|
||||
1.0.X and 1.1pre7 itself, but not with any other 1.1preX version.
|
||||
|
||||
|
||||
Requirements
|
||||
|
@ -88,6 +88,6 @@ Windows environment this means tinc will intall itself as a service, which will
|
|||
restart after reboots. To prevent tinc from detaching or running as a service,
|
||||
use the -D option.
|
||||
|
||||
The status of the VPN can be queried using the "tincctl" tool, which connects
|
||||
The status of the VPN can be queried using the "tinc" command, which connects
|
||||
to a running tinc daemon via a control connection. The same tool also makes it
|
||||
easy to start and stop tinc, and to change its configuration.
|
||||
|
|
20
README.android
Normal file
20
README.android
Normal file
|
@ -0,0 +1,20 @@
|
|||
Quick how-o cross compile tinc for android (done from $HOME/android/):
|
||||
|
||||
- Download android NDK and setup local ARM toolchain:
|
||||
wget http://dl.google.com/android/ndk/android-ndk-r8b-linux-x86.tar.bz2
|
||||
tar xfj android-ndk-r8b-linux-x86.tar.bz2
|
||||
./android-ndk-r8b/build/tools/make-standalone-toolchain.sh --platform=android-5 --install-dir=/tmp/my-android-toolchain
|
||||
|
||||
- Download and cross-compile openSSL for ARM:
|
||||
wget http://www.openssl.org/source/openssl-1.0.1c.tar.gz
|
||||
tar xfz openssl-1.0.1c.tar.gz
|
||||
cd openssl-1.0.1c
|
||||
./Configure dist
|
||||
make CC=/tmp/my-android-toolchain/bin/arm-linux-androideabi-gcc AR="/tmp/my-android-toolchain/bin/arm-linux-androideabi-ar r" RANLIB=/tmp/my-android-toolchain/bin/arm-linux-androideabi-ranlib
|
||||
|
||||
- Clone and cross-compile tinc:
|
||||
git clone git://tinc-vpn.org/tinc
|
||||
cd tinc
|
||||
autoreconf -fsi
|
||||
CC=/tmp/my-android-toolchain/bin/arm-linux-androideabi-gcc ./configure --host=arm-linux --disable-lzo --with-openssl-lib=$HOME/android/openssl-1.0.1c --with-openssl-include=$HOME/android/openssl-1.0.1c/include/
|
||||
make -j5
|
1
THANKS
1
THANKS
|
@ -30,6 +30,7 @@ We would like to thank the following people for their contributions to tinc:
|
|||
* Mark Glines
|
||||
* Markus Goetz
|
||||
* Martin Kihlgren
|
||||
* Martin Schobert
|
||||
* Martin Schürrer
|
||||
* Matias Carrasco
|
||||
* Max Rijevski
|
||||
|
|
2
configure
vendored
2
configure
vendored
|
@ -4095,7 +4095,7 @@ fi
|
|||
|
||||
# Define the identity of the package.
|
||||
PACKAGE=tinc
|
||||
VERSION=1.1pre6
|
||||
VERSION=1.1pre7
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
|
|
|
@ -4,7 +4,7 @@ AC_PREREQ(2.61)
|
|||
AC_INIT
|
||||
AC_CONFIG_SRCDIR([src/tincd.c])
|
||||
AC_GNU_SOURCE
|
||||
AM_INIT_AUTOMAKE(tinc, 1.1pre6)
|
||||
AM_INIT_AUTOMAKE(tinc, 1.1pre7)
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
info_TEXINFOS = tinc.texi
|
||||
|
||||
man_MANS = tincd.8 tincctl.8 tinc.conf.5 tinc-gui.8
|
||||
man_MANS = tincd.8 tinc.8 tinc.conf.5 tinc-gui.8
|
||||
|
||||
EXTRA_DIST = tincinclude.texi.in tincd.8.in tincctl.8.in tinc.conf.5.in tinc-gui.8.in sample-config.tar.gz
|
||||
EXTRA_DIST = tincinclude.texi.in tincd.8.in tinc.8.in tinc.conf.5.in tinc-gui.8.in sample-config.tar.gz
|
||||
|
||||
CLEANFILES = *.html tinc.info tincd.8 tincctl.8 tinc.conf.5 tinc-gui.8 tincinclude.texi
|
||||
CLEANFILES = *.html tinc.info tincd.8 tinc.8 tinc.conf.5 tinc-gui.8 tincinclude.texi
|
||||
|
||||
# Use `ginstall' in the definition of man_MANS to avoid
|
||||
# confusion with the `install' target. The install rule transforms `ginstall'
|
||||
|
@ -25,7 +25,7 @@ texi2html: tinc.texi
|
|||
tincd.8.html: tincd.8
|
||||
w3mman2html $? > $@
|
||||
|
||||
tincctl.8.html: tincctl.8
|
||||
tinc.8.html: tinc.8
|
||||
w3mman2html $? > $@
|
||||
|
||||
tinc-gui.8.html: tinc-gui.8
|
||||
|
@ -43,7 +43,7 @@ substitute = sed \
|
|||
tincd.8: tincd.8.in
|
||||
$(substitute) $? > $@
|
||||
|
||||
tincctl.8: tincctl.8.in
|
||||
tinc.8: tinc.8.in
|
||||
$(substitute) $? > $@
|
||||
|
||||
tinc-gui.8: tinc-gui.8.in
|
||||
|
|
|
@ -224,9 +224,9 @@ top_build_prefix = @top_build_prefix@
|
|||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
info_TEXINFOS = tinc.texi
|
||||
man_MANS = tincd.8 tincctl.8 tinc.conf.5 tinc-gui.8
|
||||
EXTRA_DIST = tincinclude.texi.in tincd.8.in tincctl.8.in tinc.conf.5.in tinc-gui.8.in sample-config.tar.gz
|
||||
CLEANFILES = *.html tinc.info tincd.8 tincctl.8 tinc.conf.5 tinc-gui.8 tincinclude.texi
|
||||
man_MANS = tincd.8 tinc.8 tinc.conf.5 tinc-gui.8
|
||||
EXTRA_DIST = tincinclude.texi.in tincd.8.in tinc.8.in tinc.conf.5.in tinc-gui.8.in sample-config.tar.gz
|
||||
CLEANFILES = *.html tinc.info tincd.8 tinc.8 tinc.conf.5 tinc-gui.8 tincinclude.texi
|
||||
substitute = sed \
|
||||
-e s,'@PACKAGE\@',"$(PACKAGE)",g \
|
||||
-e s,'@VERSION\@',"$(VERSION)",g \
|
||||
|
@ -772,7 +772,7 @@ texi2html: tinc.texi
|
|||
tincd.8.html: tincd.8
|
||||
w3mman2html $? > $@
|
||||
|
||||
tincctl.8.html: tincctl.8
|
||||
tinc.8.html: tinc.8
|
||||
w3mman2html $? > $@
|
||||
|
||||
tinc-gui.8.html: tinc-gui.8
|
||||
|
@ -784,7 +784,7 @@ tinc.conf.5.html: tinc.conf.5
|
|||
tincd.8: tincd.8.in
|
||||
$(substitute) $? > $@
|
||||
|
||||
tincctl.8: tincctl.8.in
|
||||
tinc.8: tinc.8.in
|
||||
$(substitute) $? > $@
|
||||
|
||||
tinc-gui.8: tinc-gui.8.in
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
.\" Manual page created by:
|
||||
.\" Scott Lamb
|
||||
.Sh NAME
|
||||
.Nm tincctl
|
||||
.Nm tinc
|
||||
.Nd tinc VPN control
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
|
@ -51,12 +51,12 @@ Create initial configuration files and RSA and ECDSA keypairs with default lengt
|
|||
If no
|
||||
.Ar name
|
||||
for this node is given, it will be asked for.
|
||||
.It config Oo get Oc Ar variable
|
||||
.It get Ar variable
|
||||
Print the current value of configuration variable
|
||||
.Ar variable .
|
||||
If more than one variable with the same name exists,
|
||||
the value of each of them will be printed on a separate line.
|
||||
.It config Oo set Oc Ar variable Ar value
|
||||
.It set Ar variable Ar value
|
||||
Set configuration variable
|
||||
.Ar variable
|
||||
to the given
|
||||
|
@ -64,9 +64,9 @@ to the given
|
|||
All previously existing configuration variables with the same name are removed.
|
||||
To set a variable for a specific host, use the notation
|
||||
.Ar host Ns Li . Ns Ar variable .
|
||||
.It config add Ar variable Ar value
|
||||
.It add Ar variable Ar value
|
||||
As above, but without removing any previously existing configuration variables.
|
||||
.It config del Ar variable Op Ar value
|
||||
.It del Ar variable Op Ar value
|
||||
Remove configuration variables with the same name and
|
||||
.Ar value .
|
||||
If no
|
||||
|
@ -147,7 +147,7 @@ Sets debug level to
|
|||
.It log Op Ar N
|
||||
Capture log messages from a running tinc daemon.
|
||||
An optional debug level can be given that will be applied only for log messages sent to
|
||||
.Nm tincctl .
|
||||
.Nm tinc .
|
||||
.It retry
|
||||
Forces
|
||||
.Xr tincd 8
|
||||
|
@ -182,19 +182,19 @@ such as
|
|||
.Sh EXAMPLES
|
||||
Examples of some commands:
|
||||
.Bd -literal -offset indent
|
||||
tincctl -n vpn dump graph | circo -Txlib
|
||||
tincctl -n vpn pcap | tcpdump -r -
|
||||
tincctl -n vpn top
|
||||
tinc -n vpn dump graph | circo -Txlib
|
||||
tinc -n vpn pcap | tcpdump -r -
|
||||
tinc -n vpn top
|
||||
.Pp
|
||||
.Ed
|
||||
Example of configuring tinc using
|
||||
.Nm :
|
||||
.Bd -literal -offset indent
|
||||
tincctl -n vpn init foo
|
||||
tincctl -n vpn config Subnet 192.168.1.0/24
|
||||
tincctl -n vpn config bar.Address bar.example.com
|
||||
tincctl -n vpn config ConnectTo bar
|
||||
tincctl -n vpn export | gpg --clearsign | mail -s "My config" vpnmaster@example.com
|
||||
tinc -n vpn init foo
|
||||
tinc -n vpn add Subnet 192.168.1.0/24
|
||||
tinc -n vpn add bar.Address bar.example.com
|
||||
tinc -n vpn add ConnectTo bar
|
||||
tinc -n vpn export | gpg --clearsign | mail -s "My config" vpnmaster@example.com
|
||||
.Ed
|
||||
.Sh TOP
|
||||
The top command connects to a running tinc daemon and repeatedly queries its per-node traffic counters.
|
|
@ -55,15 +55,15 @@ However, you are only allowed to use alphanumerical characters (a-z, A-Z, and 0-
|
|||
.Sh INITIAL CONFIGURATION
|
||||
If you have not configured tinc yet, you can easily create a basic configuration using the following command:
|
||||
.Bd -literal -offset indent
|
||||
.Nm tincctl Fl n Ar NETNAME Li init Ar NAME
|
||||
.Nm tinc Fl n Ar NETNAME Li init Ar NAME
|
||||
.Ed
|
||||
.Pp
|
||||
You can further change the configuration as needed either by manually editing the configuration files,
|
||||
or by using
|
||||
.Xr tincctl 8 .
|
||||
.Xr tinc 8 .
|
||||
.Sh PUBLIC/PRIVATE KEYS
|
||||
The
|
||||
.Nm tincctl Li init
|
||||
.Nm tinc Li init
|
||||
command will have generated both RSA and ECDSA public/private keypairs.
|
||||
The private keys should be stored in files named
|
||||
.Pa rsa_key.priv
|
||||
|
@ -77,7 +77,7 @@ The RSA keys are used for backwards compatibility with tinc version 1.0.
|
|||
If you are upgrading from version 1.0 to 1.1, you can keep the old configuration files,
|
||||
but you will need to create ECDSA keys using the following command:
|
||||
.Bd -literal -offset indent
|
||||
.Nm tincctl Fl n Ar NETNAME Li generate-ecdsa-keys
|
||||
.Nm tinc Fl n Ar NETNAME Li generate-ecdsa-keys
|
||||
.Ed
|
||||
.Sh SERVER CONFIGURATION
|
||||
The server configuration of the daemon is done in the file
|
||||
|
@ -102,7 +102,7 @@ it is recommended to put host specific configuration options in the host configu
|
|||
as this makes it easy to exchange with other nodes.
|
||||
.Pp
|
||||
You can edit the config file manually, but it is recommended that you use
|
||||
.Xr tincctl 8
|
||||
.Xr tinc 8
|
||||
to change configuration variables for you.
|
||||
.Pp
|
||||
Here are all valid variables, listed in alphabetical order.
|
||||
|
@ -279,7 +279,7 @@ When this option is enabled, experimental protocol enhancements will be used.
|
|||
Ephemeral ECDH will be used for key exchanges,
|
||||
and ECDSA will be used instead of RSA for authentication.
|
||||
When enabled, an ECDSA key must have been generated before with
|
||||
.Nm tincctl generate-ecdsa-keys .
|
||||
.Nm tinc generate-ecdsa-keys .
|
||||
The experimental protocol may change at any time,
|
||||
and there is no guarantee that tinc will run stable when it is used.
|
||||
.It Va Forwarding Li = off | internal | kernel Po internal Pc Bq experimental
|
||||
|
@ -482,6 +482,8 @@ Furthermore, specifying
|
|||
.Qq none
|
||||
will turn off packet encryption.
|
||||
It is best to use only those ciphers which support CBC mode.
|
||||
This option has no effect for connections between nodes using
|
||||
.Va ExperimentalProtocol .
|
||||
.It Va ClampMSS Li = yes | no Pq yes
|
||||
This option specifies whether tinc should clamp the maximum segment size (MSS)
|
||||
of TCP packets to the path MTU. This helps in situations where ICMP
|
||||
|
@ -496,6 +498,8 @@ Any digest supported by OpenSSL is recognised.
|
|||
Furthermore, specifying
|
||||
.Qq none
|
||||
will turn off packet authentication.
|
||||
This option has no effect for connections between nodes using
|
||||
.Va ExperimentalProtocol .
|
||||
.It Va IndirectData Li = yes | no Pq no
|
||||
When set to yes, other nodes which do not already have a meta connection to you
|
||||
will not try to establish direct communication with you.
|
||||
|
@ -505,6 +509,8 @@ The length of the message authentication code used to authenticate UDP packets.
|
|||
Can be anything from
|
||||
.Qq 0
|
||||
up to the length of the digest produced by the digest algorithm.
|
||||
This option has no effect for connections between nodes using
|
||||
.Va ExperimentalProtocol .
|
||||
.It Va PMTU Li = Ar mtu Po 1514 Pc
|
||||
This option controls the initial path MTU to this node.
|
||||
.It Va PMTUDiscovery Li = yes | no Po yes Pc
|
||||
|
@ -653,7 +659,7 @@ its connection to the virtual network device.
|
|||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr tincd 8 ,
|
||||
.Xr tincctl 8 ,
|
||||
.Xr tinc 8 ,
|
||||
.Pa http://www.tinc-vpn.org/ ,
|
||||
.Pa http://www.tldp.org/LDP/nag2/ .
|
||||
.Pp
|
||||
|
|
1211
doc/tinc.info
1211
doc/tinc.info
File diff suppressed because it is too large
Load diff
459
doc/tinc.texi
459
doc/tinc.texi
|
@ -30,6 +30,10 @@ permission notice identical to this one.
|
|||
|
||||
@end ifinfo
|
||||
|
||||
@afourpaper
|
||||
@paragraphindent none
|
||||
@finalout
|
||||
|
||||
@titlepage
|
||||
@title tinc Manual
|
||||
@subtitle Setting up a Virtual Private Network with tinc
|
||||
|
@ -462,7 +466,7 @@ default).
|
|||
@subsection libcurses
|
||||
|
||||
@cindex libcurses
|
||||
For the "tincctl top" command, tinc requires a curses library.
|
||||
For the "tinc top" command, tinc requires a curses library.
|
||||
|
||||
If this library is not installed, you wil get an error when running the
|
||||
configure script. You can either install a suitable curses library, or disable
|
||||
|
@ -485,7 +489,7 @@ of this package.
|
|||
@subsection libreadline
|
||||
|
||||
@cindex libreadline
|
||||
For the "tincctl" command's shell functionality, tinc uses the readline library.
|
||||
For the "tinc" command's shell functionality, tinc uses the readline library.
|
||||
|
||||
If this library is not installed, you wil get an error when running the
|
||||
configure script. You can either install a suitable readline library, or
|
||||
|
@ -696,12 +700,12 @@ If you have everything clearly pictured in your mind,
|
|||
proceed in the following order:
|
||||
First, create the initial configuration files and public/private keypairs using the following command:
|
||||
@example
|
||||
tincctl -n @var{NETNAME} init @var{NAME}
|
||||
tinc -n @var{NETNAME} init @var{NAME}
|
||||
@end example
|
||||
Second, use @samp{tincctl -n @var{NETNAME} config ...} to further configure tinc.
|
||||
Finally, export your host configuration file using @samp{tincctl -n @var{NETNAME} export} and send it to those
|
||||
Second, use @samp{tinc -n @var{NETNAME} add ...} to further configure tinc.
|
||||
Finally, export your host configuration file using @samp{tinc -n @var{NETNAME} export} and send it to those
|
||||
people or computers you want tinc to connect to.
|
||||
They should send you their host configuration file back, which you can import using @samp{tincctl -n @var{NETNAME} import}.
|
||||
They should send you their host configuration file back, which you can import using @samp{tinc -n @var{NETNAME} import}.
|
||||
|
||||
These steps are described in the subsections below.
|
||||
|
||||
|
@ -721,7 +725,7 @@ it doesn't even have to be the same on all the nodes of your VPN,
|
|||
but it is recommended that you choose one anyway.
|
||||
|
||||
We will asume you use a netname throughout this document.
|
||||
This means that you call tincctl with the -n argument,
|
||||
This means that you call tinc with the -n argument,
|
||||
which will specify the netname.
|
||||
|
||||
The effect of this option is that tinc will set its configuration
|
||||
|
@ -809,7 +813,7 @@ put host specific configuration options in the host configuration file, as this
|
|||
makes it easy to exchange with other nodes.
|
||||
|
||||
You can edit the config file manually, but it is recommended that you use
|
||||
tincctl to change configuration variables for you.
|
||||
the tinc command to change configuration variables for you.
|
||||
|
||||
In the following two subsections all valid variables are listed in alphabetical order.
|
||||
The default value is given between parentheses,
|
||||
|
@ -1003,7 +1007,7 @@ When this option is enabled, experimental protocol enhancements will be used.
|
|||
Ephemeral ECDH will be used for key exchanges,
|
||||
and ECDSA will be used instead of RSA for authentication.
|
||||
When enabled, an ECDSA key must have been generated before with
|
||||
@samp{tincctl generate-ecdsa-keys}.
|
||||
@samp{tinc generate-ecdsa-keys}.
|
||||
The experimental protocol may change at any time,
|
||||
and there is no guarantee that tinc will run stable when it is used.
|
||||
|
||||
|
@ -1130,7 +1134,7 @@ accidental eavesdropping if you are editting the configuration file.
|
|||
@cindex PrivateKeyFile
|
||||
@item PrivateKeyFile = <@var{path}> (@file{@value{sysconfdir}/tinc/@var{netname}/rsa_key.priv})
|
||||
This is the full path name of the RSA private key file that was
|
||||
generated by @samp{tincctl generate-keys}. It must be a full path, not a
|
||||
generated by @samp{tinc generate-keys}. It must be a full path, not a
|
||||
relative directory.
|
||||
|
||||
@cindex ProcessPriority
|
||||
|
@ -1217,10 +1221,11 @@ If no port is specified, the default Port is used.
|
|||
|
||||
@cindex Cipher
|
||||
@item Cipher = <@var{cipher}> (blowfish)
|
||||
The symmetric cipher algorithm used to encrypt UDP packets.
|
||||
The symmetric cipher algorithm used to encrypt UDP packets using the legacy protocol.
|
||||
Any cipher supported by OpenSSL is recognized.
|
||||
Furthermore, specifying "none" will turn off packet encryption.
|
||||
It is best to use only those ciphers which support CBC mode.
|
||||
This option has no effect for connections using the SPTPS protocol, which always use AES-256-CTR.
|
||||
|
||||
@cindex ClampMSS
|
||||
@item ClampMSS = <yes|no> (yes)
|
||||
|
@ -1236,9 +1241,10 @@ Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib),
|
|||
|
||||
@cindex Digest
|
||||
@item Digest = <@var{digest}> (sha1)
|
||||
The digest algorithm used to authenticate UDP packets.
|
||||
The digest algorithm used to authenticate UDP packets using the legacy protocol.
|
||||
Any digest supported by OpenSSL is recognized.
|
||||
Furthermore, specifying "none" will turn off packet authentication.
|
||||
This option has no effect for connections using the SPTPS protocol, which always use HMAC-SHA-256.
|
||||
|
||||
@cindex IndirectData
|
||||
@item IndirectData = <yes|no> (no)
|
||||
|
@ -1248,9 +1254,10 @@ It is best to leave this option out or set it to no.
|
|||
|
||||
@cindex MACLength
|
||||
@item MACLength = <@var{bytes}> (4)
|
||||
The length of the message authentication code used to authenticate UDP packets.
|
||||
The length of the message authentication code used to authenticate UDP packets using the legacy protocol.
|
||||
Can be anything from 0
|
||||
up to the length of the digest produced by the digest algorithm.
|
||||
This option has no effect for connections using the SPTPS protocol, which never truncate MACs.
|
||||
|
||||
@cindex PMTU
|
||||
@item PMTU = <@var{mtu}> (1514)
|
||||
|
@ -1273,7 +1280,7 @@ This is the RSA public key for this host.
|
|||
@cindex PublicKeyFile
|
||||
@item PublicKeyFile = <@var{path}> [obsolete]
|
||||
This is the full path name of the RSA public key file that was generated
|
||||
by @samp{tincctl generate-keys}. It must be a full path, not a relative
|
||||
by @samp{tinc generate-keys}. It must be a full path, not a relative
|
||||
directory.
|
||||
|
||||
@cindex PEM format
|
||||
|
@ -1421,7 +1428,7 @@ When a subnet becomes (un)reachable, this is set to the subnet.
|
|||
The initial directory structure, configuration files and public/private keypairs are created using the following command:
|
||||
|
||||
@example
|
||||
tincctl -n @var{netname} init @var{name}
|
||||
tinc -n @var{netname} init @var{name}
|
||||
@end example
|
||||
|
||||
(You will need to run this as root, or use "sudo".)
|
||||
|
@ -1449,7 +1456,7 @@ and you yourself have a smaller portion of that range: 192.168.2.0/24.
|
|||
Then you should run the following command:
|
||||
|
||||
@example
|
||||
tincctl -n @var{netname} config add subnet 192.168.2.0/24
|
||||
tinc -n @var{netname} add subnet 192.168.2.0/24
|
||||
@end example
|
||||
|
||||
This will add a Subnet statement to your host configuration file.
|
||||
|
@ -1465,18 +1472,18 @@ If you will use more than one address range, you can add more Subnets.
|
|||
For example, if you also use the IPv6 subnet fec0:0:0:2::/64, you can add it as well:
|
||||
|
||||
@example
|
||||
tincctl -n @var{netname} config add subnet fec0:0:0:2::/24
|
||||
tinc -n @var{netname} add subnet fec0:0:0:2::/24
|
||||
@end example
|
||||
|
||||
This will add another line to the file @file{hosts/@var{name}}.
|
||||
If you make a mistake, you can undo it by simply using @samp{config del} instead of @samp{config add}.
|
||||
If you make a mistake, you can undo it by simply using @samp{del} instead of @samp{add}.
|
||||
|
||||
If you want other tinc daemons to create meta-connections to your daemon,
|
||||
you should add your public IP address or hostname to your host configuration file.
|
||||
For example, if your hostname is foo.example.org, run:
|
||||
|
||||
@example
|
||||
tincctl -n @var{netname} config add address foo.example.org
|
||||
tinc -n @var{netname} add address foo.example.org
|
||||
@end example
|
||||
|
||||
If you already know to which daemons your daemon should make meta-connections,
|
||||
|
@ -1484,7 +1491,7 @@ you should configure that now as well.
|
|||
Suppose you want to connect to a daemon named "bar", run:
|
||||
|
||||
@example
|
||||
tincctl -n @var{netname} config add connectto bar
|
||||
tinc -n @var{netname} add connectto bar
|
||||
@end example
|
||||
|
||||
Note that you specify the Name of the other daemon here, not an IP address or hostname!
|
||||
|
@ -1501,7 +1508,7 @@ If you are on a UNIX platform, you can easily send an email containing the neces
|
|||
(assuming the owner of bar has the email address bar@@example.org):
|
||||
|
||||
@example
|
||||
tincctl -n @var{netname} export | mail -s "My config file" bar@@example.org
|
||||
tinc -n @var{netname} export | mail -s "My config file" bar@@example.org
|
||||
@end example
|
||||
|
||||
If the owner of bar does the same to send his host configuration file to you,
|
||||
|
@ -1509,16 +1516,16 @@ you can probably pipe his email through the following command,
|
|||
or you can just start this command in a terminal and copy&paste the email:
|
||||
|
||||
@example
|
||||
tincctl -n @var{netname} import
|
||||
tinc -n @var{netname} import
|
||||
@end example
|
||||
|
||||
If you are the owner of bar yourself, and you have SSH access to that computer,
|
||||
you can also swap the host configuration files using the following command:
|
||||
|
||||
@example
|
||||
tincctl -n @var{netname} export \
|
||||
| ssh bar.example.org tincctl -n @var{netname} exchange \
|
||||
| tincctl -n @var{netname} import
|
||||
tinc -n @var{netname} export \
|
||||
| ssh bar.example.org tinc -n @var{netname} exchange \
|
||||
| tinc -n @var{netname} import
|
||||
@end example
|
||||
|
||||
You should repeat this for all nodes you ConnectTo, or which ConnectTo you.
|
||||
|
@ -1551,7 +1558,7 @@ When tinc starts, this script will be executed. When tinc exits, it will execute
|
|||
You can manually open the script in an editor, or use the following command:
|
||||
|
||||
@example
|
||||
tincctl -n @var{netname} edit tinc-up
|
||||
tinc -n @var{netname} edit tinc-up
|
||||
@end example
|
||||
|
||||
An example @file{tinc-up} script, that would be appropriate for the scenario in the previous section, is:
|
||||
|
@ -1612,7 +1619,7 @@ the real interface is also shown as a comment, to give you an idea of
|
|||
how these example host is set up. All branches use the netname `company'
|
||||
for this particular VPN.
|
||||
|
||||
Each branch is set up using the @samp{tincctl init} and @samp{tincctl config} commands,
|
||||
Each branch is set up using the @samp{tinc init} and @samp{tinc config} commands,
|
||||
here we just show the end results:
|
||||
|
||||
@subsubheading For Branch A
|
||||
|
@ -1783,7 +1790,7 @@ their daemons, tinc will try connecting until they are available.
|
|||
If everything else is done, you can start tinc by typing the following command:
|
||||
|
||||
@example
|
||||
tincctl -n @var{netname} start
|
||||
tinc -n @var{netname} start
|
||||
@end example
|
||||
|
||||
@cindex daemon
|
||||
|
@ -1834,7 +1841,7 @@ Specifying . for @var{netname} is the same as not specifying any @var{netname}.
|
|||
@xref{Multiple networks}.
|
||||
|
||||
@item --pidfile=@var{filename}
|
||||
Store a cookie in @var{filename} which allows tincctl to authenticate.
|
||||
Store a cookie in @var{filename} which allows tinc to authenticate.
|
||||
If unspecified, the default is
|
||||
@file{@value{localstatedir}/run/tinc.@var{netname}.pid}.
|
||||
|
||||
|
@ -2108,25 +2115,25 @@ Be sure to include the following information in your bugreport:
|
|||
@node Controlling tinc
|
||||
@chapter Controlling tinc
|
||||
|
||||
You can control and inspect a running tincd through the tincctl
|
||||
You can control and inspect a running tincd through the tinc
|
||||
command. A quick example:
|
||||
|
||||
@example
|
||||
tincctl -n @var{netname} reload
|
||||
tinc -n @var{netname} reload
|
||||
@end example
|
||||
|
||||
@menu
|
||||
* tincctl runtime options::
|
||||
* tincctl environment variables::
|
||||
* tincctl commands::
|
||||
* tincctl examples::
|
||||
* tincctl top::
|
||||
* tinc runtime options::
|
||||
* tinc environment variables::
|
||||
* tinc commands::
|
||||
* tinc examples::
|
||||
* tinc top::
|
||||
@end menu
|
||||
|
||||
|
||||
@c ==================================================================
|
||||
@node tincctl runtime options
|
||||
@section tincctl runtime options
|
||||
@node tinc runtime options
|
||||
@section tinc runtime options
|
||||
|
||||
@c from the manpage
|
||||
@table @option
|
||||
|
@ -2151,8 +2158,8 @@ Output version information and exit.
|
|||
@end table
|
||||
|
||||
@c ==================================================================
|
||||
@node tincctl environment variables
|
||||
@section tincctl environment variables
|
||||
@node tinc environment variables
|
||||
@section tinc environment variables
|
||||
|
||||
@table @env
|
||||
@cindex NETNAME
|
||||
|
@ -2162,8 +2169,8 @@ the value of this environment variable is used.
|
|||
@end table
|
||||
|
||||
@c ==================================================================
|
||||
@node tincctl commands
|
||||
@section tincctl commands
|
||||
@node tinc commands
|
||||
@section tinc commands
|
||||
|
||||
@c from the manpage
|
||||
@table @code
|
||||
|
@ -2172,20 +2179,20 @@ the value of this environment variable is used.
|
|||
Create initial configuration files and RSA and ECDSA keypairs with default length.
|
||||
If no @var{name} for this node is given, it will be asked for.
|
||||
|
||||
@item config [get] @var{variable}
|
||||
@item get @var{variable}
|
||||
Print the current value of configuration variable @var{variable}.
|
||||
If more than one variable with the same name exists,
|
||||
the value of each of them will be printed on a separate line.
|
||||
|
||||
@item config [set] @var{variable} @var{value}
|
||||
@item set @var{variable} @var{value}
|
||||
Set configuration variable @var{variable} to the given @var{value}.
|
||||
All previously existing configuration variables with the same name are removed.
|
||||
To set a variable for a specific host, use the notation @var{host}.@var{variable}.
|
||||
|
||||
@item config add @var{variable} @var{value}
|
||||
@item add @var{variable} @var{value}
|
||||
As above, but without removing any previously existing configuration variables.
|
||||
|
||||
@item config del @var{variable} [@var{value}]
|
||||
@item del @var{variable} [@var{value}]
|
||||
Remove configuration variables with the same name and @var{value}.
|
||||
If no @var{value} is given, all configuration variables with the same name will be removed.
|
||||
|
||||
|
@ -2200,7 +2207,7 @@ Export the host configuration file of the local node to standard output.
|
|||
Export all host configuration files to standard output.
|
||||
|
||||
@item import [--force]
|
||||
Import host configuration file(s) generated by the tincctl export command from standard input.
|
||||
Import host configuration file(s) generated by the tinc export command from standard input.
|
||||
Already existing host configuration files are not overwritten unless the option --force is used.
|
||||
|
||||
@item exchange [--force]
|
||||
|
@ -2263,7 +2270,7 @@ Sets debug level to @var{level}.
|
|||
|
||||
@item log [@var{level}]
|
||||
Capture log messages from a running tinc daemon.
|
||||
An optional debug level can be given that will be applied only for log messages sent to tincctl.
|
||||
An optional debug level can be given that will be applied only for log messages sent to tinc.
|
||||
|
||||
@item retry
|
||||
Forces tinc to try to connect to all uplinks immediately.
|
||||
|
@ -2276,7 +2283,7 @@ it defaults to the maximum time of 15 minutes.
|
|||
Closes the meta connection with the given @var{node}.
|
||||
|
||||
@item top
|
||||
If tincctl is compiled with libcurses support, this will display live traffic statistics for all the known nodes,
|
||||
If tinc is compiled with libcurses support, this will display live traffic statistics for all the known nodes,
|
||||
similar to the UNIX top command.
|
||||
See below for more information.
|
||||
|
||||
|
@ -2288,30 +2295,30 @@ such as tcpdump.
|
|||
@end table
|
||||
|
||||
@c ==================================================================
|
||||
@node tincctl examples
|
||||
@section tincctl examples
|
||||
@node tinc examples
|
||||
@section tinc examples
|
||||
|
||||
Examples of some commands:
|
||||
|
||||
@example
|
||||
tincctl -n vpn dump graph | circo -Txlib
|
||||
tincctl -n vpn pcap | tcpdump -r -
|
||||
tincctl -n vpn top
|
||||
tinc -n vpn dump graph | circo -Txlib
|
||||
tinc -n vpn pcap | tcpdump -r -
|
||||
tinc -n vpn top
|
||||
@end example
|
||||
|
||||
Example of configuring tinc using tincctl:
|
||||
Example of configuring tinc using the tinc command:
|
||||
|
||||
@example
|
||||
tincctl -n vpn init foo
|
||||
tincctl -n vpn config Subnet 192.168.1.0/24
|
||||
tincctl -n vpn config bar.Address bar.example.com
|
||||
tincctl -n vpn config ConnectTo bar
|
||||
tincctl -n vpn export | gpg --clearsign | mail -s "My config" vpnmaster@@example.com
|
||||
tinc -n vpn init foo
|
||||
tinc -n vpn add Subnet 192.168.1.0/24
|
||||
tinc -n vpn add bar.Address bar.example.com
|
||||
tinc -n vpn add ConnectTo bar
|
||||
tinc -n vpn export | gpg --clearsign | mail -s "My config" vpnmaster@@example.com
|
||||
@end example
|
||||
|
||||
@c ==================================================================
|
||||
@node tincctl top
|
||||
@section tincctl top
|
||||
@node tinc top
|
||||
@section tinc top
|
||||
|
||||
The top command connects to a running tinc daemon and repeatedly queries its per-node traffic counters.
|
||||
It displays a list of all the known nodes in the left-most column,
|
||||
|
@ -2504,7 +2511,7 @@ daemon started with the --bypass-security option
|
|||
and to read and write requests by hand, provided that one
|
||||
understands the numeric codes sent.
|
||||
|
||||
The authentication scheme is described in @ref{Authentication protocol}. After a
|
||||
The authentication scheme is described in @ref{Security}. After a
|
||||
successful authentication, the server and the client will exchange all the
|
||||
information about other tinc daemons and subnets they know of, so that both
|
||||
sides (and all the other tinc daemons behind them) have their information
|
||||
|
@ -2624,29 +2631,28 @@ the tinc project after TINC.
|
|||
But in order to be ``immune'' to eavesdropping, you'll have to encrypt
|
||||
your data. Because tinc is a @emph{Secure} VPN (SVPN) daemon, it does
|
||||
exactly that: encrypt.
|
||||
Tinc by default uses blowfish encryption with 128 bit keys in CBC mode, 32 bit
|
||||
sequence numbers and 4 byte long message authentication codes to make sure
|
||||
eavesdroppers cannot get and cannot change any information at all from the
|
||||
packets they can intercept. The encryption algorithm and message authentication
|
||||
algorithm can be changed in the configuration. The length of the message
|
||||
authentication codes is also adjustable. The length of the key for the
|
||||
encryption algorithm is always the default length used by OpenSSL.
|
||||
However, encryption in itself does not prevent an attacker from modifying the encrypted data.
|
||||
Therefore, tinc also authenticates the data.
|
||||
Finally, tinc uses sequence numbers (which themselves are also authenticated) to prevent an attacker from replaying valid packets.
|
||||
|
||||
Since version 1.1pre3, tinc has two protocols used to protect your data; the legacy protocol, and the new Simple Peer-to-Peer Security (SPTPS) protocol.
|
||||
The SPTPS protocol is designed to address some weaknesses in the legacy protocol.
|
||||
The new authentication protocol is used when two nodes connect to each other that both have the ExperimentalProtocol option set to yes,
|
||||
otherwise the legacy protocol will be used.
|
||||
|
||||
@menu
|
||||
* Authentication protocol::
|
||||
* Legacy authentication protocol::
|
||||
* Simple Peer-to-Peer Security::
|
||||
* Encryption of network packets::
|
||||
* Security issues::
|
||||
@end menu
|
||||
|
||||
|
||||
@c ==================================================================
|
||||
@node Authentication protocol
|
||||
@subsection Authentication protocol
|
||||
@node Legacy authentication protocol
|
||||
@subsection Legacy authentication protocol
|
||||
|
||||
@cindex authentication
|
||||
A new scheme for authentication in tinc has been devised, which offers some
|
||||
improvements over the protocol used in 1.0pre2 and 1.0pre3. Explanation is
|
||||
below.
|
||||
@cindex legacy authentication protocol
|
||||
|
||||
@cindex ID
|
||||
@cindex META_KEY
|
||||
|
@ -2660,28 +2666,50 @@ client <attempts connection>
|
|||
|
||||
server <accepts connection>
|
||||
|
||||
client ID client 12
|
||||
| +---> version
|
||||
+-------> name of tinc daemon
|
||||
client ID client 17.2
|
||||
| | +-> minor protocol version
|
||||
| +----> major protocol version
|
||||
+--------> name of tinc daemon
|
||||
|
||||
server ID server 12
|
||||
| +---> version
|
||||
+-------> name of tinc daemon
|
||||
server ID server 17.2
|
||||
| | +-> minor protocol version
|
||||
| +----> major protocol version
|
||||
+--------> name of tinc daemon
|
||||
|
||||
client META_KEY 5f0823a93e35b69e...7086ec7866ce582b
|
||||
\_________________________________/
|
||||
+-> RSAKEYLEN bits totally random string S1,
|
||||
encrypted with server's public RSA key
|
||||
client META_KEY 94 64 0 0 5f0823a93e35b69e...7086ec7866ce582b
|
||||
| | | | \_________________________________/
|
||||
| | | | +-> RSAKEYLEN bits totally random string S1,
|
||||
| | | | encrypted with server's public RSA key
|
||||
| | | +-> compression level
|
||||
| | +---> MAC length
|
||||
| +------> digest algorithm NID
|
||||
+---------> cipher algorithm NID
|
||||
|
||||
server META_KEY 6ab9c1640388f8f0...45d1a07f8a672630
|
||||
\_________________________________/
|
||||
+-> RSAKEYLEN bits totally random string S2,
|
||||
encrypted with client's public RSA key
|
||||
server META_KEY 94 64 0 0 6ab9c1640388f8f0...45d1a07f8a672630
|
||||
| | | | \_________________________________/
|
||||
| | | | +-> RSAKEYLEN bits totally random string S2,
|
||||
| | | | encrypted with client's public RSA key
|
||||
| | | +-> compression level
|
||||
| | +---> MAC length
|
||||
| +------> digest algorithm NID
|
||||
+---------> cipher algorithm NID
|
||||
--------------------------------------------------------------------------
|
||||
@end example
|
||||
|
||||
The protocol allows each side to specify encryption algorithms and parameters,
|
||||
but in practice they are always fixed, since older versions of tinc did not
|
||||
allow them to be different from the default values. The cipher is always
|
||||
Blowfish in OFB mode, the digest is SHA1, but the MAC length is zero and no
|
||||
compression is used.
|
||||
|
||||
From now on:
|
||||
- the client will symmetrically encrypt outgoing traffic using S1
|
||||
- the server will symmetrically encrypt outgoing traffic using S2
|
||||
@itemize
|
||||
@item the client will symmetrically encrypt outgoing traffic using S1
|
||||
@item the server will symmetrically encrypt outgoing traffic using S2
|
||||
@end itemize
|
||||
|
||||
@example
|
||||
--------------------------------------------------------------------------
|
||||
client CHALLENGE da02add1817c1920989ba6ae2a49cecbda0
|
||||
\_________________________________/
|
||||
+-> CHALLEN bits totally random string H1
|
||||
|
@ -2711,47 +2739,178 @@ server ACK 655 321 0
|
|||
--------------------------------------------------------------------------
|
||||
@end example
|
||||
|
||||
This new scheme has several improvements, both in efficiency and security.
|
||||
This legacy authentication protocol has several weaknesses, pointed out by security export Peter Gutmann.
|
||||
First, data is encrypted with RSA without padding.
|
||||
Padding schemes are designed to prevent attacks when the size of the plaintext is not equal to the size of the RSA key.
|
||||
Tinc always encrypts random nonces that have the same size as the RSA key, so we do not believe this leads to a break of the security.
|
||||
There might be timing or other side-channel attacks against RSA encryption and decryption, tinc does not employ any protection against those.
|
||||
Furthermore, both sides send identical messages to each other, there is no distinction between server and client,
|
||||
which could make a MITM attack easier.
|
||||
However, no exploit is known in which a third party who is not already trusted by other nodes in the VPN could gain access.
|
||||
Finally, the RSA keys are used to directly encrypt the session keys, which means that if the RSA keys are compromised, it is possible to decrypt all previous VPN traffic.
|
||||
In other words, the legacy protocol does not provide perfect forward secrecy.
|
||||
|
||||
First of all, the server sends exactly the same kind of messages over the wire
|
||||
as the client. The previous versions of tinc first authenticated the client,
|
||||
and then the server. This scheme even allows both sides to send their messages
|
||||
simultaneously, there is no need to wait for the other to send something first.
|
||||
This means that any calculations that need to be done upon sending or receiving
|
||||
a message can also be done in parallel. This is especially important when doing
|
||||
RSA encryption/decryption. Given that these calculations are the main part of
|
||||
the CPU time spent for the authentication, speed is improved by a factor 2.
|
||||
@c ==================================================================
|
||||
@node Simple Peer-to-Peer Security
|
||||
@subsection Simple Peer-to-Peer Security
|
||||
@cindex SPTPS
|
||||
|
||||
Second, only one RSA encrypted message is sent instead of two. This reduces the
|
||||
amount of information attackers can see (and thus use for a cryptographic
|
||||
attack). It also improves speed by a factor two, making the total speedup a
|
||||
factor 4.
|
||||
The SPTPS protocol is designed to address the weaknesses in the legacy protocol.
|
||||
SPTPS is based on TLS 1.2, but has been simplified: there is no support for exchanging public keys, and there is no cipher suite negotiation.
|
||||
Instead, SPTPS always uses a very strong cipher suite:
|
||||
peers authenticate each other using 521 bits ECC keys,
|
||||
Diffie-Hellman using ephemeral 521 bits ECC keys is used to provide perfect forward secrecy (PFS),
|
||||
AES-256-CTR is used for encryption, and HMAC-SHA-256 for message authentication.
|
||||
|
||||
Third, and most important:
|
||||
The symmetric cipher keys are exchanged first, the challenge is done
|
||||
afterwards. In the previous authentication scheme, because a man-in-the-middle
|
||||
could pass the challenge/chal_reply phase (by just copying the messages between
|
||||
the two real tinc daemons), but no information was exchanged that was really
|
||||
needed to read the rest of the messages, the challenge/chal_reply phase was of
|
||||
no real use. The man-in-the-middle was only stopped by the fact that only after
|
||||
the ACK messages were encrypted with the symmetric cipher. Potentially, it
|
||||
could even send it's own symmetric key to the server (if it knew the server's
|
||||
public key) and read some of the metadata the server would send it (it was
|
||||
impossible for the mitm to read actual network packets though). The new scheme
|
||||
however prevents this.
|
||||
Similar to TLS, messages are split up in records.
|
||||
A complete logical record contains the following information:
|
||||
|
||||
This new scheme makes sure that first of all, symmetric keys are exchanged. The
|
||||
rest of the messages are then encrypted with the symmetric cipher. Then, each
|
||||
side can only read received messages if they have their private key. The
|
||||
challenge is there to let the other side know that the private key is really
|
||||
known, because a challenge reply can only be sent back if the challenge is
|
||||
decrypted correctly, and that can only be done with knowledge of the private
|
||||
key.
|
||||
@itemize
|
||||
@item uint32_t seqno (network byte order)
|
||||
@item uint16_t length (network byte order)
|
||||
@item uint8_t type
|
||||
@item opaque data[length]
|
||||
@item opaque hmac[HMAC_SIZE] (HMAC over all preceding fields)
|
||||
@end itemize
|
||||
|
||||
Fourth: the first thing that is sent via the symmetric cipher encrypted
|
||||
connection is a totally random string, so that there is no known plaintext (for
|
||||
an attacker) in the beginning of the encrypted stream.
|
||||
Depending on whether SPTPS records are sent via TCP or UDP, either the seqno or the length field is omitted on the wire
|
||||
(but they are still included in the calculation of the HMAC);
|
||||
for TCP packets are guaranteed to arrive in-order so we can infer the seqno, but packets can be split or merged, so we still need the length field to determine the boundaries between records;
|
||||
for UDP packets we know that there is exactly one record per packet, and we know the length of a packet, but packets can be dropped, duplicated and/or reordered, so we need to include the seqno.
|
||||
|
||||
The type field is used to distinguish between application records or handshake records.
|
||||
Types 0 to 127 are application records, type 128 is a handshake record, and types 129 to 255 are reserved.
|
||||
|
||||
Before the initial handshake, no fields are encrypted, and the HMAC field is not present.
|
||||
After the authentication handshake, the length (if present), type and data fields are encrypted, and the HMAC field is present.
|
||||
For UDP packets, the seqno field is not encrypted, as it is used to determine the value of the counter used for encryption.
|
||||
|
||||
The authentication consists of an exchange of Key EXchange, SIGnature and ACKnowledge messages, transmitted using type 128 records.
|
||||
|
||||
Overview:
|
||||
|
||||
@example
|
||||
Initiator Responder
|
||||
---------------------
|
||||
KEX ->
|
||||
<- KEX
|
||||
SIG ->
|
||||
<- SIG
|
||||
|
||||
...encrypt and HMAC using session keys from now on...
|
||||
|
||||
App ->
|
||||
<- App
|
||||
...
|
||||
...
|
||||
|
||||
...key renegotiation starts here...
|
||||
|
||||
KEX ->
|
||||
<- KEX
|
||||
SIG ->
|
||||
<- SIG
|
||||
ACK ->
|
||||
<- ACK
|
||||
|
||||
...encrypt and HMAC using new session keys from now on...
|
||||
|
||||
App ->
|
||||
<- App
|
||||
...
|
||||
...
|
||||
---------------------
|
||||
@end example
|
||||
|
||||
Note that the responder does not need to wait before it receives the first KEX message,
|
||||
it can immediately send its own once it has accepted an incoming connection.
|
||||
|
||||
Key EXchange message:
|
||||
|
||||
@itemize
|
||||
@item uint8_t kex_version (always 0 in this version of SPTPS)
|
||||
@item opaque nonce[32] (random number)
|
||||
@item opaque ecdh_key[ECDH_SIZE]
|
||||
@end itemize
|
||||
|
||||
SIGnature message:
|
||||
|
||||
@itemize
|
||||
@item opaque ecdsa_signature[ECDSA_SIZE]
|
||||
@end itemize
|
||||
|
||||
ACKnowledge message:
|
||||
|
||||
@itemize
|
||||
@item empty (only sent after key renegotiation)
|
||||
@end itemize
|
||||
|
||||
Remarks:
|
||||
|
||||
@itemize
|
||||
@item At the start, both peers generate a random nonce and an Elliptic Curve public key and send it to the other in the KEX message.
|
||||
@item After receiving the other's KEX message, both KEX messages are concatenated (see below),
|
||||
and the result is signed using ECDSA.
|
||||
The result is sent to the other.
|
||||
@item After receiving the other's SIG message, the signature is verified.
|
||||
If it is correct, the shared secret is calculated from the public keys exchanged in the KEX message using the Elliptic Curve Diffie-Helman algorithm.
|
||||
@item The shared secret key is expanded using a PRF.
|
||||
Both nonces and the application specific label are also used as input for the PRF.
|
||||
@item An ACK message is sent only when doing key renegotiation, and is sent using the old encryption keys.
|
||||
@item The expanded key is used to key the encryption and HMAC algorithms.
|
||||
@end itemize
|
||||
|
||||
The signature is calculated over this string:
|
||||
|
||||
@itemize
|
||||
@item uint8_t initiator (0 = local peer, 1 = remote peer is initiator)
|
||||
@item opaque remote_kex_message[1 + 32 + ECDH_SIZE]
|
||||
@item opaque local_kex_message[1 + 32 + ECDH_SIZE]
|
||||
@item opaque label[label_length]
|
||||
@end itemize
|
||||
|
||||
The PRF is calculated as follows:
|
||||
|
||||
@itemize
|
||||
@item A HMAC using SHA512 is used, the shared secret is used as the key.
|
||||
@item For each block of 64 bytes, a HMAC is calculated. For block n: hmac[n] =
|
||||
HMAC_SHA512(hmac[n - 1] + seed)
|
||||
@item For the first block (n = 1), hmac[0] is given by HMAC_SHA512(zeroes + seed),
|
||||
where zeroes is a block of 64 zero bytes.
|
||||
@end itemize
|
||||
|
||||
The seed is as follows:
|
||||
|
||||
@itemize
|
||||
@item const char[13] "key expansion"
|
||||
@item opaque responder_nonce[32]
|
||||
@item opaque initiator_nonce[32]
|
||||
@item opaque label[label_length]
|
||||
@end itemize
|
||||
|
||||
The expanded key is used as follows:
|
||||
|
||||
@itemize
|
||||
@item opaque responder_cipher_key[CIPHER_KEYSIZE]
|
||||
@item opaque responder_digest_key[DIGEST_KEYSIZE]
|
||||
@item opaque initiator_cipher_key[CIPHER_KEYSIZE]
|
||||
@item opaque initiator_digest_key[DIGEST_KEYSIZE]
|
||||
@end itemize
|
||||
|
||||
Where initiator_cipher_key is the key used by session initiator to encrypt
|
||||
messages sent to the responder.
|
||||
|
||||
When using 521 bits EC keys, the AES-256-CTR cipher and HMAC-SHA-256 digest algorithm,
|
||||
the sizes are as follows:
|
||||
|
||||
@example
|
||||
ECDH_SIZE: 67 (= ceil(521/8) + 1)
|
||||
ECDSA_SIZE: 141 (= 2 * ceil(521/8) + 9)
|
||||
CIPHER_KEYSIZE: 48 (= 256/8 + 128/8)
|
||||
DIGEST_KEYSIZE: 32 (= 256/8)
|
||||
@end example
|
||||
|
||||
Note that the cipher key also includes the initial value for the counter.
|
||||
|
||||
@c ==================================================================
|
||||
@node Encryption of network packets
|
||||
|
@ -2761,11 +2920,11 @@ an attacker) in the beginning of the encrypted stream.
|
|||
A data packet can only be sent if the encryption key is known to both
|
||||
parties, and the connection is activated. If the encryption key is not
|
||||
known, a request is sent to the destination using the meta connection
|
||||
to retrieve it. The packet is stored in a queue while waiting for the
|
||||
key to arrive.
|
||||
to retrieve it.
|
||||
|
||||
@cindex UDP
|
||||
The UDP packet containing the network packet from the VPN has the following layout:
|
||||
The UDP packets can be either encrypted with the legacy protocol or with SPTPS.
|
||||
In case of the legacy protocol, the UDP packet containing the network packet from the VPN has the following layout:
|
||||
|
||||
@example
|
||||
... | IP header | UDP header | seqno | VPN packet | MAC | UDP trailer
|
||||
|
@ -2775,12 +2934,38 @@ The UDP packet containing the network packet from the VPN has the following layo
|
|||
Encrypted with symmetric cipher
|
||||
@end example
|
||||
|
||||
|
||||
|
||||
|
||||
So, the entire VPN packet is encrypted using a symmetric cipher, including a 32 bits
|
||||
sequence number that is added in front of the actual VPN packet, to act as a unique
|
||||
IV for each packet and to prevent replay attacks. A message authentication code
|
||||
is added to the UDP packet to prevent alteration of packets. By default the
|
||||
first 4 bytes of the digest are used for this, but this can be changed using
|
||||
the MACLength configuration variable.
|
||||
is added to the UDP packet to prevent alteration of packets.
|
||||
Tinc by default encrypts network packets using Blowfish with 128 bit keys in CBC mode
|
||||
and uses 4 byte long message authentication codes to make sure
|
||||
eavesdroppers cannot get and cannot change any information at all from the
|
||||
packets they can intercept. The encryption algorithm and message authentication
|
||||
algorithm can be changed in the configuration. The length of the message
|
||||
authentication codes is also adjustable. The length of the key for the
|
||||
encryption algorithm is always the default length used by OpenSSL.
|
||||
|
||||
The SPTPS protocol is described in @ref{Simple Peer-to-Peer Security}.
|
||||
For comparison, this is how SPTPS UDP packets look:
|
||||
|
||||
@example
|
||||
... | IP header | UDP header | seqno | type | VPN packet | MAC | UDP trailer
|
||||
\__________________/\_____/
|
||||
| |
|
||||
V +---> digest algorithm
|
||||
Encrypted with symmetric cipher
|
||||
@end example
|
||||
|
||||
The difference is that the seqno is not encrypted, since the encryption cipher is used in CTR mode,
|
||||
and therefore the seqno must be known before the packet can be decrypted.
|
||||
Furthermore, the MAC is never truncated.
|
||||
The SPTPS protocol always uses the AES-256-CTR cipher and HMAC-SHA-256 digest,
|
||||
this cannot be changed.
|
||||
|
||||
|
||||
@c ==================================================================
|
||||
@node Security issues
|
||||
|
@ -2803,8 +2988,10 @@ On the 15th of September 2003, Peter Gutmann posted a security analysis of tinc
|
|||
1.0.1. He argues that the 32 bit sequence number used by tinc is not a good IV,
|
||||
that tinc's default length of 4 bytes for the MAC is too short, and he doesn't
|
||||
like tinc's use of RSA during authentication. We do not know of a security hole
|
||||
in this version of tinc, but tinc's security is not as strong as TLS or IPsec.
|
||||
We will address these issues in tinc 2.0.
|
||||
in the legacy protocol of tinc, but it is not as strong as TLS or IPsec.
|
||||
|
||||
This version of tinc comes with an improved protocol, called Simple Peer-to-Peer Security,
|
||||
which aims to be as strong as TLS with one of the strongest cipher suites.
|
||||
|
||||
Cryptography is a hard thing to get right. We cannot make any
|
||||
guarantees. Time, review and feedback are the only things that can
|
||||
|
|
|
@ -92,7 +92,7 @@ is omitted, the default is
|
|||
Store a cookie in
|
||||
.Ar FILENAME
|
||||
which allows
|
||||
.Xr tincctl 8
|
||||
.Xr tinc 8
|
||||
to authenticate.
|
||||
If
|
||||
.Ar FILE
|
||||
|
@ -186,7 +186,7 @@ If you find any bugs, report them to tinc@tinc-vpn.org.
|
|||
.Sh TODO
|
||||
A lot, especially security auditing.
|
||||
.Sh SEE ALSO
|
||||
.Xr tincctl 8 ,
|
||||
.Xr tinc 8 ,
|
||||
.Xr tinc.conf 5 ,
|
||||
.Pa http://www.tinc-vpn.org/ ,
|
||||
.Pa http://www.cabal.org/ .
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
## Produce this file with automake to get Makefile.in
|
||||
|
||||
sbin_PROGRAMS = tincd tincctl sptps_test
|
||||
sbin_PROGRAMS = tincd tinc sptps_test
|
||||
|
||||
EXTRA_DIST = linux bsd solaris cygwin mingw openssl gcrypt
|
||||
|
||||
|
@ -22,11 +22,11 @@ endif
|
|||
nodist_tincd_SOURCES = \
|
||||
device.c cipher.c crypto.c ecdh.c ecdsa.c digest.c prf.c rsa.c
|
||||
|
||||
tincctl_SOURCES = \
|
||||
tinc_SOURCES = \
|
||||
utils.c getopt.c getopt1.c dropin.c \
|
||||
info.c list.c subnet_parse.c tincctl.c top.c names.c
|
||||
|
||||
nodist_tincctl_SOURCES = \
|
||||
nodist_tinc_SOURCES = \
|
||||
ecdsagen.c rsagen.c
|
||||
|
||||
sptps_test_SOURCES = \
|
||||
|
@ -37,7 +37,7 @@ if TUNEMU
|
|||
tincd_SOURCES += bsd/tunemu.c
|
||||
endif
|
||||
|
||||
tincctl_LDADD = $(READLINE_LIBS) $(CURSES_LIBS)
|
||||
tinc_LDADD = $(READLINE_LIBS) $(CURSES_LIBS)
|
||||
|
||||
DEFAULT_INCLUDES =
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ PRE_UNINSTALL = :
|
|||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
sbin_PROGRAMS = tincd$(EXEEXT) tincctl$(EXEEXT) sptps_test$(EXEEXT)
|
||||
sbin_PROGRAMS = tincd$(EXEEXT) tinc$(EXEEXT) sptps_test$(EXEEXT)
|
||||
@UML_TRUE@am__append_1 = uml_device.c
|
||||
@VDE_TRUE@am__append_2 = vde_device.c
|
||||
@TUNEMU_TRUE@am__append_3 = bsd/tunemu.c
|
||||
|
@ -79,14 +79,14 @@ am_sptps_test_OBJECTS = logger.$(OBJEXT) cipher.$(OBJEXT) \
|
|||
sptps_test.$(OBJEXT) utils.$(OBJEXT)
|
||||
sptps_test_OBJECTS = $(am_sptps_test_OBJECTS)
|
||||
sptps_test_LDADD = $(LDADD)
|
||||
am_tincctl_OBJECTS = utils.$(OBJEXT) getopt.$(OBJEXT) \
|
||||
getopt1.$(OBJEXT) dropin.$(OBJEXT) info.$(OBJEXT) \
|
||||
list.$(OBJEXT) subnet_parse.$(OBJEXT) tincctl.$(OBJEXT) \
|
||||
top.$(OBJEXT) names.$(OBJEXT)
|
||||
nodist_tincctl_OBJECTS = ecdsagen.$(OBJEXT) rsagen.$(OBJEXT)
|
||||
tincctl_OBJECTS = $(am_tincctl_OBJECTS) $(nodist_tincctl_OBJECTS)
|
||||
am_tinc_OBJECTS = utils.$(OBJEXT) getopt.$(OBJEXT) getopt1.$(OBJEXT) \
|
||||
dropin.$(OBJEXT) info.$(OBJEXT) list.$(OBJEXT) \
|
||||
subnet_parse.$(OBJEXT) tincctl.$(OBJEXT) top.$(OBJEXT) \
|
||||
names.$(OBJEXT)
|
||||
nodist_tinc_OBJECTS = ecdsagen.$(OBJEXT) rsagen.$(OBJEXT)
|
||||
tinc_OBJECTS = $(am_tinc_OBJECTS) $(nodist_tinc_OBJECTS)
|
||||
am__DEPENDENCIES_1 =
|
||||
tincctl_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
|
||||
tinc_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
|
||||
am__tincd_SOURCES_DIST = utils.c getopt.c getopt1.c list.c \
|
||||
splay_tree.c dropin.c fake-getaddrinfo.c fake-getnameinfo.c \
|
||||
hash.c buffer.c conf.c connection.c control.c edge.c graph.c \
|
||||
|
@ -128,10 +128,9 @@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
|||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
SOURCES = $(sptps_test_SOURCES) $(tincctl_SOURCES) \
|
||||
$(nodist_tincctl_SOURCES) $(tincd_SOURCES) \
|
||||
$(nodist_tincd_SOURCES)
|
||||
DIST_SOURCES = $(sptps_test_SOURCES) $(tincctl_SOURCES) \
|
||||
SOURCES = $(sptps_test_SOURCES) $(tinc_SOURCES) $(nodist_tinc_SOURCES) \
|
||||
$(tincd_SOURCES) $(nodist_tincd_SOURCES)
|
||||
DIST_SOURCES = $(sptps_test_SOURCES) $(tinc_SOURCES) \
|
||||
$(am__tincd_SOURCES_DIST)
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
|
@ -258,18 +257,18 @@ tincd_SOURCES = utils.c getopt.c getopt1.c list.c splay_tree.c \
|
|||
nodist_tincd_SOURCES = \
|
||||
device.c cipher.c crypto.c ecdh.c ecdsa.c digest.c prf.c rsa.c
|
||||
|
||||
tincctl_SOURCES = \
|
||||
tinc_SOURCES = \
|
||||
utils.c getopt.c getopt1.c dropin.c \
|
||||
info.c list.c subnet_parse.c tincctl.c top.c names.c
|
||||
|
||||
nodist_tincctl_SOURCES = \
|
||||
nodist_tinc_SOURCES = \
|
||||
ecdsagen.c rsagen.c
|
||||
|
||||
sptps_test_SOURCES = \
|
||||
logger.c cipher.c crypto.c ecdh.c ecdsa.c digest.c prf.c \
|
||||
sptps.c sptps_test.c utils.c
|
||||
|
||||
tincctl_LDADD = $(READLINE_LIBS) $(CURSES_LIBS)
|
||||
tinc_LDADD = $(READLINE_LIBS) $(CURSES_LIBS)
|
||||
DEFAULT_INCLUDES =
|
||||
noinst_HEADERS = \
|
||||
xalloc.h utils.h getopt.h list.h splay_tree.h dropin.h fake-getaddrinfo.h fake-getnameinfo.h fake-gai-errnos.h ipv6.h ipv4.h ethernet.h \
|
||||
|
@ -357,9 +356,9 @@ clean-sbinPROGRAMS:
|
|||
sptps_test$(EXEEXT): $(sptps_test_OBJECTS) $(sptps_test_DEPENDENCIES) $(EXTRA_sptps_test_DEPENDENCIES)
|
||||
@rm -f sptps_test$(EXEEXT)
|
||||
$(LINK) $(sptps_test_OBJECTS) $(sptps_test_LDADD) $(LIBS)
|
||||
tincctl$(EXEEXT): $(tincctl_OBJECTS) $(tincctl_DEPENDENCIES) $(EXTRA_tincctl_DEPENDENCIES)
|
||||
@rm -f tincctl$(EXEEXT)
|
||||
$(LINK) $(tincctl_OBJECTS) $(tincctl_LDADD) $(LIBS)
|
||||
tinc$(EXEEXT): $(tinc_OBJECTS) $(tinc_DEPENDENCIES) $(EXTRA_tinc_DEPENDENCIES)
|
||||
@rm -f tinc$(EXEEXT)
|
||||
$(LINK) $(tinc_OBJECTS) $(tinc_LDADD) $(LIBS)
|
||||
tincd$(EXEEXT): $(tincd_OBJECTS) $(tincd_DEPENDENCIES) $(EXTRA_tincd_DEPENDENCIES)
|
||||
@rm -f tincd$(EXEEXT)
|
||||
$(LINK) $(tincd_OBJECTS) $(tincd_LDADD) $(LIBS)
|
||||
|
|
|
@ -245,6 +245,12 @@ bool event_loop(void) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void event_flush_output(void) {
|
||||
for splay_each(io_t, io, &io_tree)
|
||||
if(FD_ISSET(io->fd, &writefds))
|
||||
io->cb(io->data, IO_WRITE);
|
||||
}
|
||||
|
||||
void event_exit(void) {
|
||||
running = false;
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ extern void signal_add(signal_t *sig, signal_cb_t cb, void *data, int signum);
|
|||
extern void signal_del(signal_t *sig);
|
||||
|
||||
extern bool event_loop(void);
|
||||
extern void event_flush_output(void);
|
||||
extern void event_exit(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -204,7 +204,7 @@ static void check_reachability(void) {
|
|||
for splay_each(node_t, n, node_tree) {
|
||||
if(n->status.visited != n->status.reachable) {
|
||||
n->status.reachable = !n->status.reachable;
|
||||
n->last_state_change = time(NULL);
|
||||
n->last_state_change = now.tv_sec;
|
||||
|
||||
if(n->status.reachable) {
|
||||
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Node %s (%s) became reachable",
|
||||
|
|
|
@ -80,6 +80,7 @@ static DWORD WINAPI tapreader(void *bla) {
|
|||
packet.len = len;
|
||||
packet.priority = 0;
|
||||
route(myself, &packet);
|
||||
event_flush_output();
|
||||
LeaveCriticalSection(&mutex);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -406,7 +406,7 @@ int reload_configuration(void) {
|
|||
free(fname);
|
||||
}
|
||||
|
||||
last_config_check = time(NULL);
|
||||
last_config_check = now.tv_sec;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -135,6 +135,7 @@ extern int udp_sndbuf;
|
|||
extern bool do_prune;
|
||||
extern char *myport;
|
||||
extern int autoconnect;
|
||||
extern bool disablebuggypeers;
|
||||
extern int contradicting_add_edge;
|
||||
extern int contradicting_del_edge;
|
||||
extern time_t last_config_check;
|
||||
|
|
|
@ -443,6 +443,9 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
|
|||
void receive_tcppacket(connection_t *c, const char *buffer, int len) {
|
||||
vpn_packet_t outpkt;
|
||||
|
||||
if(len > sizeof outpkt.data)
|
||||
return;
|
||||
|
||||
outpkt.len = len;
|
||||
if(c->options & OPTION_TCPONLY)
|
||||
outpkt.priority = 0;
|
||||
|
@ -458,7 +461,7 @@ static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) {
|
|||
logger(DEBUG_TRAFFIC, LOG_INFO, "No valid key known yet for %s (%s)", n->name, n->hostname);
|
||||
if(!n->status.waitingforkey)
|
||||
send_req_key(n);
|
||||
else if(n->last_req_key + 10 < time(NULL)) {
|
||||
else if(n->last_req_key + 10 < now.tv_sec) {
|
||||
logger(DEBUG_ALWAYS, LOG_DEBUG, "No key from %s after 10 seconds, restarting SPTPS", n->name);
|
||||
sptps_stop(&n->sptps);
|
||||
n->status.waitingforkey = false;
|
||||
|
|
|
@ -52,6 +52,7 @@ char *proxyuser;
|
|||
char *proxypass;
|
||||
proxytype_t proxytype;
|
||||
int autoconnect;
|
||||
bool disablebuggypeers;
|
||||
|
||||
char *scriptinterpreter;
|
||||
char *scriptextension;
|
||||
|
@ -598,6 +599,8 @@ bool setup_myself_reloadable(void) {
|
|||
|
||||
get_config_int(lookup_config(config_tree, "AutoConnect"), &autoconnect);
|
||||
|
||||
get_config_bool(lookup_config(config_tree, "DisableBuggyPeers"), &disablebuggypeers);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -751,7 +754,7 @@ static bool setup_myself(void) {
|
|||
myself->nexthop = myself;
|
||||
myself->via = myself;
|
||||
myself->status.reachable = true;
|
||||
myself->last_state_change = time(NULL);
|
||||
myself->last_state_change = now.tv_sec;
|
||||
myself->status.sptps = experimental;
|
||||
node_add(myself);
|
||||
|
||||
|
@ -958,7 +961,7 @@ static bool setup_myself(void) {
|
|||
return false;
|
||||
}
|
||||
|
||||
last_config_check = time(NULL);
|
||||
last_config_check = now.tv_sec;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -294,7 +294,7 @@ void retry_outgoing(outgoing_t *outgoing) {
|
|||
void finish_connecting(connection_t *c) {
|
||||
logger(DEBUG_CONNECTIONS, LOG_INFO, "Connected to %s (%s)", c->name, c->hostname);
|
||||
|
||||
c->last_ping_time = time(NULL);
|
||||
c->last_ping_time = now.tv_sec;
|
||||
c->status.connecting = false;
|
||||
|
||||
send_id(c);
|
||||
|
@ -349,6 +349,9 @@ static void do_outgoing_pipe(connection_t *c, char *command) {
|
|||
}
|
||||
|
||||
static void handle_meta_write(connection_t *c) {
|
||||
if(c->outbuf.len <= c->outbuf.offset)
|
||||
return;
|
||||
|
||||
ssize_t outlen = send(c->socket, c->outbuf.data + c->outbuf.offset, c->outbuf.len - c->outbuf.offset, 0);
|
||||
if(outlen <= 0) {
|
||||
if(!errno || errno == EPIPE) {
|
||||
|
@ -505,7 +508,7 @@ begin:
|
|||
c->outdigest = myself->connection->outdigest;
|
||||
c->outmaclength = myself->connection->outmaclength;
|
||||
c->outcompression = myself->connection->outcompression;
|
||||
c->last_ping_time = time(NULL);
|
||||
c->last_ping_time = now.tv_sec;
|
||||
|
||||
connection_add(c);
|
||||
|
||||
|
@ -568,7 +571,7 @@ void handle_new_meta_connection(void *data, int flags) {
|
|||
c->address = sa;
|
||||
c->hostname = sockaddr2hostname(&sa);
|
||||
c->socket = fd;
|
||||
c->last_ping_time = time(NULL);
|
||||
c->last_ping_time = now.tv_sec;
|
||||
|
||||
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection from %s", c->hostname);
|
||||
|
||||
|
@ -607,7 +610,7 @@ void handle_new_unix_connection(void *data, int flags) {
|
|||
c->address = sa;
|
||||
c->hostname = xstrdup("localhost port unix");
|
||||
c->socket = fd;
|
||||
c->last_ping_time = time(NULL);
|
||||
c->last_ping_time = now.tv_sec;
|
||||
|
||||
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection from %s", c->hostname);
|
||||
|
||||
|
|
|
@ -195,7 +195,7 @@ bool seen_request(const char *request) {
|
|||
} else {
|
||||
new = xmalloc(sizeof *new);
|
||||
new->request = xstrdup(request);
|
||||
new->firstseen = time(NULL);
|
||||
new->firstseen = now.tv_sec;
|
||||
splay_insert(past_request_tree, new);
|
||||
timeout_add(&past_request_timeout, age_past_requests, NULL, &(struct timeval){10, rand() % 100000});
|
||||
return false;
|
||||
|
|
|
@ -160,7 +160,7 @@ bool id_h(connection_t *c, const char *request) {
|
|||
if(name[0] == '^' && !strcmp(name + 1, controlcookie)) {
|
||||
c->status.control = true;
|
||||
c->allow_request = CONTROL;
|
||||
c->last_ping_time = time(NULL) + 3600;
|
||||
c->last_ping_time = now.tv_sec + 3600;
|
||||
|
||||
free(c->name);
|
||||
c->name = xstrdup("<control>");
|
||||
|
@ -510,6 +510,17 @@ bool send_ack(connection_t *c) {
|
|||
static void send_everything(connection_t *c) {
|
||||
/* Send all known subnets and edges */
|
||||
|
||||
if(disablebuggypeers) {
|
||||
static struct {
|
||||
vpn_packet_t pkt;
|
||||
char pad[MAXBUFSIZE - MAXSIZE];
|
||||
} zeropkt;
|
||||
|
||||
memset(&zeropkt, 0, sizeof zeropkt);
|
||||
zeropkt.pkt.len = MAXBUFSIZE;
|
||||
send_tcppacket(c, &zeropkt.pkt);
|
||||
}
|
||||
|
||||
if(tunnelserver) {
|
||||
for splay_each(subnet_t, s, myself->subnet_tree)
|
||||
send_add_subnet(c, s);
|
||||
|
|
|
@ -111,7 +111,7 @@ bool send_req_key(node_t *to) {
|
|||
sptps_stop(&to->sptps);
|
||||
to->status.validkey = false;
|
||||
to->status.waitingforkey = true;
|
||||
to->last_req_key = time(NULL);
|
||||
to->last_req_key = now.tv_sec;
|
||||
to->incompression = myself->incompression;
|
||||
return sptps_start(&to->sptps, to, true, true, myself->connection->ecdsa, to->ecdsa, label, sizeof label, send_initial_sptps_data, receive_sptps_record);
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, in
|
|||
sptps_stop(&from->sptps);
|
||||
from->status.validkey = false;
|
||||
from->status.waitingforkey = true;
|
||||
from->last_req_key = time(NULL);
|
||||
from->last_req_key = now.tv_sec;
|
||||
sptps_start(&from->sptps, from, false, true, myself->connection->ecdsa, from->ecdsa, label, sizeof label, send_sptps_data, receive_sptps_record);
|
||||
sptps_receive_data(&from->sptps, buf, len);
|
||||
return true;
|
||||
|
|
|
@ -89,7 +89,7 @@ bool termreq_h(connection_t *c, const char *request) {
|
|||
|
||||
bool send_ping(connection_t *c) {
|
||||
c->status.pinged = true;
|
||||
c->last_ping_time = time(NULL);
|
||||
c->last_ping_time = now.tv_sec;
|
||||
|
||||
return send_request(c, "%d", PING);
|
||||
}
|
||||
|
|
|
@ -229,7 +229,7 @@ static void learn_mac(mac_t *address) {
|
|||
|
||||
subnet = new_subnet();
|
||||
subnet->type = SUBNET_MAC;
|
||||
subnet->expires = time(NULL) + macexpire;
|
||||
subnet->expires = now.tv_sec + macexpire;
|
||||
subnet->net.mac.address = *address;
|
||||
subnet->weight = 10;
|
||||
subnet_add(myself, subnet);
|
||||
|
@ -244,7 +244,7 @@ static void learn_mac(mac_t *address) {
|
|||
timeout_add(&age_subnets_timeout, age_subnets, NULL, &(struct timeval){10, rand() % 100000});
|
||||
} else {
|
||||
if(subnet->expires)
|
||||
subnet->expires = time(NULL) + macexpire;
|
||||
subnet->expires = now.tv_sec + macexpire;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -77,8 +77,8 @@ int main(int argc, char *argv[]) {
|
|||
memset(&hint, 0, sizeof hint);
|
||||
|
||||
hint.ai_family = AF_UNSPEC;
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
hint.ai_protocol = IPPROTO_TCP;
|
||||
hint.ai_socktype = datagram ? SOCK_DGRAM : SOCK_STREAM;
|
||||
hint.ai_protocol = datagram ? IPPROTO_UDP : IPPROTO_TCP;
|
||||
hint.ai_flags = initiator ? 0 : AI_PASSIVE;
|
||||
|
||||
if(getaddrinfo(initiator ? argv[3] : NULL, initiator ? argv[4] : argv[3], &hint, &ai) || !ai) {
|
||||
|
@ -86,7 +86,7 @@ int main(int argc, char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int sock = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
|
||||
int sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||
if(sock < 0) {
|
||||
fprintf(stderr, "Could not create socket: %s\n", strerror(errno));
|
||||
return 1;
|
||||
|
@ -106,6 +106,8 @@ int main(int argc, char *argv[]) {
|
|||
fprintf(stderr, "Could not bind socket: %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!datagram) {
|
||||
if(listen(sock, 1)) {
|
||||
fprintf(stderr, "Could not listen on socket: %s\n", strerror(errno));
|
||||
return 1;
|
||||
|
@ -117,6 +119,23 @@ int main(int argc, char *argv[]) {
|
|||
fprintf(stderr, "Could not accept connection: %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Listening...\n");
|
||||
|
||||
char buf[65536];
|
||||
struct sockaddr addr;
|
||||
socklen_t addrlen = sizeof addr;
|
||||
|
||||
if(recvfrom(sock, buf, sizeof buf, MSG_PEEK, &addr, &addrlen) <= 0) {
|
||||
fprintf(stderr, "Could not read from socket: %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(connect(sock, &addr, addrlen)) {
|
||||
fprintf(stderr, "Could not accept connection: %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Connected\n");
|
||||
}
|
||||
|
|
|
@ -112,11 +112,10 @@ static void usage(bool status) {
|
|||
"\n"
|
||||
"Valid commands are:\n"
|
||||
" init [name] Create initial configuration files.\n"
|
||||
" config Change configuration:\n"
|
||||
" [get] VARIABLE - print current value of VARIABLE\n"
|
||||
" [set] VARIABLE VALUE - set VARIABLE to VALUE\n"
|
||||
" add VARIABLE VALUE - add VARIABLE with the given VALUE\n"
|
||||
" del VARIABLE [VALUE] - remove VARIABLE [only ones with watching VALUE]\n"
|
||||
" get VARIABLE Print current value of VARIABLE\n"
|
||||
" set VARIABLE VALUE Set VARIABLE to VALUE\n"
|
||||
" add VARIABLE VALUE Add VARIABLE with the given VALUE\n"
|
||||
" del VARIABLE [VALUE] Remove VARIABLE [only ones with watching VALUE]\n"
|
||||
" start [tincd options] Start tincd.\n"
|
||||
" stop Stop tincd.\n"
|
||||
" restart Restart tincd.\n"
|
||||
|
@ -1148,7 +1147,7 @@ static int cmd_top(int argc, char *argv[]) {
|
|||
top(fd);
|
||||
return 0;
|
||||
#else
|
||||
fprintf(stderr, "This version of tincctl was compiled without support for the curses library.\n");
|
||||
fprintf(stderr, "This version of tinc was compiled without support for the curses library.\n");
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
@ -1199,9 +1198,10 @@ static int rstrip(char *value) {
|
|||
return len;
|
||||
}
|
||||
|
||||
static char *get_my_name() {
|
||||
static char *get_my_name(bool verbose) {
|
||||
FILE *f = fopen(tinc_conf, "r");
|
||||
if(!f) {
|
||||
if(verbose)
|
||||
fprintf(stderr, "Could not open %s: %s\n", tinc_conf, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1228,6 +1228,7 @@ static char *get_my_name() {
|
|||
}
|
||||
|
||||
fclose(f);
|
||||
if(verbose)
|
||||
fprintf(stderr, "Could not find Name in %s.\n", tinc_conf);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1309,6 +1310,9 @@ static int cmd_config(int argc, char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
if(strcasecmp(argv[0], "config"))
|
||||
argv--, argc++;
|
||||
|
||||
int action = -2;
|
||||
if(!strcasecmp(argv[1], "get")) {
|
||||
argv++, argc--;
|
||||
|
@ -1402,7 +1406,7 @@ static int cmd_config(int argc, char *argv[]) {
|
|||
/* Should this go into our own host config file? */
|
||||
|
||||
if(!node && !(variables[i].type & VAR_SERVER)) {
|
||||
node = get_my_name();
|
||||
node = get_my_name(true);
|
||||
if(!node)
|
||||
return 1;
|
||||
}
|
||||
|
@ -1692,6 +1696,9 @@ static int cmd_generate_keys(int argc, char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
if(!name)
|
||||
name = get_my_name(false);
|
||||
|
||||
return !(rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true) && ecdsa_keygen(true));
|
||||
}
|
||||
|
||||
|
@ -1701,6 +1708,9 @@ static int cmd_generate_rsa_keys(int argc, char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
if(!name)
|
||||
name = get_my_name(false);
|
||||
|
||||
return !rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true);
|
||||
}
|
||||
|
||||
|
@ -1710,6 +1720,9 @@ static int cmd_generate_ecdsa_keys(int argc, char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
if(!name)
|
||||
name = get_my_name(false);
|
||||
|
||||
return !ecdsa_keygen(true);
|
||||
}
|
||||
|
||||
|
@ -1831,7 +1844,7 @@ static int cmd_export(int argc, char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
char *name = get_my_name();
|
||||
char *name = get_my_name(true);
|
||||
if(!name)
|
||||
return 1;
|
||||
|
||||
|
@ -1961,6 +1974,7 @@ static int cmd_exchange_all(int argc, char *argv[]) {
|
|||
static const struct {
|
||||
const char *command;
|
||||
int (*function)(int argc, char *argv[]);
|
||||
bool hidden;
|
||||
} commands[] = {
|
||||
{"start", cmd_start},
|
||||
{"stop", cmd_stop},
|
||||
|
@ -1976,7 +1990,11 @@ static const struct {
|
|||
{"pcap", cmd_pcap},
|
||||
{"log", cmd_log},
|
||||
{"pid", cmd_pid},
|
||||
{"config", cmd_config},
|
||||
{"config", cmd_config, true},
|
||||
{"add", cmd_config},
|
||||
{"del", cmd_config},
|
||||
{"get", cmd_config},
|
||||
{"set", cmd_config},
|
||||
{"init", cmd_init},
|
||||
{"generate-keys", cmd_generate_keys},
|
||||
{"generate-rsa-keys", cmd_generate_rsa_keys},
|
||||
|
@ -2003,7 +2021,7 @@ static char *complete_command(const char *text, int state) {
|
|||
i++;
|
||||
|
||||
while(commands[i].command) {
|
||||
if(!strncasecmp(commands[i].command, text, strlen(text)))
|
||||
if(!commands[i].hidden && !strncasecmp(commands[i].command, text, strlen(text)))
|
||||
return xstrdup(commands[i].command);
|
||||
i++;
|
||||
}
|
||||
|
@ -2030,31 +2048,14 @@ static char *complete_dump(const char *text, int state) {
|
|||
}
|
||||
|
||||
static char *complete_config(const char *text, int state) {
|
||||
const char *sub[] = {"get", "set", "add", "del"};
|
||||
static int i;
|
||||
if(!state) {
|
||||
i = 0;
|
||||
if(!strchr(rl_line_buffer + 7, ' '))
|
||||
i = -4;
|
||||
else {
|
||||
bool found = false;
|
||||
for(int i = 0; i < 4; i++) {
|
||||
if(!strncasecmp(rl_line_buffer + 7, sub[i], strlen(sub[i])) && rl_line_buffer[7 + strlen(sub[i])] == ' ') {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
|
||||
while(i < 0 || variables[i].name) {
|
||||
if(i < 0 && !strncasecmp(sub[i + 4], text, strlen(text)))
|
||||
return xstrdup(sub[i + 4]);
|
||||
if(i >= 0) {
|
||||
if(!state)
|
||||
i = 0;
|
||||
else
|
||||
i++;
|
||||
|
||||
while(variables[i].name) {
|
||||
char *dot = strchr(text, '.');
|
||||
if(dot) {
|
||||
if((variables[i].type & VAR_HOST) && !strncasecmp(variables[i].name, dot + 1, strlen(dot + 1))) {
|
||||
|
@ -2066,7 +2067,6 @@ static char *complete_config(const char *text, int state) {
|
|||
if(!strncasecmp(variables[i].name, text, strlen(text)))
|
||||
return xstrdup(variables[i].name);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
|
@ -2118,7 +2118,13 @@ static char **completion (const char *text, int start, int end) {
|
|||
matches = rl_completion_matches(text, complete_command);
|
||||
else if(!strncasecmp(rl_line_buffer, "dump ", 5))
|
||||
matches = rl_completion_matches(text, complete_dump);
|
||||
else if(!strncasecmp(rl_line_buffer, "config ", 7))
|
||||
else if(!strncasecmp(rl_line_buffer, "add ", 4))
|
||||
matches = rl_completion_matches(text, complete_config);
|
||||
else if(!strncasecmp(rl_line_buffer, "del ", 4))
|
||||
matches = rl_completion_matches(text, complete_config);
|
||||
else if(!strncasecmp(rl_line_buffer, "get ", 4))
|
||||
matches = rl_completion_matches(text, complete_config);
|
||||
else if(!strncasecmp(rl_line_buffer, "set ", 4))
|
||||
matches = rl_completion_matches(text, complete_config);
|
||||
else if(!strncasecmp(rl_line_buffer, "info ", 5))
|
||||
matches = rl_completion_matches(text, complete_info);
|
||||
|
|
|
@ -346,7 +346,8 @@ int main(int argc, char **argv) {
|
|||
|
||||
/* Slllluuuuuuurrrrp! */
|
||||
|
||||
srand(time(NULL));
|
||||
gettimeofday(&now, NULL);
|
||||
srand(now.tv_sec + now.tv_usec);
|
||||
crypto_init();
|
||||
|
||||
if(!read_server_config())
|
||||
|
|
Loading…
Reference in a new issue