From: Saverio Proto Date: Thu, 17 Apr 2014 22:19:30 +0000 (+0200) Subject: Merge remote-tracking branch 'origin/master' into saverio X-Git-Url: http://git.meshlink.io/?p=meshlink;a=commitdiff_plain;h=22f930e7c6352a1b43b1605799925e10fced254a;hp=82bbb6f1947bfb98a52422d7202aef331d36b1d7 Merge remote-tracking branch 'origin/master' into saverio --- diff --git a/COPYING.README b/COPYING.README deleted file mode 100644 index bb776e71..00000000 --- a/COPYING.README +++ /dev/null @@ -1,6 +0,0 @@ -The following applies to MeshLink: - -This program is released under the GPL with the additional exemption that -compiling, linking, and/or using OpenSSL is allowed. You may provide binary -packages linked to the OpenSSL libraries, provided that all other requirements -of the GPL are met. diff --git a/README b/README index 57c28699..714d8211 100644 --- a/README +++ b/README @@ -21,11 +21,7 @@ Please do not use this library yet. Requirements ------------ -In order to compile MeshLink, you will need a GNU C compiler environment. Please -ensure you have the latest stable versions of all the required libraries: - -- OpenSSL (http://www.openssl.org/) version 1.0.0 or later, with support for - elliptic curve cryptography (ECC) and Galois counter mode (GCM) enabled. +In order to compile MeshLink, you will need a GNU C compiler environment. The following libraries are used by default, but can be disabled if necessary: @@ -46,4 +42,4 @@ Other noteworthy features are: - IPv6 support - NAT traversal (requires at least one node that is not behind a NAT) - Ed25519 keys (TBD) -- AES-256-GCM encryption and message authentication +- ChaCha-Poly1305 encryption and message authentication diff --git a/README.android b/README.android index 4d8a0e9a..42b21368 100644 --- a/README.android +++ b/README.android @@ -5,16 +5,9 @@ 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 MeshLink: git clone git://meshlink.io/meshlink cd meshlink 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/ +CC=/tmp/my-android-toolchain/bin/arm-linux-androideabi-gcc ./configure --host=arm-linux make -j5 diff --git a/README.git b/README.git index 21488936..d973ca23 100644 --- a/README.git +++ b/README.git @@ -1,7 +1,6 @@ Before you can start compiling MeshLink from a fresh git clone, you have to install the very latest versions of the following packages: -- OpenSSL - zlib - GCC - automake diff --git a/configure.ac b/configure.ac index 1d66abb1..b163474a 100644 --- a/configure.ac +++ b/configure.ac @@ -6,6 +6,7 @@ AC_CONFIG_SRCDIR([src/libmeshlink.c]) AC_GNU_SOURCE AM_INIT_AUTOMAKE([check-news std-options subdir-objects -Wall]) AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_MACRO_DIR([m4]) # Enable GNU extensions. # Define this here, not in acconfig's @TOP@ section, since definitions @@ -178,8 +179,6 @@ dnl These are defined in files in m4/ MeshLink_ZLIB -MeshLink_OPENSSL - AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile m4/Makefile test/Makefile]) AC_OUTPUT diff --git a/doc/CONNECTIVITY b/doc/CONNECTIVITY deleted file mode 100644 index 05a9eaf3..00000000 --- a/doc/CONNECTIVITY +++ /dev/null @@ -1,43 +0,0 @@ -This document describes how nodes in a VPN find and connect to eachother and -maintain a stable network. - - Copyright 2001-2006 Guus Sliepen - - Permission is granted to make and distribute verbatim copies of - this documentation provided the copyright notice and this - permission notice are preserved on all copies. - - Permission is granted to copy and distribute modified versions of - this documentation under the conditions for verbatim copying, - provided that the entire resulting derived work is distributed - under the terms of a permission notice identical to this one. - -1. Synchronisation -================== - -Each tinc daemon has zero or more connections to other tinc daemons. It will -try to keep its own information synchronised with the other tinc daemons. If -one of its peers sends information, the tinc daemon will check if it is new -information. If so, it will update its own information and forward the new -information to all the other peers. - -This scheme will make sure that after a short amount of time all tinc daemons -share the same information. It will also almost completely prevent information -from looping, because "new" information that is already known is ignored and -not forwarded any further. However, since information can also be deleted -there's the possibility of a looping sequence of add/delete messages. This is -resolved by additionaly adding a unique identifier to each broadcasted message. -Messages are dropped if the same message with that identifier has already been -seen. - -2. Routing -========== - -Every node tells its peers to which other peers it is connected. This way -every node will eventually know every connection every node has on the VPN. -Each node will use graph algorithms to determine if other nodes are reachable or not and -what the best route is to other nodes. - -Because all nodes share the same information, using a deterministic algorithm -each node will calculate the same minimum spanning tree for the entire VPN. -The MST will be used to send broadcast VPN packets. diff --git a/doc/Makefile.am b/doc/Makefile.am index 56d81e32..9fa98b6b 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,12 +1,12 @@ ## Process this file with automake to get Makefile.in -info_TEXINFOS = tinc.texi +info_TEXINFOS = meshlink.texi man_MANS = -EXTRA_DIST = tincinclude.texi.in +EXTRA_DIST = include.texi.in -CLEANFILES = *.html tincinclude.texi +CLEANFILES = *.html include.texi # Use `ginstall' in the definition of man_MANS to avoid # confusion with the `install' target. The install rule transforms `ginstall' @@ -22,7 +22,7 @@ substitute = sed \ -e s,'@sysconfdir\@',"$(sysconfdir)",g \ -e s,'@localstatedir\@',"$(localstatedir)",g -tincinclude.texi: tincinclude.texi.in +include.texi: include.texi.in $(substitute) $? > $@ -tinc.texi: tincinclude.texi +meshlink.texi: include.texi diff --git a/doc/NETWORKING b/doc/NETWORKING deleted file mode 100644 index eb4f6bc6..00000000 --- a/doc/NETWORKING +++ /dev/null @@ -1,81 +0,0 @@ -This is the network infrastructure documentation for tinc, a Virtual Private -Network daemon. - - Copyright 2001-2006 Guus Sliepen - - Permission is granted to make and distribute verbatim copies of - this documentation provided the copyright notice and this - permission notice are preserved on all copies. - - Permission is granted to copy and distribute modified versions of - this documentation under the conditions for verbatim copying, - provided that the entire resulting derived work is distributed - under the terms of a permission notice identical to this one. - -1. Packet flow -============== - -There are two directions for packets. There are packets received from the tap -device that have to be sent out to other tinc daemon, and there are packets -that are received from other tinc daemons which have to be send to the tap -device. The first direction will be called the outgoing direction, while the -latter will be called the incoming direction. - -1.1 Outgoing flow ------------------ - - handle_tap_input() - | - | - V - route_outgoing() - | - | - V - send_packet() ---- - / \ / \ - / \ | queue - V V V / -send_tcppacket() send_udppacket()-- - -Packets are read from the tap device by handle_tap_input(). The packets will be -marked as coming from ourself, and are then handled by route_outgoing(). This -function will determine the destination tinc daemon this packet has to be sent -to, and in the future it may also determine if this packet has to be broadcast -or multicast. route_outgoing() will call send_packet() (in case of -broad/multicast several times). send_packet() will check the destination -connection_t entry to see if it is a valid destination, and whether it has to -be sent via TCP or UDP. It will then either call send_tcppacket() or -send_udppacket(). Since a different key is used for UDP packets, which might -not be available at that time, send_udppacket() might put the packet in a queue -and send a REQ_KEY to the destination tinc daemon. If the key has been retrieved, -the packet will be fed to send_udppacket() again. - -1.2 Incoming flow ------------------ - - handle_vpn_input() - | - | - V -tcppacket_h() receive_udppacket() - \ / - \ / - V V - receive_packet() - | - | - V - route_incoming() - | - | - V - accept_packet() - -Packets from other tinc daemons can be received by tcppacket_h(), for TCP -packets, and receive_udppacket() via handle_vpn_input() for UDP packets. -receive_packet() actually does not have to do much, except logging and calling -route_incoming(), but it's there for symmetry with the scheme for the outgoing -flow. route_incoming() will change the MAC header of the packet if necessary to -let the kernel accept the packet after it has been sent to the tap device by -accept_packet(). diff --git a/doc/PROTOCOL b/doc/PROTOCOL deleted file mode 100644 index 3e2915bd..00000000 --- a/doc/PROTOCOL +++ /dev/null @@ -1,148 +0,0 @@ -This is the protocol documentation for tinc, a Virtual Private Network daemon. - - Copyright 2000-2006 Guus Sliepen , - 2000-2005 Ivo Timmmermans - - Permission is granted to make and distribute verbatim copies of - this documentation provided the copyright notice and this - permission notice are preserved on all copies. - - Permission is granted to copy and distribute modified versions of - this documentation under the conditions for verbatim copying, - provided that the entire resulting derived work is distributed - under the terms of a permission notice identical to this one. - -1. Protocols used in tinc -------------------------- - -tinc uses several protocols to function correctly. To enter the -network of tinc daemons that make up the virtual private network, tinc -makes TCP connections to other tinc daemons. It uses the "meta -protocol" for these connections. To exchange packets on the virtual -network, UDP connections are made and the "packet protocol" is used. -Tinc also needs to exchange network packets with the kernel. This is -done using the ethertap device or the universal TUN/TAP device that -can be found in various UNIX flavours. - -2. Packet protocol ------------------- - -Normal packets are sent without any state information, so the layout -is pretty basic. - -A data packet can only be sent if the encryption key, cipher and digest are -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 -retreive it. - -0 1 2 3 4 5 6 7 ... 97 98 99 100 -| seqno | data | MAC | -\____________________________________/\_______________/ - | | - encrypted using symmetric cipher digest - -The sequence number prevents replay attacks, the message authentication code -prevents altered packets from being accepted. - -3. Meta protocol ----------------- - -The meta protocol is used to tie all tinc daemons together, and -exchange information about which tinc daemon serves which virtual -subnet. - -The meta protocol consists of requests that can be sent to the other -side. Each request has a unique number and several parameters. All -requests are represented in the standard ASCII character set. It is -possible to use tools such as telnet or netcat to connect to a tinc -daemon and to read and write requests by hand, provided that one -understands the numeric codes sent. - -The authentication scheme is described in the SECURITY2 file. After a -succesful 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 -synchronised. - -daemon message --------------------------------------------------------------------------- -origin ADD_EDGE node1 node2 21.32.43.54 655 222 0 - | | | | | +-> options - | | | | +----> weight - | | | +--------> UDP port of node2 - | | +----------------> real address of node2 - | +-------------------------> name of destination node - +-------------------------------> name of source node - -origin ADD_SUBNET node 192.168.1.0/24 - | | +--> prefixlength - | +--------> network address - +------------------> owner of this subnet --------------------------------------------------------------------------- - -The ADD_EDGE messages are to inform other tinc daemons that a connection between -two nodes exist. The address of the destination node is available so that -VPN packets can be sent directly to that node. - -The ADD_SUBNET messages inform other tinc daemons that certain subnets belong -to certain nodes. tinc will use it to determine to which node a VPN packet has -to be sent. - -message ------------------------------------------------------------------- -DEL_EDGE node1 node2 - | +----> name of destination node - +----------> name of source node - -DEL_SUBNET node 192.168.1.0/24 - | | +--> prefixlength - | +--------> network address - +------------------> owner of this subnet ------------------------------------------------------------------- - -In case a connection between two daemons is closed or broken, DEL_EDGE messages -are sent to inform the other daemons of that fact. Each daemon will calculate a -new route to the the daemons, or mark them unreachable if there isn't any. - -message ------------------------------------------------------------------- -REQ_KEY origin destination - | +--> name of the tinc daemon it wants the key from - +----------> name of the daemon that wants the key - -ANS_KEY origin destination 4ae0b0a82d6e0078 91 64 4 - | | \______________/ | | +--> MAC length - | | | | +-----> digest algorithm - | | | +--------> cipher algorithm - | | +--> 128 bits key - | +--> name of the daemon that wants the key - +----------> name of the daemon that uses this key - -KEY_CHANGED origin - +--> daemon that has changed it's packet key --------------------------------------------------------------------------- - -The keys used to encrypt VPN packets are not sent out directly. This is -because it would generate a lot of traffic on VPNs with many daemons, and -chances are that not every tinc daemon will ever send a packet to every -other daemon. Instead, if a daemon needs a key it sends a request for it -via the meta connection of the nearest hop in the direction of the -destination. If any hop on the way has already learned the key, it will -act as a proxy and forward its copy back to the requestor. - -daemon message --------------------------------------------------------------------------- -origin PING -dest. PONG --------------------------------------------------------------------------- - -There is also a mechanism to check if hosts are still alive. Since network -failures or a crash can cause a daemon to be killed without properly -shutting down the TCP connection, this is necessary to keep an up to date -connection list. Pings are sent at regular intervals, except when there -is also some other traffic. A little bit of salt (random data) is added -with each PING and PONG message, to make sure that long sequences of PING/PONG -messages without any other traffic won't result in known plaintext. - -This basically covers everything that is sent over the meta connection by -tinc. diff --git a/doc/SECURITY2 b/doc/SECURITY2 deleted file mode 100644 index 56db6b60..00000000 --- a/doc/SECURITY2 +++ /dev/null @@ -1,121 +0,0 @@ -This is the security documentation for tinc, a Virtual Private Network daemon. - - Copyright 2001-2006 Guus Sliepen , - 2001-2006 Wessel Dankers - - Permission is granted to make and distribute verbatim copies of - this documentation provided the copyright notice and this - permission notice are preserved on all copies. - - Permission is granted to copy and distribute modified versions of - this documentation under the conditions for verbatim copying, - provided that the entire resulting derived work is distributed - under the terms of a permission notice identical to this one. - -Proposed new authentication scheme ----------------------------------- - -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. - -daemon message --------------------------------------------------------------------------- -client - -server - -client ID client 12 - | +---> version - +-------> name of tinc daemon - -server ID server 12 - | +---> version - +-------> name of tinc daemon - -client META_KEY 5f0823a93e35b69e...7086ec7866ce582b - \_________________________________/ - +-> RSAKEYLEN bits totally random string S1, - encrypted with server's public RSA key - -server META_KEY 6ab9c1640388f8f0...45d1a07f8a672630 - \_________________________________/ - +-> RSAKEYLEN bits totally random string S2, - encrypted with client's public RSA key - -From now on: - - the client will symmetrically encrypt outgoing traffic using S1 - - the server will symmetrically encrypt outgoing traffic using S2 - -client CHALLENGE da02add1817c1920989ba6ae2a49cecbda0 - \_________________________________/ - +-> CHALLEN bits totally random string H1 - -server CHALLENGE 57fb4b2ccd70d6bb35a64c142f47e61d57f - \_________________________________/ - +-> CHALLEN bits totally random string H2 - -client CHAL_REPLY 816a86 - +-> 160 bits SHA1 of H2 - -server CHAL_REPLY 928ffe - +-> 160 bits SHA1 of H1 - -After the correct challenge replies are recieved, both ends have proved -their identity. Further information is exchanged. - -client ACK 655 123 0 - | | +-> options - | +----> estimated weight - +--------> listening port of client - -server ACK 655 321 0 - | | +-> options - | +----> estimated weight - +--------> listening port of server --------------------------------------------------------------------------- - -This new scheme has several improvements, both in efficiency and security. - -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. - -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 crypto attack). It -also improves speed by a factor two, making the total speedup a factor 4. - -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. - -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. - -Fourth: the first thing that is send 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. - -Some things to be discussed: - - - What should CHALLEN be? Same as RSAKEYLEN? 256 bits? More/less? diff --git a/doc/include.texi.in b/doc/include.texi.in new file mode 100644 index 00000000..da4adc57 --- /dev/null +++ b/doc/include.texi.in @@ -0,0 +1,4 @@ +@set VERSION @VERSION@ +@set PACKAGE @PACKAGE@ +@set sysconfdir @sysconfdir@ +@set localstatedir @localstatedir@ diff --git a/doc/meshlink.texi b/doc/meshlink.texi new file mode 100644 index 00000000..50756342 --- /dev/null +++ b/doc/meshlink.texi @@ -0,0 +1,116 @@ +\input texinfo @c -*-texinfo-*- +@c %**start of header +@setfilename meshlink.info +@settitle MeshLink Manual +@setchapternewpage odd +@c %**end of header + +@include include.texi + +@ifinfo +@dircategory Networking tools +@direntry +* MeshLink: (MeshLink). The MeshLink library. +@end direntry + +This is the info manual for the MeshLink library version @value{VERSION}. + +Copyright @copyright{} 2014 Guus Sliepen . + +Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. +@end ifinfo + +@afourpaper +@paragraphindent none +@finalout + +@titlepage +@title The MeshLink library +@author Guus Sliepen + +@page +@vskip 0pt plus 1filll +This is the info manual for the MeshLink library version @value{VERSION}. + +Copyright @copyright{} 2014 Guus Sliepen + +Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. +@end titlepage + +@ifnottex +@c ================================================================== +@node Top +@top Top + +@menu +* Introduction:: +* About us:: +* Concept Index:: All used terms explained +@end menu +@end ifnottex + +@c ================================================================== +@node Introduction +@chapter Introduction + +The MeshLink library allows applications that link to it to connect to other +instances of itself, and exchange messages in a secure way. MeshLink provides +end-to-end encryption and authentication of messages with perfect forward +secrecy. The MeshLink library starts its own thread which handles all network +communications. The application only needs to register callbacks to get +notified of incoming messages and other important events. + +This manual will contain information on how to compile the MeshLink library itself, +as well as how to integrate the MeshLink library into your own applications. + + +@c ================================================================== +@node About us +@chapter About us + + +@menu +* Contact information:: +* Authors:: +@end menu + + +@c ================================================================== +@node Contact information +@section Contact information + +The MeshLink website is at @url{http://meshlink.io/}. + + +@c ================================================================== +@node Authors +@section Authors + +@table @asis +@item Guus Sliepen (@email{guus@@meshlink.io}) +@end table + +@c ================================================================== +@node Concept Index +@unnumbered Concept Index + +@c ================================================================== +@printindex cp + +@c ================================================================== +@contents +@bye diff --git a/doc/tinc.texi b/doc/tinc.texi deleted file mode 100644 index 555b816b..00000000 --- a/doc/tinc.texi +++ /dev/null @@ -1,3301 +0,0 @@ -\input texinfo @c -*-texinfo-*- -@c %**start of header -@setfilename tinc.info -@settitle tinc Manual -@setchapternewpage odd -@c %**end of header - -@include tincinclude.texi - -@ifinfo -@dircategory Networking tools -@direntry -* tinc: (tinc). The tinc Manual. -@end direntry - -This is the info manual for @value{PACKAGE} version @value{VERSION}, a Virtual Private Network daemon. - -Copyright @copyright{} 1998-2014 Ivo Timmermans, -Guus Sliepen and -Wessel Dankers . - -Permission is granted to make and distribute verbatim copies of this -manual provided the copyright notice and this permission notice are -preserved on all copies. - -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided that the -entire resulting derived work is distributed under the terms of a -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 -@author Ivo Timmermans and Guus Sliepen - -@page -@vskip 0pt plus 1filll -This is the info manual for @value{PACKAGE} version @value{VERSION}, a Virtual Private Network daemon. - -Copyright @copyright{} 1998-2014 Ivo Timmermans, -Guus Sliepen and -Wessel Dankers . - -Permission is granted to make and distribute verbatim copies of this -manual provided the copyright notice and this permission notice are -preserved on all copies. - -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided that the -entire resulting derived work is distributed under the terms of a -permission notice identical to this one. - -@end titlepage - -@ifnottex -@c ================================================================== -@node Top -@top Top - -@menu -* Introduction:: -* Preparations:: -* Installation:: -* Configuration:: -* Running tinc:: -* Controlling tinc:: -* Technical information:: -* Platform specific information:: -* About us:: -* Concept Index:: All used terms explained -@end menu -@end ifnottex - -@c ================================================================== -@node Introduction -@chapter Introduction - -@cindex tinc -Tinc is a Virtual Private Network (VPN) daemon that uses tunneling and -encryption to create a secure private network between hosts on the -Internet. - -Because the tunnel appears to the IP level network code as a normal -network device, there is no need to adapt any existing software. -The encrypted tunnels allows VPN sites to share information with each other -over the Internet without exposing any information to others. - -This document is the manual for tinc. Included are chapters on how to -configure your computer to use tinc, as well as the configuration -process of tinc itself. - -@menu -* Virtual Private Networks:: -* tinc:: About tinc -* Supported platforms:: -@end menu - -@c ================================================================== -@node Virtual Private Networks -@section Virtual Private Networks - -@cindex VPN -A Virtual Private Network or VPN is a network that can only be accessed -by a few elected computers that participate. This goal is achievable in -more than just one way. - -@cindex private -Private networks can consist of a single stand-alone Ethernet LAN. Or -even two computers hooked up using a null-modem cable. In these cases, -it is -obvious that the network is @emph{private}, no one can access it from the -outside. But if your computers are linked to the Internet, the network -is not private anymore, unless one uses firewalls to block all private -traffic. But then, there is no way to send private data to trusted -computers on the other end of the Internet. - -@cindex virtual -This problem can be solved by using @emph{virtual} networks. Virtual -networks can live on top of other networks, but they use encapsulation to -keep using their private address space so they do not interfere with -the Internet. Mostly, virtual networks appear like a single LAN, even though -they can span the entire world. But virtual networks can't be secured -by using firewalls, because the traffic that flows through it has to go -through the Internet, where other people can look at it. - -As is the case with either type of VPN, anybody could eavesdrop. Or -worse, alter data. Hence it's probably advisable to encrypt the data -that flows over the network. - -When one introduces encryption, we can form a true VPN. Other people may -see encrypted traffic, but if they don't know how to decipher it (they -need to know the key for that), they cannot read the information that flows -through the VPN. This is what tinc was made for. - - -@c ================================================================== -@node tinc -@section tinc - -@cindex vpnd -I really don't quite remember what got us started, but it must have been -Guus' idea. He wrote a simple implementation (about 50 lines of C) that -used the ethertap device that Linux knows of since somewhere -about kernel 2.1.60. It didn't work immediately and he improved it a -bit. At this stage, the project was still simply called "vpnd". - -Since then, a lot has changed---to say the least. - -@cindex tincd -Tinc now supports encryption, it consists of a single daemon (tincd) for -both the receiving and sending end, it has become largely -runtime-configurable---in short, it has become a full-fledged -professional package. - -@cindex traditional VPNs -@cindex scalability -Tinc also allows more than two sites to connect to eachother and form a single VPN. -Traditionally VPNs are created by making tunnels, which only have two endpoints. -Larger VPNs with more sites are created by adding more tunnels. -Tinc takes another approach: only endpoints are specified, -the software itself will take care of creating the tunnels. -This allows for easier configuration and improved scalability. - -A lot can---and will be---changed. We have a number of things that we would like to -see in the future releases of tinc. Not everything will be available in -the near future. Our first objective is to make tinc work perfectly as -it stands, and then add more advanced features. - -Meanwhile, we're always open-minded towards new ideas. And we're -available too. - - -@c ================================================================== -@node Supported platforms -@section Supported platforms - -@cindex platforms -Tinc has been verified to work under Linux, FreeBSD, OpenBSD, NetBSD, MacOS/X (Darwin), Solaris, and Windows (both natively and in a Cygwin environment), -with various hardware architectures. These are some of the platforms -that are supported by the universal tun/tap device driver or other virtual network device drivers. -Without such a driver, tinc will most -likely compile and run, but it will not be able to send or receive data -packets. - -@cindex release -For an up to date list of supported platforms, please check the list on -our website: -@uref{http://www.tinc-vpn.org/platforms/}. - -@c -@c -@c -@c -@c -@c -@c Preparing your system -@c -@c -@c -@c -@c - -@c ================================================================== -@node Preparations -@chapter Preparations - -This chapter contains information on how to prepare your system to -support tinc. - -@menu -* Configuring the kernel:: -* Libraries:: -@end menu - - -@c ================================================================== -@node Configuring the kernel -@section Configuring the kernel - -@menu -* Configuration of Linux kernels:: -* Configuration of FreeBSD kernels:: -* Configuration of OpenBSD kernels:: -* Configuration of NetBSD kernels:: -* Configuration of Solaris kernels:: -* Configuration of Darwin (MacOS/X) kernels:: -* Configuration of Windows:: -@end menu - - -@c ================================================================== -@node Configuration of Linux kernels -@subsection Configuration of Linux kernels - -@cindex Universal tun/tap -For tinc to work, you need a kernel that supports the Universal tun/tap device. -Most distributions come with kernels that already support this. -Here are the options you have to turn on when configuring a new kernel: - -@example -Code maturity level options -[*] Prompt for development and/or incomplete code/drivers -Network device support - Universal tun/tap device driver support -@end example - -It's not necessary to compile this driver as a module, even if you are going to -run more than one instance of tinc. - -If you decide to build the tun/tap driver as a kernel module, add these lines -to @file{/etc/modules.conf}: - -@example -alias char-major-10-200 tun -@end example - - -@c ================================================================== -@node Configuration of FreeBSD kernels -@subsection Configuration of FreeBSD kernels - -For FreeBSD version 4.1 and higher, tun and tap drivers are included in the default kernel configuration. -The tap driver can be loaded with @code{kldload if_tap}, or by adding @code{if_tap_load="YES"} to @file{/boot/loader.conf}. - - -@c ================================================================== -@node Configuration of OpenBSD kernels -@subsection Configuration of OpenBSD kernels - -For OpenBSD version 2.9 and higher, -the tun driver is included in the default kernel configuration. -There is also a kernel patch from @uref{http://diehard.n-r-g.com/stuff/openbsd/} -which adds a tap device to OpenBSD which should work with tinc, -but with recent versions of OpenBSD, -a tun device can act as a tap device by setting the link0 option with ifconfig. - - -@c ================================================================== -@node Configuration of NetBSD kernels -@subsection Configuration of NetBSD kernels - -For NetBSD version 1.5.2 and higher, -the tun driver is included in the default kernel configuration. - -Tunneling IPv6 may not work on NetBSD's tun device. - - -@c ================================================================== -@node Configuration of Solaris kernels -@subsection Configuration of Solaris kernels - -For Solaris 8 (SunOS 5.8) and higher, -the tun driver may or may not be included in the default kernel configuration. -If it isn't, the source can be downloaded from @uref{http://vtun.sourceforge.net/tun/}. -For x86 and sparc64 architectures, precompiled versions can be found at @uref{http://www.monkey.org/~dugsong/fragroute/}. -If the @file{net/if_tun.h} header file is missing, install it from the source package. - - -@c ================================================================== -@node Configuration of Darwin (MacOS/X) kernels -@subsection Configuration of Darwin (MacOS/X) kernels - -Tinc on Darwin relies on a tunnel driver for its data acquisition from the kernel. -Tinc supports either the driver from @uref{http://tuntaposx.sourceforge.net/}, -which supports both tun and tap style devices, -and also the driver from from @uref{http://chrisp.de/en/projects/tunnel.html}. -The former driver is recommended. -The tunnel driver must be loaded before starting tinc with the following command: - -@example -kmodload tunnel -@end example - - -@c ================================================================== -@node Configuration of Windows -@subsection Configuration of Windows - -You will need to install the latest TAP-Win32 driver from OpenVPN. -You can download it from @uref{http://openvpn.sourceforge.net}. -Using the Network Connections control panel, -configure the TAP-Win32 network interface in the same way as you would do from the tinc-up script, -as explained in the rest of the documentation. - - -@c ================================================================== -@node Libraries -@section Libraries - -@cindex requirements -@cindex libraries -Before you can configure or build tinc, you need to have the OpenSSL, zlib, -lzo, curses and readline libraries installed on your system. If you try to -configure tinc without having them installed, configure will give you an error -message, and stop. - -@menu -* OpenSSL:: -* zlib:: -* lzo:: -* libcurses:: -* libreadline:: -@end menu - - -@c ================================================================== -@node OpenSSL -@subsection OpenSSL - -@cindex OpenSSL -For all cryptography-related functions, tinc uses the functions provided -by the OpenSSL library. - -If this library is not installed, you wil get an error when configuring -tinc for build. Support for running tinc with other cryptographic libraries -installed @emph{may} be added in the future. - -You can use your operating system's package manager to install this if -available. Make sure you install the development AND runtime versions -of this package. - -If you have to install OpenSSL manually, you can get the source code -from @url{http://www.openssl.org/}. Instructions on how to configure, -build and install this package are included within the package. Please -make sure you build development and runtime libraries (which is the -default). - -If you installed the OpenSSL libraries from source, it may be necessary -to let configure know where they are, by passing configure one of the ---with-openssl-* parameters. - -@example ---with-openssl=DIR OpenSSL library and headers prefix ---with-openssl-include=DIR OpenSSL headers directory - (Default is OPENSSL_DIR/include) ---with-openssl-lib=DIR OpenSSL library directory - (Default is OPENSSL_DIR/lib) -@end example - - -@subsubheading License - -@cindex license -The complete source code of tinc is covered by the GNU GPL version 2. -Since the license under which OpenSSL is distributed is not directly -compatible with the terms of the GNU GPL -@uref{http://www.openssl.org/support/faq.html#LEGAL2}, we -include an exemption to the GPL (see also the file COPYING.README) to allow -everyone to create a statically or dynamically linked executable: - -@quotation -This program is released under the GPL with the additional exemption -that compiling, linking, and/or using OpenSSL is allowed. You may -provide binary packages linked to the OpenSSL libraries, provided that -all other requirements of the GPL are met. -@end quotation - -Since the LZO library used by tinc is also covered by the GPL, -we also present the following exemption: - -@quotation -Hereby I grant a special exception to the tinc VPN project -(http://www.tinc-vpn.org/) to link the LZO library with the OpenSSL library -(http://www.openssl.org). - -Markus F.X.J. Oberhumer -@end quotation - - -@c ================================================================== -@node zlib -@subsection zlib - -@cindex zlib -For the optional compression of UDP packets, tinc uses the functions provided -by the zlib library. - -If this library is not installed, you wil get an error when running the -configure script. You can either install the zlib library, or disable support -for zlib compression by using the "--disable-zlib" option when running the -configure script. Note that if you disable support for zlib, the resulting -binary will not work correctly on VPNs where zlib compression is used. - -You can use your operating system's package manager to install this if -available. Make sure you install the development AND runtime versions -of this package. - -If you have to install zlib manually, you can get the source code -from @url{http://www.gzip.org/zlib/}. Instructions on how to configure, -build and install this package are included within the package. Please -make sure you build development and runtime libraries (which is the -default). - - -@c ================================================================== -@node lzo -@subsection lzo - -@cindex lzo -Another form of compression is offered using the LZO library. - -If this library is not installed, you wil get an error when running the -configure script. You can either install the LZO library, or disable support -for LZO compression by using the "--disable-lzo" option when running the -configure script. Note that if you disable support for LZO, the resulting -binary will not work correctly on VPNs where LZO compression is used. - -You can use your operating system's package manager to install this if -available. Make sure you install the development AND runtime versions -of this package. - -If you have to install lzo manually, you can get the source code -from @url{http://www.oberhumer.com/opensource/lzo/}. Instructions on how to configure, -build and install this package are included within the package. Please -make sure you build development and runtime libraries (which is the -default). - - -@c ================================================================== -@node libcurses -@subsection libcurses - -@cindex libcurses -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 -all functionality that depends on a curses library by using the -"--disable-curses" option when running the configure script. - -There are several curses libraries. It is recommended that you install -"ncurses" (@url{http://invisible-island.net/ncurses/}), -however other curses libraries should also work. -In particular, "PDCurses" (@url{http://pdcurses.sourceforge.net/}) -is recommended if you want to compile tinc for Windows. - -You can use your operating system's package manager to install this if -available. Make sure you install the development AND runtime versions -of this package. - - -@c ================================================================== -@node libreadline -@subsection libreadline - -@cindex libreadline -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 -disable all functionality that depends on a readline library by using the -"--disable-readline" option when running the configure script. - -You can use your operating system's package manager to install this if -available. Make sure you install the development AND runtime versions -of this package. - -If you have to install libreadline manually, you can get the source code from -@url{http://www.gnu.org/software/readline/}. Instructions on how to configure, -build and install this package are included within the package. Please make -sure you build development and runtime libraries (which is the default). - - -@c -@c -@c -@c Installing tinc -@c -@c -@c -@c - -@c ================================================================== -@node Installation -@chapter Installation - -If you use Debian, you may want to install one of the -precompiled packages for your system. These packages are equipped with -system startup scripts and sample configurations. - -If you cannot use one of the precompiled packages, or you want to compile tinc -for yourself, you can use the source. The source is distributed under -the GNU General Public License (GPL). Download the source from the -@uref{http://www.tinc-vpn.org/download/, download page}, which has -the checksums of these files listed; you may wish to check these with -md5sum before continuing. - -Tinc comes in a convenient autoconf/automake package, which you can just -treat the same as any other package. Which is just untar it, type -`./configure' and then `make'. -More detailed instructions are in the file @file{INSTALL}, which is -included in the source distribution. - -@menu -* Building and installing tinc:: -* System files:: -@end menu - - -@c ================================================================== -@node Building and installing tinc -@section Building and installing tinc - -Detailed instructions on configuring the source, building tinc and installing tinc -can be found in the file called @file{INSTALL}. - -@cindex binary package -If you happen to have a binary package for tinc for your distribution, -you can use the package management tools of that distribution to install tinc. -The documentation that comes along with your distribution will tell you how to do that. - -@menu -* Darwin (MacOS/X) build environment:: -* Cygwin (Windows) build environment:: -* MinGW (Windows) build environment:: -@end menu - - -@c ================================================================== -@node Darwin (MacOS/X) build environment -@subsection Darwin (MacOS/X) build environment - -In order to build tinc on Darwin, you need to install the MacOS/X Developer Tools -from @uref{http://developer.apple.com/tools/macosxtools.html} and -a recent version of Fink from @uref{http://www.finkproject.org/}. - -After installation use fink to download and install the following packages: -autoconf25, automake, dlcompat, m4, openssl, zlib and lzo. - -@c ================================================================== -@node Cygwin (Windows) build environment -@subsection Cygwin (Windows) build environment - -If Cygwin hasn't already been installed, install it directly from -@uref{http://www.cygwin.com/}. - -When tinc is compiled in a Cygwin environment, it can only be run in this environment, -but all programs, including those started outside the Cygwin environment, will be able to use the VPN. -It will also support all features. - -@c ================================================================== -@node MinGW (Windows) build environment -@subsection MinGW (Windows) build environment - -You will need to install the MinGW environment from @uref{http://www.mingw.org}. - -When tinc is compiled using MinGW it runs natively under Windows, -it is not necessary to keep MinGW installed. - -When detaching, tinc will install itself as a service, -which will be restarted automatically after reboots. - - -@c ================================================================== -@node System files -@section System files - -Before you can run tinc, you must make sure you have all the needed -files on your system. - -@menu -* Device files:: -* Other files:: -@end menu - - -@c ================================================================== -@node Device files -@subsection Device files - -@cindex device files -Most operating systems nowadays come with the necessary device files by default, -or they have a mechanism to create them on demand. - -If you use Linux and do not have udev installed, -you may need to create the following device file if it does not exist: - -@example -mknod -m 600 /dev/net/tun c 10 200 -@end example - - -@c ================================================================== -@node Other files -@subsection Other files - -@subsubheading @file{/etc/networks} - -You may add a line to @file{/etc/networks} so that your VPN will get a -symbolic name. For example: - -@example -myvpn 10.0.0.0 -@end example - -@subsubheading @file{/etc/services} - -@cindex port numbers -You may add this line to @file{/etc/services}. The effect is that you -may supply a @samp{tinc} as a valid port number to some programs. The -number 655 is registered with the IANA. - -@example -tinc 655/tcp TINC -tinc 655/udp TINC -# Ivo Timmermans -@end example - - -@c -@c -@c -@c -@c Configuring tinc -@c -@c -@c -@c - - -@c ================================================================== -@node Configuration -@chapter Configuration - -@menu -* Configuration introduction:: -* Multiple networks:: -* How connections work:: -* Configuration files:: -* Network interfaces:: -* Example configuration:: -@end menu - -@c ================================================================== -@node Configuration introduction -@section Configuration introduction - -Before actually starting to configure tinc and editing files, -make sure you have read this entire section so you know what to expect. -Then, make it clear to yourself how you want to organize your VPN: -What are the nodes (computers running tinc)? -What IP addresses/subnets do they have? -What is the network mask of the entire VPN? -Do you need special firewall rules? -Do you have to set up masquerading or forwarding rules? -Do you want to run tinc in router mode or switch mode? -These questions can only be answered by yourself, -you will not find the answers in this documentation. -Make sure you have an adequate understanding of networks in general. -@cindex Network Administrators Guide -A good resource on networking is the -@uref{http://www.tldp.org/LDP/nag2/, Linux Network Administrators Guide}. - -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 -tinc -n @var{NETNAME} init @var{NAME} -@end example -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{tinc -n @var{NETNAME} import}. - -These steps are described in the subsections below. - - -@c ================================================================== -@node Multiple networks -@section Multiple networks - -@cindex multiple networks -@cindex netname - -In order to allow you to run more than one tinc daemon on one computer, -for instance if your computer is part of more than one VPN, -you can assign a @var{netname} to your VPN. -It is not required if you only run one tinc daemon, -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 tinc with the -n argument, -which will specify the netname. - -The effect of this option is that tinc will set its configuration -root to @file{@value{sysconfdir}/tinc/@var{netname}/}, where @var{netname} is your argument to the -n option. -You will also notice that log messages it appears in syslog as coming from @file{tinc.@var{netname}}, -and on Linux, unless specified otherwise, the name of the virtual network interface will be the same as the network name. - -However, it is not strictly necessary that you call tinc with the -n -option. If you don not use it, the network name will just be empty, and -tinc will look for files in @file{@value{sysconfdir}/tinc/} instead of -@file{@value{sysconfdir}/tinc/@var{netname}/}; -the configuration file will then be @file{@value{sysconfdir}/tinc/tinc.conf}, -and the host configuration files are expected to be in @file{@value{sysconfdir}/tinc/hosts/}. - - -@c ================================================================== -@node How connections work -@section How connections work - -When tinc starts up, it parses the command-line options and then -reads in the configuration file tinc.conf. -If it sees one or more `ConnectTo' values pointing to other tinc daemons in that file, -it will try to connect to those other daemons. -Whether this succeeds or not and whether `ConnectTo' is specified or not, -tinc will listen for incoming connection from other deamons. -If you did specify a `ConnectTo' value and the other side is not responding, -tinc will keep retrying. -This means that once started, tinc will stay running until you tell it to stop, -and failures to connect to other tinc daemons will not stop your tinc daemon -for trying again later. -This means you don't have to intervene if there are temporary network problems. - -@cindex client -@cindex server -There is no real distinction between a server and a client in tinc. -If you wish, you can view a tinc daemon without a `ConnectTo' value as a server, -and one which does specify such a value as a client. -It does not matter if two tinc daemons have a `ConnectTo' value pointing to each other however. - -Connections specified using `ConnectTo' are so-called meta-connections. -Tinc daemons exchange information about all other daemon they know about via these meta-connections. -After learning about all the daemons in the VPN, -tinc will create other connections as necessary in order to communicate with them. -For example, if there are three daemons named A, B and C, and A has @samp{ConnectTo = B} in its tinc.conf file, -and C has @samp{ConnectTo = B} in its tinc.conf file, then A will learn about C from B, -and will be able to exchange VPN packets with C without the need to have @samp{ConnectTo = C} in its tinc.conf file. - -It could be that some daemons are located behind a Network Address Translation (NAT) device, or behind a firewall. -In the above scenario with three daemons, if A and C are behind a NAT, -B will automatically help A and C punch holes through their NAT, -in a way similar to the STUN protocol, so that A and C can still communicate with each other directly. -It is not always possible to do this however, and firewalls might also prevent direct communication. -In that case, VPN packets between A and C will be forwarded by B. - -In effect, all nodes in the VPN will be able to talk to each other, as long as -their is a path of meta-connections between them, and whenever possible, two -nodes will communicate with each other directly. - - -@c ================================================================== -@node Configuration files -@section Configuration files - -The actual configuration of the daemon is done in the file -@file{@value{sysconfdir}/tinc/@var{netname}/tinc.conf} and at least one other file in the directory -@file{@value{sysconfdir}/tinc/@var{netname}/hosts/}. - -An optionnal directory @file{@value{sysconfdir}/tinc/@var{netname}/conf.d} can be added from which -any .conf file will be read. - -These file consists of comments (lines started with a #) or assignments -in the form of - -@example -Variable = Value. -@end example - -The variable names are case insensitive, and any spaces, tabs, newlines -and carriage returns are ignored. Note: it is not required that you put -in the `=' sign, but doing so improves readability. If you leave it -out, remember to replace it with at least one space character. - -The server configuration is complemented with host specific configuration (see -the next section). Although all host configuration options for the local node -listed in this document can also be put in -@file{@value{sysconfdir}/tinc/@var{netname}/tinc.conf}, it is recommended to -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 -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, -other comments are between square brackets. - -@menu -* Main configuration variables:: -* Host configuration variables:: -* Scripts:: -* How to configure:: -@end menu - - -@c ================================================================== -@node Main configuration variables -@subsection Main configuration variables - -@table @asis -@cindex AddressFamily -@item AddressFamily = (any) -This option affects the address family of listening and outgoing sockets. -If any is selected, then depending on the operating system -both IPv4 and IPv6 or just IPv6 listening sockets will be created. - -@cindex AutoConnect -@item AutoConnect = (0) [experimental] -If set to a non-zero value, -tinc will try to only have count meta connections to other nodes, -by automatically making or breaking connections to known nodes. -Higher values increase redundancy but also increase meta data overhead. -When using this option, a good value is 3. - -@cindex BindToAddress -@item BindToAddress = <@var{address}> [<@var{port}>] -This is the same as ListenAddress, however the address given with the BindToAddress option -will also be used for outgoing connections. -This is useful if your computer has more than one IPv4 or IPv6 address, -and you want tinc to only use a specific one for outgoing packets. - -@cindex BindToInterface -@item BindToInterface = <@var{interface}> [experimental] -If you have more than one network interface in your computer, tinc will -by default listen on all of them for incoming connections. It is -possible to bind tinc to a single interface like eth0 or ppp0 with this -variable. - -This option may not work on all platforms. -Also, on some platforms it will not actually bind to an interface, -but rather to the address that the interface has at the moment a socket is created. - -@cindex Broadcast -@item Broadcast = (mst) [experimental] -This option selects the way broadcast packets are sent to other daemons. -@emph{NOTE: all nodes in a VPN must use the same Broadcast mode, otherwise routing loops can form.} - -@table @asis -@item no -Broadcast packets are never sent to other nodes. - -@item mst -Broadcast packets are sent and forwarded via the VPN's Minimum Spanning Tree. -This ensures broadcast packets reach all nodes. - -@item direct -Broadcast packets are sent directly to all nodes that can be reached directly. -Broadcast packets received from other nodes are never forwarded. -If the IndirectData option is also set, broadcast packets will only be sent to nodes which we have a meta connection to. -@end table - -@cindex ConnectTo -@item ConnectTo = <@var{name}> -Specifies which other tinc daemon to connect to on startup. -Multiple ConnectTo variables may be specified, -in which case outgoing connections to each specified tinc daemon are made. -The names should be known to this tinc daemon -(i.e., there should be a host configuration file for the name on the ConnectTo line). - -If you don't specify a host with ConnectTo, -tinc won't try to connect to other daemons at all, -and will instead just listen for incoming connections. - -@cindex DecrementTTL -@item DecrementTTL = (no) [experimental] -When enabled, tinc will decrement the Time To Live field in IPv4 packets, or the Hop Limit field in IPv6 packets, -before forwarding a received packet to the virtual network device or to another node, -and will drop packets that have a TTL value of zero, -in which case it will send an ICMP Time Exceeded packet back. - -Do not use this option if you use switch mode and want to use IPv6. - -@cindex Device -@item Device = <@var{device}> (@file{/dev/tap0}, @file{/dev/net/tun} or other depending on platform) -The virtual network device to use. -Tinc will automatically detect what kind of device it is. -Note that you can only use one device per daemon. -Under Windows, use @var{Interface} instead of @var{Device}. -Note that you can only use one device per daemon. -See also @ref{Device files}. - -@cindex DeviceType -@item DeviceType = <@var{type}> (platform dependent) -The type of the virtual network device. -Tinc will normally automatically select the right type of tun/tap interface, and this option should not be used. -However, this option can be used to select one of the special interface types, if support for them is compiled in. - -@table @asis -@cindex dummy -@item dummy -Use a dummy interface. -No packets are ever read or written to a virtual network device. -Useful for testing, or when setting up a node that only forwards packets for other nodes. - -@cindex raw_socket -@item raw_socket -Open a raw socket, and bind it to a pre-existing -@var{Interface} (eth0 by default). -All packets are read from this interface. -Packets received for the local node are written to the raw socket. -However, at least on Linux, the operating system does not process IP packets destined for the local host. - -@cindex multicast -@item multicast -Open a multicast UDP socket and bind it to the address and port (separated by spaces) and optionally a TTL value specified using @var{Device}. -Packets are read from and written to this multicast socket. -This can be used to connect to UML, QEMU or KVM instances listening on the same multicast address. -Do NOT connect multiple tinc daemons to the same multicast address, this will very likely cause routing loops. -Also note that this can cause decrypted VPN packets to be sent out on a real network if misconfigured. - -@cindex UML -@item uml (not compiled in by default) -Create a UNIX socket with the filename specified by -@var{Device}, or @file{@value{localstatedir}/run/@var{netname}.umlsocket} -if not specified. -Tinc will wait for a User Mode Linux instance to connect to this socket. - -@cindex VDE -@item vde (not compiled in by default) -Uses the libvdeplug library to connect to a Virtual Distributed Ethernet switch, -using the UNIX socket specified by -@var{Device}, or @file{@value{localstatedir}/run/vde.ctl} -if not specified. -@end table - -Also, in case tinc does not seem to correctly interpret packets received from the virtual network device, -it can be used to change the way packets are interpreted: - -@table @asis -@item tun (BSD and Linux) -Set type to tun. -Depending on the platform, this can either be with or without an address family header (see below). - -@cindex tunnohead -@item tunnohead (BSD) -Set type to tun without an address family header. -Tinc will expect packets read from the virtual network device to start with an IP header. -On some platforms IPv6 packets cannot be read from or written to the device in this mode. - -@cindex tunifhead -@item tunifhead (BSD) -Set type to tun with an address family header. -Tinc will expect packets read from the virtual network device -to start with a four byte header containing the address family, -followed by an IP header. -This mode should support both IPv4 and IPv6 packets. - -@item tap (BSD and Linux) -Set type to tap. -Tinc will expect packets read from the virtual network device -to start with an Ethernet header. -@end table - -@cindex DirectOnly -@item DirectOnly = (no) [experimental] -When this option is enabled, packets that cannot be sent directly to the destination node, -but which would have to be forwarded by an intermediate node, are dropped instead. -When combined with the IndirectData option, -packets for nodes for which we do not have a meta connection with are also dropped. - -@cindex ECDSAPrivateKeyFile -@item ECDSAPrivateKeyFile = <@var{path}> (@file{@value{sysconfdir}/tinc/@var{netname}/ecdsa_key.priv}) -The file in which the private ECDSA key of this tinc daemon resides. -This is only used if ExperimentalProtocol is enabled. - -@cindex ExperimentalProtocol -@item ExperimentalProtocol = (yes) -When this option is enabled, the SPTPS protocol will be used when connecting to nodes that also support it. -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{tinc generate-ecdsa-keys}. - -@cindex Forwarding -@item Forwarding = (internal) [experimental] -This option selects the way indirect packets are forwarded. - -@table @asis -@item off -Incoming packets that are not meant for the local node, -but which should be forwarded to another node, are dropped. - -@item internal -Incoming packets that are meant for another node are forwarded by tinc internally. - -This is the default mode, and unless you really know you need another forwarding mode, don't change it. - -@item kernel -Incoming packets are always sent to the TUN/TAP device, even if the packets are not for the local node. -This is less efficient, but allows the kernel to apply its routing and firewall rules on them, -and can also help debugging. -@end table - -@cindex Hostnames -@item Hostnames = (no) -This option selects whether IP addresses (both real and on the VPN) -should be resolved. Since DNS lookups are blocking, it might affect -tinc's efficiency, even stopping the daemon for a few seconds everytime -it does a lookup if your DNS server is not responding. - -This does not affect resolving hostnames to IP addresses from the -configuration file, but whether hostnames should be resolved while logging. - -@cindex Interface -@item Interface = <@var{interface}> -Defines the name of the interface corresponding to the virtual network device. -Depending on the operating system and the type of device this may or may not actually set the name of the interface. -Under Windows, this variable is used to select which network interface will be used. -If you specified a Device, this variable is almost always already correctly set. - -@cindex ListenAddress -@item ListenAddress = <@var{address}> [<@var{port}>] -If your computer has more than one IPv4 or IPv6 address, tinc -will by default listen on all of them for incoming connections. -This option can be used to restrict which addresses tinc listens on. -Multiple ListenAddress variables may be specified, -in which case listening sockets for each specified address are made. - -If no @var{port} is specified, the socket will listen on the port specified by the Port option, -or to port 655 if neither is given. -To only listen on a specific port but not to a specific address, use "*" for the @var{address}. - -@cindex LocalDiscovery -@item LocalDiscovery = (no) -When enabled, tinc will try to detect peers that are on the same local network. -This will allow direct communication using LAN addresses, even if both peers are behind a NAT -and they only ConnectTo a third node outside the NAT, -which normally would prevent the peers from learning each other's LAN address. - -Currently, local discovery is implemented by sending broadcast packets to the LAN during path MTU discovery. -This feature may not work in all possible situations. - -@cindex LocalDiscoveryAddress -@item LocalDiscoveryAddress <@var{address}> -If this variable is specified, local discovery packets are sent to the given @var{address}. - -@cindex Mode -@item Mode = (router) -This option selects the way packets are routed to other daemons. - -@table @asis -@cindex router -@item router -In this mode Subnet -variables in the host configuration files will be used to form a routing table. -Only packets of routable protocols (IPv4 and IPv6) are supported in this mode. - -This is the default mode, and unless you really know you need another mode, don't change it. - -@cindex switch -@item switch -In this mode the MAC addresses of the packets on the VPN will be used to -dynamically create a routing table just like an Ethernet switch does. -Unicast, multicast and broadcast packets of every protocol that runs over Ethernet are supported in this mode -at the cost of frequent broadcast ARP requests and routing table updates. - -This mode is primarily useful if you want to bridge Ethernet segments. - -@cindex hub -@item hub -This mode is almost the same as the switch mode, but instead -every packet will be broadcast to the other daemons -while no routing table is managed. -@end table - -@cindex KeyExpire -@item KeyExpire = <@var{seconds}> (3600) -This option controls the time the encryption keys used to encrypt the data -are valid. It is common practice to change keys at regular intervals to -make it even harder for crackers, even though it is thought to be nearly -impossible to crack a single key. - -@cindex MACExpire -@item MACExpire = <@var{seconds}> (600) -This option controls the amount of time MAC addresses are kept before they are removed. -This only has effect when Mode is set to "switch". - -@cindex MaxConnectionBurst -@item MaxConnectionBurst = <@var{count}> (100) -This option controls how many connections tinc accepts in quick succession. -If there are more connections than the given number in a short time interval, -tinc will reduce the number of accepted connections to only one per second, -until the burst has passed. - -@cindex Name -@item Name = <@var{name}> [required] -This is a symbolic name for this connection. -The name should consist only of alfanumeric and underscore characters (a-z, A-Z, 0-9 and _), and is case sensitive. - -If Name starts with a $, then the contents of the environment variable that follows will be used. -In that case, invalid characters will be converted to underscores. -If Name is $HOST, but no such environment variable exist, -the hostname will be read using the gethostname() system call. - -@cindex PingInterval -@item PingInterval = <@var{seconds}> (60) -The number of seconds of inactivity that tinc will wait before sending a -probe to the other end. - -@cindex PingTimeout -@item PingTimeout = <@var{seconds}> (5) -The number of seconds to wait for a response to pings or to allow meta -connections to block. If the other end doesn't respond within this time, -the connection is terminated, and the others will be notified of this. - -@cindex PriorityInheritance -@item PriorityInheritance = (no) [experimental] -When this option is enabled the value of the TOS field of tunneled IPv4 packets -will be inherited by the UDP packets that are sent out. - -@cindex PrivateKey -@item PrivateKey = <@var{key}> [obsolete] -This is the RSA private key for tinc. However, for safety reasons it is -advised to store private keys of any kind in separate files. This prevents -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{tinc generate-keys}. It must be a full path, not a -relative directory. - -@cindex ProcessPriority -@item ProcessPriority = -When this option is used the priority of the tincd process will be adjusted. -Increasing the priority may help to reduce latency and packet loss on the VPN. - -@cindex Proxy -@item Proxy = socks4 | socks5 | http | exec @var{...} [experimental] -Use a proxy when making outgoing connections. -The following proxy types are currently supported: - -@table @asis -@cindex socks4 -@item socks4 <@var{address}> <@var{port}> [<@var{username}>] -Connects to the proxy using the SOCKS version 4 protocol. -Optionally, a @var{username} can be supplied which will be passed on to the proxy server. - -@cindex socks5 -@item socks5 <@var{address}> <@var{port}> [<@var{username}> <@var{password}>] -Connect to the proxy using the SOCKS version 5 protocol. -If a @var{username} and @var{password} are given, basic username/password authentication will be used, -otherwise no authentication will be used. - -@cindex http -@item http <@var{address}> <@var{port}> -Connects to the proxy and sends a HTTP CONNECT request. - -@cindex exec -@item exec <@var{command}> -Executes the given command which should set up the outgoing connection. -The environment variables @env{NAME}, @env{NODE}, @env{REMOTEADDRES} and @env{REMOTEPORT} are available. -@end table - -@cindex ReplayWindow -@item ReplayWindow = (16) -This is the size of the replay tracking window for each remote node, in bytes. -The window is a bitfield which tracks 1 packet per bit, so for example -the default setting of 16 will track up to 128 packets in the window. In high -bandwidth scenarios, setting this to a higher value can reduce packet loss from -the interaction of replay tracking with underlying real packet loss and/or -reordering. Setting this to zero will disable replay tracking completely and -pass all traffic, but leaves tinc vulnerable to replay-based attacks on your -traffic. - -@cindex StrictSubnets -@item StrictSubnets = (no) [experimental] -When this option is enabled tinc will only use Subnet statements which are -present in the host config files in the local -@file{@value{sysconfdir}/tinc/@var{netname}/hosts/} directory. -Subnets learned via connections to other nodes and which are not -present in the local host config files are ignored. - -@cindex TunnelServer -@item TunnelServer = (no) [experimental] -When this option is enabled tinc will no longer forward information between other tinc daemons, -and will only allow connections with nodes for which host config files are present in the local -@file{@value{sysconfdir}/tinc/@var{netname}/hosts/} directory. -Setting this options also implicitly sets StrictSubnets. - -@cindex UDPRcvBuf -@item UDPRcvBuf = (OS default) -Sets the socket receive buffer size for the UDP socket, in bytes. -If unset, the default buffer size will be used by the operating system. - -@cindex UDPSndBuf -@item UDPSndBuf = Pq OS default -Sets the socket send buffer size for the UDP socket, in bytes. -If unset, the default buffer size will be used by the operating system. - -@end table - - -@c ================================================================== -@node Host configuration variables -@subsection Host configuration variables - -@table @asis -@cindex Address -@item Address = <@var{IP address}|@var{hostname}> [] [recommended] -This variable is only required if you want to connect to this host. It -must resolve to the external IP address where the host can be reached, -not the one that is internal to the VPN. -If no port is specified, the default Port is used. -Multiple Address variables can be specified, in which case each address will be -tried until a working connection has been established. - -@cindex Cipher -@item Cipher = <@var{cipher}> (blowfish) -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) -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 -Fragmentation Needed or Packet too Big messages are dropped by firewalls. - -@cindex Compression -@item Compression = <@var{level}> (0) -This option sets the level of compression used for UDP packets. -Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib), -10 (fast lzo) and 11 (best lzo). - -@cindex Digest -@item Digest = <@var{digest}> (sha1) -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 = (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. -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 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) -This option controls the initial path MTU to this node. - -@cindex PMTUDiscovery -@item PMTUDiscovery = (yes) -When this option is enabled, tinc will try to discover the path MTU to this node. -After the path MTU has been discovered, it will be enforced on the VPN. - -@cindex Port -@item Port = <@var{port}> (655) -This is the port this tinc daemon listens on. -You can use decimal portnumbers or symbolic names (as listed in @file{/etc/services}). - -@cindex PublicKey -@item PublicKey = <@var{key}> [obsolete] -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{tinc generate-keys}. It must be a full path, not a relative -directory. - -@cindex PEM format -From version 1.0pre4 on tinc will store the public key directly into the -host configuration file in PEM format, the above two options then are not -necessary. Either the PEM format is used, or exactly -@strong{one of the above two options} must be specified -in each host configuration file, if you want to be able to establish a -connection with that host. - -@cindex Subnet -@item Subnet = <@var{address}[/@var{prefixlength}[#@var{weight}]]> -The subnet which this tinc daemon will serve. -Tinc tries to look up which other daemon it should send a packet to by searching the appropiate subnet. -If the packet matches a subnet, -it will be sent to the daemon who has this subnet in his host configuration file. -Multiple subnet lines can be specified for each daemon. - -Subnets can either be single MAC, IPv4 or IPv6 addresses, -in which case a subnet consisting of only that single address is assumed, -or they can be a IPv4 or IPv6 network address with a prefixlength. -For example, IPv4 subnets must be in a form like 192.168.1.0/24, -where 192.168.1.0 is the network address and 24 is the number of bits set in the netmask. -Note that subnets like 192.168.1.1/24 are invalid! -Read a networking HOWTO/FAQ/guide if you don't understand this. -IPv6 subnets are notated like fec0:0:0:1::/64. -MAC addresses are notated like 0:1a:2b:3c:4d:5e. - -@cindex CIDR notation -Prefixlength is the number of bits set to 1 in the netmask part; for -example: netmask 255.255.255.0 would become /24, 255.255.252.0 becomes -/22. This conforms to standard CIDR notation as described in -@uref{http://www.ietf.org/rfc/rfc1519.txt, RFC1519} - -A Subnet can be given a weight to indicate its priority over identical Subnets -owned by different nodes. The default weight is 10. Lower values indicate -higher priority. Packets will be sent to the node with the highest priority, -unless that node is not reachable, in which case the node with the next highest -priority will be tried, and so on. - -@cindex TCPonly -@item TCPonly = (no) -If this variable is set to yes, then the packets are tunnelled over a -TCP connection instead of a UDP connection. This is especially useful -for those who want to run a tinc daemon from behind a masquerading -firewall, or if UDP packet routing is disabled somehow. -Setting this options also implicitly sets IndirectData. - -@cindex Weight -@item Weight = -If this variable is set, it overrides the weight given to connections made with -another host. A higher weight means a lower priority is given to this -connection when broadcasting or forwarding packets. -@end table - - -@c ================================================================== -@node Scripts -@subsection Scripts - -@cindex scripts -Apart from reading the server and host configuration files, -tinc can also run scripts at certain moments. -Under Windows (not Cygwin), the scripts should have the extension @file{.bat} or @file{.cmd}. - -@table @file -@cindex tinc-up -@item @value{sysconfdir}/tinc/@var{netname}/tinc-up -This is the most important script. -If it is present it will be executed right after the tinc daemon has been -started and has connected to the virtual network device. -It should be used to set up the corresponding network interface, -but can also be used to start other things. -Under Windows you can use the Network Connections control panel instead of creating this script. - -@cindex tinc-down -@item @value{sysconfdir}/tinc/@var{netname}/tinc-down -This script is started right before the tinc daemon quits. - -@item @value{sysconfdir}/tinc/@var{netname}/hosts/@var{host}-up -This script is started when the tinc daemon with name @var{host} becomes reachable. - -@item @value{sysconfdir}/tinc/@var{netname}/hosts/@var{host}-down -This script is started when the tinc daemon with name @var{host} becomes unreachable. - -@item @value{sysconfdir}/tinc/@var{netname}/host-up -This script is started when any host becomes reachable. - -@item @value{sysconfdir}/tinc/@var{netname}/host-down -This script is started when any host becomes unreachable. - -@item @value{sysconfdir}/tinc/@var{netname}/subnet-up -This script is started when a Subnet becomes reachable. -The Subnet and the node it belongs to are passed in environment variables. - -@item @value{sysconfdir}/tinc/@var{netname}/subnet-down -This script is started when a Subnet becomes unreachable. - -@item @value{sysconfdir}/tinc/@var{netname}/invitation-created -This script is started when a new invitation has been created. - -@item @value{sysconfdir}/tinc/@var{netname}/invitation-accepted -This script is started when an invitation has been used. - -@end table - -@cindex environment variables -The scripts are started without command line arguments, -but can make use of certain environment variables. -Under UNIX like operating systems the names of environment variables must be preceded by a $ in scripts. -Under Windows, in @file{.bat} or @file{.cmd} files, they have to be put between % signs. - -@table @env -@cindex NETNAME -@item NETNAME -If a netname was specified, this environment variable contains it. - -@cindex NAME -@item NAME -Contains the name of this tinc daemon. - -@cindex DEVICE -@item DEVICE -Contains the name of the virtual network device that tinc uses. - -@cindex INTERFACE -@item INTERFACE -Contains the name of the virtual network interface that tinc uses. -This should be used for commands like ifconfig. - -@cindex NODE -@item NODE -When a host becomes (un)reachable, this is set to its name. -If a subnet becomes (un)reachable, this is set to the owner of that subnet. - -@cindex REMOTEADDRESS -@item REMOTEADDRESS -When a host becomes (un)reachable, this is set to its real address. - -@cindex REMOTEPORT -@item REMOTEPORT -When a host becomes (un)reachable, -this is set to the port number it uses for communication with other tinc daemons. - -@cindex SUBNET -@item SUBNET -When a subnet becomes (un)reachable, this is set to the subnet. - -@cindex WEIGHT -@item WEIGHT -When a subnet becomes (un)reachable, this is set to the subnet weight. - -@cindex INVITATION_FILE -@item INVITATION_FILE -When the @file{invitation-created} script is called, -this is set to the file where the invitation details will be stored. - -@cindex INVITATION_URL -@item INVITATION_URL -When the @file{invitation-created} script is called, -this is set to the invitation URL that has been created. -@end table - -Do not forget that under UNIX operating systems, -you have to make the scripts executable, using the command @samp{chmod a+x script}. - - -@c ================================================================== -@node How to configure -@subsection How to configure - -@subsubheading Step 1. Creating initial configuration files. - -The initial directory structure, configuration files and public/private keypairs are created using the following command: - -@example -tinc -n @var{netname} init @var{name} -@end example - -(You will need to run this as root, or use "sudo".) -This will create the configuration directory @file{@value{sysconfdir}/tinc/@var{netname}.}, -and inside it will create another directory named @file{hosts/}. -In the configuration directory, it will create the file @file{tinc.conf} with the following contents: - -@example -Name = @var{name} -@end example - -It will also create private RSA and ECDSA keys, which will be stored in the files @file{rsa_key.priv} and @file{ecdsa_key.priv}. -It will also create a host configuration file @file{hosts/@var{name}}, -which will contain the corresponding public RSA and ECDSA keys. - -Finally, on UNIX operating systems, it will create an executable script @file{tinc-up}, -which will initially not do anything except warning that you should edit it. - -@subsubheading Step 2. Modifying the initial configuration. - -Unless you want to use tinc in switch mode, -you should now configure which range of addresses you will use on the VPN. -Let's assume you will be part of a VPN which uses the address range 192.168.0.0/16, -and you yourself have a smaller portion of that range: 192.168.2.0/24. -Then you should run the following command: - -@example -tinc -n @var{netname} add subnet 192.168.2.0/24 -@end example - -This will add a Subnet statement to your host configuration file. -Try opening the file @file{@value{sysconfdir}/tinc/@var{netname}/hosts/@var{name}} in an editor. -You should now see a file containing the public RSA and ECDSA keys (which looks like a bunch of random characters), -and the following line at the bottom: - -@example -Subnet = 192.168.2.0/24 -@end example - -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 -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{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 -tinc -n @var{netname} add address foo.example.org -@end example - -If you already know to which daemons your daemon should make meta-connections, -you should configure that now as well. -Suppose you want to connect to a daemon named "bar", run: - -@example -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! -When you start tinc, and it tries to make a connection to "bar", -it will look for a host configuration file named @file{hosts/bar}, -and will read Address statements and public keys from that file. - -@subsubheading Step 2. Exchanging configuration files. - -If your daemon has a ConnectTo = bar statement in its @file{tinc.conf} file, -or if bar has a ConnectTo your daemon, then you both need each other's host configuration files. -You should send @file{hosts/@var{name}} to bar, and bar should send you his file which you should move to @file{hosts/bar}. -If you are on a UNIX platform, you can easily send an email containing the necessary information using the following command -(assuming the owner of bar has the email address bar@@example.org): - -@example -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, -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 -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 -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. -However, remember that you do not need to ConnectTo all nodes in the VPN; -it is only necessary to create one or a few meta-connections, -after the connections are made tinc will learn about all the other nodes in the VPN, -and will automatically make other connections as necessary. - - -@c ================================================================== -@node Network interfaces -@section Network interfaces - -Before tinc can start transmitting data over the tunnel, it must -set up the virtual network interface. - -First, decide which IP addresses you want to have associated with these -devices, and what network mask they must have. - -Tinc will open a virtual network device (@file{/dev/tun}, @file{/dev/tap0} or similar), -which will also create a network interface called something like @samp{tun0}, @samp{tap0}. -If you are using the Linux tun/tap driver, the network interface will by default have the same name as the @var{netname}. -Under Windows you can change the name of the network interface from the Network Connections control panel. - -@cindex tinc-up -You can configure the network interface by putting ordinary ifconfig, route, and other commands -to a script named @file{@value{sysconfdir}/tinc/@var{netname}/tinc-up}. -When tinc starts, this script will be executed. When tinc exits, it will execute the script named -@file{@value{sysconfdir}/tinc/@var{netname}/tinc-down}, but normally you don't need to create that script. -You can manually open the script in an editor, or use the following command: - -@example -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: - -@example -#!/bin/sh -ifconfig $INTERFACE 192.168.2.1 netmask 255.255.0.0 -ip addr add fec0:0:0:2::/48 dev $INTERFACE -@end example - -The first command gives the interface an IPv4 address and a netmask. -The kernel will also automatically add an IPv4 route to this interface, so normally you don't need -to add route commands to the @file{tinc-up} script. -The kernel will also bring the interface up after this command. -@cindex netmask -The netmask is the mask of the @emph{entire} VPN network, not just your -own subnet. -The second command gives the interface an IPv6 address and netmask, -which will also automatically add an IPv6 route. -If you only want to use "ip addr" commands on Linux, don't forget that it doesn't bring the interface up, unlike ifconfig, -so you need to add @samp{ip link set $INTERFACE up} in that case. - -The exact syntax of the ifconfig and route commands differs from platform to platform. -You can look up the commands for setting addresses and adding routes in @ref{Platform specific information}, -but it is best to consult the manpages of those utilities on your platform. - - -@c ================================================================== -@node Example configuration -@section Example configuration - - -@cindex example -Imagine the following situation. Branch A of our example `company' wants to connect -three branch offices in B, C and D using the Internet. All four offices -have a 24/7 connection to the Internet. - -A is going to serve as the center of the network. B and C will connect -to A, and D will connect to C. Each office will be assigned their own IP -network, 10.x.0.0. - -@example -A: net 10.1.0.0 mask 255.255.0.0 gateway 10.1.54.1 internet IP 1.2.3.4 -B: net 10.2.0.0 mask 255.255.0.0 gateway 10.2.1.12 internet IP 2.3.4.5 -C: net 10.3.0.0 mask 255.255.0.0 gateway 10.3.69.254 internet IP 3.4.5.6 -D: net 10.4.0.0 mask 255.255.0.0 gateway 10.4.3.32 internet IP 4.5.6.7 -@end example - -Here, ``gateway'' is the VPN IP address of the machine that is running the -tincd, and ``internet IP'' is the IP address of the firewall, which does not -need to run tincd, but it must do a port forwarding of TCP and UDP on port -655 (unless otherwise configured). - -In this example, it is assumed that eth0 is the interface that points to -the inner (physical) LAN of the office, although this could also be the -same as the interface that leads to the Internet. The configuration of -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{tinc init} and @samp{tinc config} commands, -here we just show the end results: - -@subsubheading For Branch A - -@emph{BranchA} would be configured like this: - -In @file{@value{sysconfdir}/tinc/company/tinc-up}: - -@example -#!/bin/sh - -# Real interface of internal network: -# ifconfig eth0 10.1.54.1 netmask 255.255.0.0 - -ifconfig $INTERFACE 10.1.54.1 netmask 255.0.0.0 -@end example - -and in @file{@value{sysconfdir}/tinc/company/tinc.conf}: - -@example -Name = BranchA -@end example - -On all hosts, @file{@value{sysconfdir}/tinc/company/hosts/BranchA} contains: - -@example -Subnet = 10.1.0.0/16 -Address = 1.2.3.4 - ------BEGIN RSA PUBLIC KEY----- -... ------END RSA PUBLIC KEY----- -@end example - -Note that the IP addresses of eth0 and the VPN interface are the same. -This is quite possible, if you make sure that the netmasks of the interfaces are different. -It is in fact recommended to give both real internal network interfaces and VPN interfaces the same IP address, -since that will make things a lot easier to remember and set up. - - -@subsubheading For Branch B - -In @file{@value{sysconfdir}/tinc/company/tinc-up}: - -@example -#!/bin/sh - -# Real interface of internal network: -# ifconfig eth0 10.2.43.8 netmask 255.255.0.0 - -ifconfig $INTERFACE 10.2.1.12 netmask 255.0.0.0 -@end example - -and in @file{@value{sysconfdir}/tinc/company/tinc.conf}: - -@example -Name = BranchB -ConnectTo = BranchA -@end example - -Note here that the internal address (on eth0) doesn't have to be the -same as on the VPN interface. Also, ConnectTo is given so that this node will -always try to connect to BranchA. - -On all hosts, in @file{@value{sysconfdir}/tinc/company/hosts/BranchB}: - -@example -Subnet = 10.2.0.0/16 -Address = 2.3.4.5 - ------BEGIN RSA PUBLIC KEY----- -... ------END RSA PUBLIC KEY----- -@end example - - -@subsubheading For Branch C - -In @file{@value{sysconfdir}/tinc/company/tinc-up}: - -@example -#!/bin/sh - -# Real interface of internal network: -# ifconfig eth0 10.3.69.254 netmask 255.255.0.0 - -ifconfig $INTERFACE 10.3.69.254 netmask 255.0.0.0 -@end example - -and in @file{@value{sysconfdir}/tinc/company/tinc.conf}: - -@example -Name = BranchC -ConnectTo = BranchA -@end example - -C already has another daemon that runs on port 655, so they have to -reserve another port for tinc. It knows the portnumber it has to listen on -from it's own host configuration file. - -On all hosts, in @file{@value{sysconfdir}/tinc/company/hosts/BranchC}: - -@example -Address = 3.4.5.6 -Subnet = 10.3.0.0/16 -Port = 2000 - ------BEGIN RSA PUBLIC KEY----- -... ------END RSA PUBLIC KEY----- -@end example - - -@subsubheading For Branch D - -In @file{@value{sysconfdir}/tinc/company/tinc-up}: - -@example -#!/bin/sh - -# Real interface of internal network: -# ifconfig eth0 10.4.3.32 netmask 255.255.0.0 - -ifconfig $INTERFACE 10.4.3.32 netmask 255.0.0.0 -@end example - -and in @file{@value{sysconfdir}/tinc/company/tinc.conf}: - -@example -Name = BranchD -ConnectTo = BranchC -@end example - -D will be connecting to C, which has a tincd running for this network on -port 2000. It knows the port number from the host configuration file. - -On all hosts, in @file{@value{sysconfdir}/tinc/company/hosts/BranchD}: - -@example -Subnet = 10.4.0.0/16 -Address = 4.5.6.7 - ------BEGIN RSA PUBLIC KEY----- -... ------END RSA PUBLIC KEY----- -@end example - -@subsubheading Key files - -A, B, C and D all have their own public/private keypairs: - -The private RSA key is stored in @file{@value{sysconfdir}/tinc/company/rsa_key.priv}, -the private ECDSA key is stored in @file{@value{sysconfdir}/tinc/company/ecdsa_key.priv}, -and the public RSA and ECDSA keys are put into the host configuration file in the @file{@value{sysconfdir}/tinc/company/hosts/} directory. - -@subsubheading Starting - -After each branch has finished configuration and they have distributed -the host configuration files amongst them, they can start their tinc daemons. -They don't necessarily have to wait for the other branches to have started -their daemons, tinc will try connecting until they are available. - - -@c ================================================================== -@node Running tinc -@chapter Running tinc - -If everything else is done, you can start tinc by typing the following command: - -@example -tinc -n @var{netname} start -@end example - -@cindex daemon -Tinc will detach from the terminal and continue to run in the background like a good daemon. -If there are any problems however you can try to increase the debug level -and look in the syslog to find out what the problems are. - -@menu -* Runtime options:: -* Signals:: -* Debug levels:: -* Solving problems:: -* Error messages:: -* Sending bug reports:: -@end menu - - -@c ================================================================== -@node Runtime options -@section Runtime options - -Besides the settings in the configuration file, tinc also accepts some -command line options. - -@cindex command line -@cindex runtime options -@cindex options -@c from the manpage -@table @option -@item -c, --config=@var{path} -Read configuration options from the directory @var{path}. The default is -@file{@value{sysconfdir}/tinc/@var{netname}/}. - -@item -D, --no-detach -Don't fork and detach. -This will also disable the automatic restart mechanism for fatal errors. - -@cindex debug level -@item -d, --debug=@var{level} -Set debug level to @var{level}. The higher the debug level, the more gets -logged. Everything goes via syslog. - -@item -n, --net=@var{netname} -Use configuration for net @var{netname}. -This will let tinc read all configuration files from -@file{@value{sysconfdir}/tinc/@var{netname}/}. -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 tinc to authenticate. -If unspecified, the default is -@file{@value{localstatedir}/run/tinc.@var{netname}.pid}. - -@item -o, --option=[@var{HOST}.]@var{KEY}=@var{VALUE} -Without specifying a @var{HOST}, this will set server configuration variable @var{KEY} to @var{VALUE}. -If specified as @var{HOST}.@var{KEY}=@var{VALUE}, -this will set the host configuration variable @var{KEY} of the host named @var{HOST} to @var{VALUE}. -This option can be used more than once to specify multiple configuration variables. - -@item -L, --mlock -Lock tinc into main memory. -This will prevent sensitive data like shared private keys to be written to the system swap files/partitions. - -This option is not supported on all platforms. - -@item --logfile[=@var{file}] -Write log entries to a file instead of to the system logging facility. -If @var{file} is omitted, the default is @file{@value{localstatedir}/log/tinc.@var{netname}.log}. - -@item --bypass-security -Disables encryption and authentication. -Only useful for debugging. - -@item -R, --chroot -Change process root directory to the directory where the config file is -located (@file{@value{sysconfdir}/tinc/@var{netname}/} as determined by --n/--net option or as given by -c/--config option), for added security. -The chroot is performed after all the initialization is done, after -writing pid files and opening network sockets. - -Note that this option alone does not do any good without -U/--user, below. - -Note also that tinc can't run scripts anymore (such as tinc-down or host-up), -unless it's setup to be runnable inside chroot environment. - -This option is not supported on all platforms. -@item -U, --user=@var{user} -Switch to the given @var{user} after initialization, at the same time as -chroot is performed (see --chroot above). With this option tinc drops -privileges, for added security. - -This option is not supported on all platforms. - -@item --help -Display a short reminder of these runtime options and terminate. - -@item --version -Output version information and exit. - -@end table - -@c ================================================================== -@node Signals -@section Signals - -@cindex signals -You can also send the following signals to a running tincd process: - -@c from the manpage -@table @samp - -@item ALRM -Forces tinc to try to connect to all uplinks immediately. -Usually tinc attempts to do this itself, -but increases the time it waits between the attempts each time it failed, -and if tinc didn't succeed to connect to an uplink the first time after it started, -it defaults to the maximum time of 15 minutes. - -@item HUP -Partially rereads configuration files. -Connections to hosts whose host config file are removed are closed. -New outgoing connections specified in @file{tinc.conf} will be made. -If the --logfile option is used, this will also close and reopen the log file, -useful when log rotation is used. - -@end table - -@c ================================================================== -@node Debug levels -@section Debug levels - -@cindex debug levels -The tinc daemon can send a lot of messages to the syslog. -The higher the debug level, the more messages it will log. -Each level inherits all messages of the previous level: - -@c from the manpage -@table @samp - -@item 0 -This will log a message indicating tinc has started along with a version number. -It will also log any serious error. - -@item 1 -This will log all connections that are made with other tinc daemons. - -@item 2 -This will log status and error messages from scripts and other tinc daemons. - -@item 3 -This will log all requests that are exchanged with other tinc daemons. These include -authentication, key exchange and connection list updates. - -@item 4 -This will log a copy of everything received on the meta socket. - -@item 5 -This will log all network traffic over the virtual private network. - -@end table - -@c ================================================================== -@node Solving problems -@section Solving problems - -If tinc starts without problems, but if the VPN doesn't work, you will have to find the cause of the problem. -The first thing to do is to start tinc with a high debug level in the foreground, -so you can directly see everything tinc logs: - -@example -tincd -n @var{netname} -d5 -D -@end example - -If tinc does not log any error messages, then you might want to check the following things: - -@itemize -@item @file{tinc-up} script -Does this script contain the right commands? -Normally you must give the interface the address of this host on the VPN, and the netmask must be big enough so that the entire VPN is covered. - -@item Subnet -Does the Subnet (or Subnets) in the host configuration file of this host match the portion of the VPN that belongs to this host? - -@item Firewalls and NATs -Do you have a firewall or a NAT device (a masquerading firewall or perhaps an ADSL router that performs masquerading)? -If so, check that it allows TCP and UDP traffic on port 655. -If it masquerades and the host running tinc is behind it, make sure that it forwards TCP and UDP traffic to port 655 to the host running tinc. -You can add @samp{TCPOnly = yes} to your host config file to force tinc to only use a single TCP connection, -this works through most firewalls and NATs. - -@end itemize - - -@c ================================================================== -@node Error messages -@section Error messages - -What follows is a list of the most common error messages you might find in the logs. -Some of them will only be visible if the debug level is high enough. - -@table @samp -@item Could not open /dev/tap0: No such device - -@itemize -@item You forgot to `modprobe netlink_dev' or `modprobe ethertap'. -@item You forgot to compile `Netlink device emulation' in the kernel. -@end itemize - -@item Can't write to /dev/net/tun: No such device - -@itemize -@item You forgot to `modprobe tun'. -@item You forgot to compile `Universal TUN/TAP driver' in the kernel. -@item The tun device is located somewhere else in @file{/dev/}. -@end itemize - -@item Network address and prefix length do not match! - -@itemize -@item The Subnet field must contain a @emph{network} address, trailing bits should be 0. -@item If you only want to use one IP address, set the netmask to /32. -@end itemize - -@item Error reading RSA key file `rsa_key.priv': No such file or directory - -@itemize -@item You forgot to create a public/private keypair. -@item Specify the complete pathname to the private key file with the @samp{PrivateKeyFile} option. -@end itemize - -@item Warning: insecure file permissions for RSA private key file `rsa_key.priv'! - -@itemize -@item The private key file is readable by users other than root. -Use chmod to correct the file permissions. -@end itemize - -@item Creating metasocket failed: Address family not supported - -@itemize -@item By default tinc tries to create both IPv4 and IPv6 sockets. -On some platforms this might not be implemented. -If the logs show @samp{Ready} later on, then at least one metasocket was created, -and you can ignore this message. -You can add @samp{AddressFamily = ipv4} to @file{tinc.conf} to prevent this from happening. -@end itemize - -@item Cannot route packet: unknown IPv4 destination 1.2.3.4 - -@itemize -@item You try to send traffic to a host on the VPN for which no Subnet is known. -@item If it is a broadcast address (ending in .255), it probably is a samba server or a Windows host sending broadcast packets. -You can ignore it. -@end itemize - -@item Cannot route packet: ARP request for unknown address 1.2.3.4 - -@itemize -@item You try to send traffic to a host on the VPN for which no Subnet is known. -@end itemize - -@item Packet with destination 1.2.3.4 is looping back to us! - -@itemize -@item Something is not configured right. Packets are being sent out to the -virtual network device, but according to the Subnet directives in your host configuration -file, those packets should go to your own host. Most common mistake is that -you have a Subnet line in your host configuration file with a prefix length which is -just as large as the prefix of the virtual network interface. The latter should in almost all -cases be larger. Rethink your configuration. -Note that you will only see this message if you specified a debug -level of 5 or higher! -@item Chances are that a @samp{Subnet = ...} line in the host configuration file of this tinc daemon is wrong. -Change it to a subnet that is accepted locally by another interface, -or if that is not the case, try changing the prefix length into /32. -@end itemize - -@item Node foo (1.2.3.4) is not reachable - -@itemize -@item Node foo does not have a connection anymore, its tinc daemon is not running or its connection to the Internet is broken. -@end itemize - -@item Received UDP packet from unknown source 1.2.3.4 (port 12345) - -@itemize -@item If you see this only sporadically, it is harmless and caused by a node sending packets using an old key. -@item If you see this often and another node is not reachable anymore, then a NAT (masquerading firewall) is changing the source address of UDP packets. -You can add @samp{TCPOnly = yes} to host configuration files to force all VPN traffic to go over a TCP connection. -@end itemize - -@item Got bad/bogus/unauthorized REQUEST from foo (1.2.3.4 port 12345) - -@itemize -@item Node foo does not have the right public/private keypair. -Generate new keypairs and distribute them again. -@item An attacker tries to gain access to your VPN. -@item A network error caused corruption of metadata sent from foo. -@end itemize - -@end table - -@c ================================================================== -@node Sending bug reports -@section Sending bug reports - -If you really can't find the cause of a problem, or if you suspect tinc is not working right, -you can send us a bugreport, see @ref{Contact information}. -Be sure to include the following information in your bugreport: - -@itemize -@item A clear description of what you are trying to achieve and what the problem is. -@item What platform (operating system, version, hardware architecture) and which version of tinc you use. -@item If compiling tinc fails, a copy of @file{config.log} and the error messages you get. -@item Otherwise, a copy of @file{tinc.conf}, @file{tinc-up} and all files in the @file{hosts/} directory. -@item The output of the commands @samp{ifconfig -a} and @samp{route -n} (or @samp{netstat -rn} if that doesn't work). -@item The output of any command that fails to work as it should (like ping or traceroute). -@end itemize - -@c ================================================================== -@node Controlling tinc -@chapter Controlling tinc - -@cindex command line interface -You can start, stop, control and inspect a running tincd through the tinc -command. A quick example: - -@example -tinc -n @var{netname} reload -@end example - -@cindex shell -If tinc is started without a command, it will act as a shell; it will display a -prompt, and commands can be entered on the prompt. If tinc is compiled with -libreadline, history and command completion are available on the prompt. One -can also pipe a script containing commands through tinc. In that case, lines -starting with a # symbol will be ignored. - -@menu -* tinc runtime options:: -* tinc environment variables:: -* tinc commands:: -* tinc examples:: -* tinc top:: -@end menu - - -@c ================================================================== -@node tinc runtime options -@section tinc runtime options - -@c from the manpage -@table @option -@item -c, --config=@var{path} -Read configuration options from the directory @var{path}. The default is -@file{@value{sysconfdir}/tinc/@var{netname}/}. - -@item -n, --net=@var{netname} -Use configuration for net @var{netname}. @xref{Multiple networks}. - -@item --pidfile=@var{filename} -Use the cookie from @var{filename} to authenticate with a running tinc daemon. -If unspecified, the default is -@file{@value{localstatedir}/run/tinc.@var{netname}.pid}. - -@item --help -Display a short reminder of runtime options and commands, then terminate. - -@item --version -Output version information and exit. - -@end table - -@c ================================================================== -@node tinc environment variables -@section tinc environment variables - -@table @env -@cindex NETNAME -@item NETNAME -If no netname is specified on the command line with the @option{-n} option, -the value of this environment variable is used. -@end table - -@c ================================================================== -@node tinc commands -@section tinc commands - -@c from the manpage -@table @code - -@cindex init -@item init [@var{name}] -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. - -@cindex get -@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. - -@cindex set -@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}. - -@cindex add -@item add @var{variable} @var{value} -As above, but without removing any previously existing configuration variables. - -@cindex del -@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. - -@cindex edit -@item edit @var{filename} -Start an editor for the given configuration file. -You do not need to specify the full path to the file. - -@cindex export -@item export -Export the host configuration file of the local node to standard output. - -@cindex export-all -@item export-all -Export all host configuration files to standard output. - -@cindex import -@item import [--force] -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. - -@cindex exchange -@item exchange [--force] -The same as export followed by import. - -@cindex exchange-all -@item exchange-all [--force] -The same as export-all followed by import. - -@cindex invite -@item invite @var{name} -Prepares an invitation for a new node with the given @var{name}, -and prints a short invitation URL that can be used with the join command. - -@cindex join -@item join [@var{URL}] -Join an existing VPN using an invitation URL created using the invite command. -If no @var{URL} is given, it will be read from standard input. - -@cindex start -@item start [tincd options] -Start @samp{tincd}, optionally with the given extra options. - -@cindex stop -@item stop -Stop @samp{tincd}. - -@cindex restart -@item restart [tincd options] -Restart @samp{tincd}, optionally with the given extra options. - -@cindex reload -@item reload -Partially rereads configuration files. Connections to hosts whose host -config files are removed are closed. New outgoing connections specified -in @file{tinc.conf} will be made. - -@cindex pid -@item pid -Shows the PID of the currently running @samp{tincd}. - -@cindex generate-keys -@item generate-keys [@var{bits}] -Generate both RSA and ECDSA keypairs (see below) and exit. -tinc will ask where you want to store the files, but will default to the -configuration directory (you can use the -c or -n option). - -@cindex generate-ecdsa-keys -@item generate-ecdsa-keys -Generate public/private ECDSA keypair and exit. - -@cindex generate-rsa-keys -@item generate-rsa-keys [@var{bits}] -Generate public/private RSA keypair and exit. If @var{bits} is omitted, the -default length will be 2048 bits. When saving keys to existing files, tinc -will not delete the old keys; you have to remove them manually. - -@cindex dump -@item dump [reachable] nodes -Dump a list of all known nodes in the VPN. -If the reachable keyword is used, only lists reachable nodes. - -@item dump edges -Dump a list of all known connections in the VPN. - -@item dump subnets -Dump a list of all known subnets in the VPN. - -@item dump connections -Dump a list of all meta connections with ourself. - -@cindex graph -@item dump graph | digraph -Dump a graph of the VPN in dotty format. -Nodes are colored according to their reachability: -red nodes are unreachable, orange nodes are indirectly reachable, green nodes are directly reachable. -Black nodes are either directly or indirectly reachable, but direct reachability has not been tried yet. - -@cindex info -@item info @var{node} | @var{subnet} | @var{address} -Show information about a particular @var{node}, @var{subnet} or @var{address}. -If an @var{address} is given, any matching subnet will be shown. - -@cindex purge -@item purge -Purges all information remembered about unreachable nodes. - -@cindex debug -@item debug @var{level} -Sets debug level to @var{level}. - -@cindex log -@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 tinc. - -@cindex retry -@item retry -Forces tinc to try to connect to all uplinks immediately. -Usually tinc attempts to do this itself, -but increases the time it waits between the attempts each time it failed, -and if tinc didn't succeed to connect to an uplink the first time after it started, -it defaults to the maximum time of 15 minutes. - -@cindex disconnect -@item disconnect @var{node} -Closes the meta connection with the given @var{node}. - -@cindex top -@item top -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. - -@cindex pcap -@item pcap -Dump VPN traffic going through the local tinc node in pcap-savefile format to standard output, -from where it can be redirected to a file or piped through a program that can parse it directly, -such as tcpdump. - -@cindex network [@var{netname}] -@item network -If @var{netname} is given, switch to that network. -Otherwise, display a list of all networks for which configuration files exist. - -@end table - -@c ================================================================== -@node tinc examples -@section tinc examples - -Examples of some commands: - -@example -tinc -n vpn dump graph | circo -Txlib -tinc -n vpn pcap | tcpdump -r - -tinc -n vpn top -@end example - -Examples of changing the configuration using tinc: - -@example -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 tinc top -@section tinc top - -@cindex 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, -and the amount of bytes and packets read from and sent to each node in the other columns. -By default, the information is updated every second. -The behaviour of the top command can be changed using the following keys: - -@table @key - -@item s -Change the interval between updates. -After pressing the @key{s} key, enter the desired interval in seconds, followed by enter. -Fractional seconds are honored. -Intervals lower than 0.1 seconds are not allowed. - -@item c -Toggle between displaying current traffic rates (in packets and bytes per second) -and cummulative traffic (total packets and bytes since the tinc daemon started). - -@item n -Sort the list of nodes by name. - -@item i -Sort the list of nodes by incoming amount of bytes. - -@item I -Sort the list of nodes by incoming amount of packets. - -@item o -Sort the list of nodes by outgoing amount of bytes. - -@item O -Sort the list of nodes by outgoing amount of packets. - -@item t -Sort the list of nodes by sum of incoming and outgoing amount of bytes. - -@item T -Sort the list of nodes by sum of incoming and outgoing amount of packets. - -@item b -Show amount of traffic in bytes. - -@item k -Show amount of traffic in kilobytes. - -@item M -Show amount of traffic in megabytes. - -@item G -Show amount of traffic in gigabytes. - -@item q -Quit. - -@end table - - -@c ================================================================== -@node Technical information -@chapter Technical information - - -@menu -* The connection:: -* The meta-protocol:: -* Security:: -@end menu - - -@c ================================================================== -@node The connection -@section The connection - -@cindex connection -Tinc is a daemon that takes VPN data and transmit that to another host -computer over the existing Internet infrastructure. - -@menu -* The UDP tunnel:: -* The meta-connection:: -@end menu - - -@c ================================================================== -@node The UDP tunnel -@subsection The UDP tunnel - -@cindex virtual network device -@cindex frame type -The data itself is read from a character device file, the so-called -@emph{virtual network device}. This device is associated with a network -interface. Any data sent to this interface can be read from the device, -and any data written to the device gets sent from the interface. -There are two possible types of virtual network devices: -`tun' style, which are point-to-point devices which can only handle IPv4 and/or IPv6 packets, -and `tap' style, which are Ethernet devices and handle complete Ethernet frames. - -So when tinc reads an Ethernet frame from the device, it determines its -type. When tinc is in it's default routing mode, it can handle IPv4 and IPv6 -packets. Depending on the Subnet lines, it will send the packets off to their destination IP address. -In the `switch' and `hub' mode, tinc will use broadcasts and MAC address discovery -to deduce the destination of the packets. -Since the latter modes only depend on the link layer information, -any protocol that runs over Ethernet is supported (for instance IPX and Appletalk). -However, only `tap' style devices provide this information. - -After the destination has been determined, -the packet will be compressed (optionally), -a sequence number will be added to the packet, -the packet will then be encrypted -and a message authentication code will be appended. - -@cindex encapsulating -@cindex UDP -When that is done, time has come to actually transport the -packet to the destination computer. We do this by sending the packet -over an UDP connection to the destination host. This is called -@emph{encapsulating}, the VPN packet (though now encrypted) is -encapsulated in another IP datagram. - -When the destination receives this packet, the same thing happens, only -in reverse. So it checks the message authentication code, decrypts the contents of the UDP datagram, -checks the sequence number -and writes the decrypted information to its own virtual network device. - -If the virtual network device is a `tun' device (a point-to-point tunnel), -there is no problem for the kernel to accept a packet. -However, if it is a `tap' device (this is the only available type on FreeBSD), -the destination MAC address must match that of the virtual network interface. -If tinc is in it's default routing mode, ARP does not work, so the correct destination MAC -can not be known by the sending host. -Tinc solves this by letting the receiving end detect the MAC address of its own virtual network interface -and overwriting the destination MAC address of the received packet. - -In switch or hub modes ARP does work so the sender already knows the correct destination MAC address. -In those modes every interface should have a unique MAC address, so make sure they are not the same. -Because switch and hub modes rely on MAC addresses to function correctly, -these modes cannot be used on the following operating systems which don't have a `tap' style virtual network device: -OpenBSD, NetBSD, Darwin and Solaris. - - -@c ================================================================== -@node The meta-connection -@subsection The meta-connection - -Having only a UDP connection available is not enough. Though suitable -for transmitting data, we want to be able to reliably send other -information, such as routing and session key information to somebody. - -@cindex TCP -TCP is a better alternative, because it already contains protection -against information being lost, unlike UDP. - -So we establish two connections. One for the encrypted VPN data, and one -for other information, the meta-data. Hence, we call the second -connection the meta-connection. We can now be sure that the -meta-information doesn't get lost on the way to another computer. - -@cindex data-protocol -@cindex meta-protocol -Like with any communication, we must have a protocol, so that everybody -knows what everything stands for, and how she should react. Because we -have two connections, we also have two protocols. The protocol used for -the UDP data is the ``data-protocol,'' the other one is the -``meta-protocol.'' - -The reason we don't use TCP for both protocols is that UDP is much -better for encapsulation, even while it is less reliable. The real -problem is that when TCP would be used to encapsulate a TCP stream -that's on the private network, for every packet sent there would be -three ACKs sent instead of just one. Furthermore, if there would be -a timeout, both TCP streams would sense the timeout, and both would -start re-sending packets. - - -@c ================================================================== -@node The meta-protocol -@section The meta-protocol - -The meta protocol is used to tie all tinc daemons together, and -exchange information about which tinc daemon serves which virtual -subnet. - -The meta protocol consists of requests that can be sent to the other -side. Each request has a unique number and several parameters. All -requests are represented in the standard ASCII character set. It is -possible to use tools such as telnet or netcat to connect to a tinc -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{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 -synchronised. - -@cindex ADD_EDGE -@cindex ADD_SUBNET -@example -message ------------------------------------------------------------------- -ADD_EDGE node1 node2 21.32.43.54 655 222 0 - | | | | | +-> options - | | | | +----> weight - | | | +--------> UDP port of node2 - | | +----------------> real address of node2 - | +-------------------------> name of destination node - +-------------------------------> name of source node - -ADD_SUBNET node 192.168.1.0/24 - | | +--> prefixlength - | +--------> network address - +------------------> owner of this subnet ------------------------------------------------------------------- -@end example - -The ADD_EDGE messages are to inform other tinc daemons that a connection between -two nodes exist. The address of the destination node is available so that -VPN packets can be sent directly to that node. - -The ADD_SUBNET messages inform other tinc daemons that certain subnets belong -to certain nodes. tinc will use it to determine to which node a VPN packet has -to be sent. - -@cindex DEL_EDGE -@cindex DEL_SUBNET -@example -message ------------------------------------------------------------------- -DEL_EDGE node1 node2 - | +----> name of destination node - +----------> name of source node - -DEL_SUBNET node 192.168.1.0/24 - | | +--> prefixlength - | +--------> network address - +------------------> owner of this subnet ------------------------------------------------------------------- -@end example - -In case a connection between two daemons is closed or broken, DEL_EDGE messages -are sent to inform the other daemons of that fact. Each daemon will calculate a -new route to the the daemons, or mark them unreachable if there isn't any. - -@cindex REQ_KEY -@cindex ANS_KEY -@cindex KEY_CHANGED -@example -message ------------------------------------------------------------------- -REQ_KEY origin destination - | +--> name of the tinc daemon it wants the key from - +----------> name of the daemon that wants the key - -ANS_KEY origin destination 4ae0b0a82d6e0078 91 64 4 - | | \______________/ | | +--> MAC length - | | | | +-----> digest algorithm - | | | +--------> cipher algorithm - | | +--> 128 bits key - | +--> name of the daemon that wants the key - +----------> name of the daemon that uses this key - -KEY_CHANGED origin - +--> daemon that has changed it's packet key ------------------------------------------------------------------- -@end example - -The keys used to encrypt VPN packets are not sent out directly. This is -because it would generate a lot of traffic on VPNs with many daemons, and -chances are that not every tinc daemon will ever send a packet to every -other daemon. Instead, if a daemon needs a key it sends a request for it -via the meta connection of the nearest hop in the direction of the -destination. - -@cindex PING -@cindex PONG -@example -daemon message ------------------------------------------------------------------- -origin PING -dest. PONG ------------------------------------------------------------------- -@end example - -There is also a mechanism to check if hosts are still alive. Since network -failures or a crash can cause a daemon to be killed without properly -shutting down the TCP connection, this is necessary to keep an up to date -connection list. PINGs are sent at regular intervals, except when there -is also some other traffic. A little bit of salt (random data) is added -with each PING and PONG message, to make sure that long sequences of PING/PONG -messages without any other traffic won't result in known plaintext. - -This basically covers what is sent over the meta connection by tinc. - - -@c ================================================================== -@node Security -@section Security - -@cindex TINC -@cindex Cabal -Tinc got its name from ``TINC,'' short for @emph{There Is No Cabal}; the -alleged Cabal was/is an organisation that was said to keep an eye on the -entire Internet. As this is exactly what you @emph{don't} want, we named -the tinc project after TINC. - -@cindex SVPN -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. -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 -* Legacy authentication protocol:: -* Simple Peer-to-Peer Security:: -* Encryption of network packets:: -* Security issues:: -@end menu - - -@c ================================================================== -@node Legacy authentication protocol -@subsection Legacy authentication protocol - -@cindex legacy authentication protocol - -@cindex ID -@cindex META_KEY -@cindex CHALLENGE -@cindex CHAL_REPLY -@cindex ACK -@example -daemon message --------------------------------------------------------------------------- -client - -server - -client ID client 17.2 - | | +-> minor protocol version - | +----> major protocol version - +--------> name of tinc daemon - -server ID server 17.2 - | | +-> minor protocol version - | +----> major protocol version - +--------> name of tinc daemon - -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 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: -@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 - -server CHALLENGE 57fb4b2ccd70d6bb35a64c142f47e61d57f - \_________________________________/ - +-> CHALLEN bits totally random string H2 - -client CHAL_REPLY 816a86 - +-> 160 bits SHA1 of H2 - -server CHAL_REPLY 928ffe - +-> 160 bits SHA1 of H1 - -After the correct challenge replies are received, both ends have proved -their identity. Further information is exchanged. - -client ACK 655 123 0 - | | +-> options - | +----> estimated weight - +--------> listening port of client - -server ACK 655 321 0 - | | +-> options - | +----> estimated weight - +--------> listening port of server --------------------------------------------------------------------------- -@end example - -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. - -@c ================================================================== -@node Simple Peer-to-Peer Security -@subsection Simple Peer-to-Peer Security -@cindex SPTPS - -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. - -Similar to TLS, messages are split up in records. -A complete logical record contains the following information: - -@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 - -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 -@subsection Encryption of network packets -@cindex encryption - -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. - -@cindex UDP -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 - \___________________/\_____/ - | | - V +---> digest algorithm - 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. -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 -@subsection Security issues - -In August 2000, we discovered the existence of a security hole in all versions -of tinc up to and including 1.0pre2. This had to do with the way we exchanged -keys. Since then, we have been working on a new authentication scheme to make -tinc as secure as possible. The current version uses the OpenSSL library and -uses strong authentication with RSA keys. - -On the 29th of December 2001, Jerome Etienne posted a security analysis of tinc -1.0pre4. Due to a lack of sequence numbers and a message authentication code -for each packet, an attacker could possibly disrupt certain network services or -launch a denial of service attack by replaying intercepted packets. The current -version adds sequence numbers and message authentication codes to prevent such -attacks. - -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 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 -prove the security of any cryptographic product. If you wish to review -tinc or give us feedback, you are stronly encouraged to do so. - - -@c ================================================================== -@node Platform specific information -@chapter Platform specific information - -@menu -* Interface configuration:: -* Routes:: -@end menu - -@c ================================================================== -@node Interface configuration -@section Interface configuration - -When configuring an interface, one normally assigns it an address and a -netmask. The address uniquely identifies the host on the network attached to -the interface. The netmask, combined with the address, forms a subnet. It is -used to add a route to the routing table instructing the kernel to send all -packets which fall into that subnet to that interface. Because all packets for -the entire VPN should go to the virtual network interface used by tinc, the -netmask should be such that it encompasses the entire VPN. - -For IPv4 addresses: - -@multitable {Darwin (MacOS/X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} -@item Linux -@tab @code{ifconfig} @var{interface} @var{address} @code{netmask} @var{netmask} -@item Linux iproute2 -@tab @code{ip addr add} @var{address}@code{/}@var{prefixlength} @code{dev} @var{interface} -@item FreeBSD -@tab @code{ifconfig} @var{interface} @var{address} @code{netmask} @var{netmask} -@item OpenBSD -@tab @code{ifconfig} @var{interface} @var{address} @code{netmask} @var{netmask} -@item NetBSD -@tab @code{ifconfig} @var{interface} @var{address} @code{netmask} @var{netmask} -@item Solaris -@tab @code{ifconfig} @var{interface} @var{address} @code{netmask} @var{netmask} -@item Darwin (MacOS/X) -@tab @code{ifconfig} @var{interface} @var{address} @code{netmask} @var{netmask} -@item Windows -@tab @code{netsh interface ip set address} @var{interface} @code{static} @var{address} @var{netmask} -@end multitable - -For IPv6 addresses: - -@multitable {Darwin (MacOS/X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} -@item Linux -@tab @code{ifconfig} @var{interface} @code{add} @var{address}@code{/}@var{prefixlength} -@item FreeBSD -@tab @code{ifconfig} @var{interface} @code{inet6} @var{address} @code{prefixlen} @var{prefixlength} -@item OpenBSD -@tab @code{ifconfig} @var{interface} @code{inet6} @var{address} @code{prefixlen} @var{prefixlength} -@item NetBSD -@tab @code{ifconfig} @var{interface} @code{inet6} @var{address} @code{prefixlen} @var{prefixlength} -@item Solaris -@tab @code{ifconfig} @var{interface} @code{inet6 plumb up} -@item -@tab @code{ifconfig} @var{interface} @code{inet6 addif} @var{address} @var{address} -@item Darwin (MacOS/X) -@tab @code{ifconfig} @var{interface} @code{inet6} @var{address} @code{prefixlen} @var{prefixlength} -@item Windows -@tab @code{netsh interface ipv6 add address} @var{interface} @code{static} @var{address}/@var{prefixlength} -@end multitable - -On some platforms, when running tinc in switch mode, the VPN interface must be set to tap mode with an ifconfig command: - -@multitable {Darwin (MacOS/X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} -@item OpenBSD -@tab @code{ifconfig} @var{interface} @code{link0} -@end multitable - -On Linux, it is possible to create a persistent tun/tap interface which will -continue to exist even if tinc quit, although this is normally not required. -It can be useful to set up a tun/tap interface owned by a non-root user, so -tinc can be started without needing any root privileges at all. - -@multitable {Darwin (MacOS/X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} -@item Linux -@tab @code{ip tuntap add dev} @var{interface} @code{mode} @var{tun|tap} @code{user} @var{username} -@end multitable - -@c ================================================================== -@node Routes -@section Routes - -In some cases it might be necessary to add more routes to the virtual network -interface. There are two ways to indicate which interface a packet should go -to, one is to use the name of the interface itself, another way is to specify -the (local) address that is assigned to that interface (@var{local_address}). The -former way is unambiguous and therefore preferable, but not all platforms -support this. - -Adding routes to IPv4 subnets: - -@multitable {Darwin (MacOS/X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} -@item Linux -@tab @code{route add -net} @var{network_address} @code{netmask} @var{netmask} @var{interface} -@item Linux iproute2 -@tab @code{ip route add} @var{network_address}@code{/}@var{prefixlength} @code{dev} @var{interface} -@item FreeBSD -@tab @code{route add} @var{network_address}@code{/}@var{prefixlength} @var{local_address} -@item OpenBSD -@tab @code{route add} @var{network_address}@code{/}@var{prefixlength} @var{local_address} -@item NetBSD -@tab @code{route add} @var{network_address}@code{/}@var{prefixlength} @var{local_address} -@item Solaris -@tab @code{route add} @var{network_address}@code{/}@var{prefixlength} @var{local_address} @code{-interface} -@item Darwin (MacOS/X) -@tab @code{route add} @var{network_address}@code{/}@var{prefixlength} @var{local_address} -@item Windows -@tab @code{netsh routing ip add persistentroute} @var{network_address} @var{netmask} @var{interface} @var{local_address} -@end multitable - -Adding routes to IPv6 subnets: - -@multitable {Darwin (MacOS/X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} -@item Linux -@tab @code{route add -A inet6} @var{network_address}@code{/}@var{prefixlength} @var{interface} -@item Linux iproute2 -@tab @code{ip route add} @var{network_address}@code{/}@var{prefixlength} @code{dev} @var{interface} -@item FreeBSD -@tab @code{route add -inet6} @var{network_address}@code{/}@var{prefixlength} @var{local_address} -@item OpenBSD -@tab @code{route add -inet6} @var{network_address} @var{local_address} @code{-prefixlen} @var{prefixlength} -@item NetBSD -@tab @code{route add -inet6} @var{network_address} @var{local_address} @code{-prefixlen} @var{prefixlength} -@item Solaris -@tab @code{route add -inet6} @var{network_address}@code{/}@var{prefixlength} @var{local_address} @code{-interface} -@item Darwin (MacOS/X) -@tab ? -@item Windows -@tab @code{netsh interface ipv6 add route} @var{network address}/@var{prefixlength} @var{interface} -@end multitable - - -@c ================================================================== -@node About us -@chapter About us - - -@menu -* Contact information:: -* Authors:: -@end menu - - -@c ================================================================== -@node Contact information -@section Contact information - -@cindex website -Tinc's website is at @url{http://www.tinc-vpn.org/}, -this server is located in the Netherlands. - -@cindex IRC -We have an IRC channel on the FreeNode and OFTC IRC networks. Connect to -@uref{http://www.freenode.net/, irc.freenode.net} -or -@uref{http://www.oftc.net/, irc.oftc.net} -and join channel #tinc. - - -@c ================================================================== -@node Authors -@section Authors - -@table @asis -@item Ivo Timmermans (zarq) -@item Guus Sliepen (guus) (@email{guus@@tinc-vpn.org}) -@end table - -We have received a lot of valuable input from users. With their help, -tinc has become the flexible and robust tool that it is today. We have -composed a list of contributions, in the file called @file{THANKS} in -the source distribution. - - -@c ================================================================== -@node Concept Index -@unnumbered Concept Index - -@c ================================================================== -@printindex cp - - -@c ================================================================== -@contents -@bye diff --git a/doc/tincinclude.texi.in b/doc/tincinclude.texi.in deleted file mode 100644 index da4adc57..00000000 --- a/doc/tincinclude.texi.in +++ /dev/null @@ -1,4 +0,0 @@ -@set VERSION @VERSION@ -@set PACKAGE @PACKAGE@ -@set sysconfdir @sysconfdir@ -@set localstatedir @localstatedir@ diff --git a/m4/openssl.m4 b/m4/openssl.m4 deleted file mode 100644 index fba06fd3..00000000 --- a/m4/openssl.m4 +++ /dev/null @@ -1,56 +0,0 @@ -dnl Check to find the OpenSSL headers/libraries - -AC_DEFUN([MeshLink_OPENSSL], -[ - case $host_os in - *mingw*) - ;; - *) - AC_CHECK_FUNC(dlopen, - [], - [AC_CHECK_LIB(dl, dlopen, - [LIBS="$LIBS -ldl"], - [AC_MSG_ERROR([OpenSSL depends on libdl.]); break] - )] - ) - ;; - esac - - AC_ARG_WITH(openssl, - AS_HELP_STRING([--with-openssl=DIR], [OpenSSL base directory, or:]), - [openssl="$withval" - CPPFLAGS="$CPPFLAGS -I$withval/include" - LDFLAGS="$LDFLAGS -L$withval/lib"] - ) - - AC_ARG_WITH(openssl-include, - AS_HELP_STRING([--with-openssl-include=DIR], [OpenSSL headers directory (without trailing /openssl)]), - [openssl_include="$withval" - CPPFLAGS="$CPPFLAGS -I$withval"] - ) - - AC_ARG_WITH(openssl-lib, - AS_HELP_STRING([--with-openssl-lib=DIR], [OpenSSL library directory]), - [openssl_lib="$withval" - LDFLAGS="$LDFLAGS -L$withval"] - ) - - AC_CHECK_HEADERS([openssl/evp.h openssl/rsa.h openssl/rand.h openssl/err.h openssl/sha.h openssl/pem.h openssl/engine.h openssl/ecdh.h openssl/ec.h], - [], - [AC_MSG_ERROR([OpenSSL header files not found.]); break] - ) - - AC_CHECK_LIB(crypto, EVP_EncryptInit_ex, - [LIBS="-lcrypto $LIBS"], - [AC_MSG_ERROR([OpenSSL libraries not found.])] - ) - - AC_CHECK_FUNCS([RAND_pseudo_bytes EVP_EncryptInit_ex ECDH_compute_key ECDSA_verify], , - [AC_MSG_ERROR([Missing OpenSSL functionality, make sure you have installed the latest version.]); break], - ) - - AC_CHECK_DECLS([OpenSSL_add_all_algorithms, EVP_CTRL_GCM_GET_TAG], , - [AC_MSG_ERROR([Missing OpenSSL functionality, make sure you have installed the latest version.]); break], - [#include ] - ) -]) diff --git a/src/Makefile.am b/src/Makefile.am index 2ca38c86..8f02c06d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,7 +29,9 @@ chacha_poly1305_SOURCES = \ chacha-poly1305/poly1305.c chacha-poly1305/poly1305.h sptps_test_SOURCES = \ + crypto.c crypto.h \ logger.c logger.h \ + prf.c prf.h \ sptps.c sptps.h \ sptps_test.c \ utils.c utils.h \ @@ -37,12 +39,15 @@ sptps_test_SOURCES = \ $(chacha_poly1305_SOURCES) sptps_keypair_SOURCES = \ + crypto.c crypto.h \ sptps_keypair.c \ utils.c utils.h \ $(ed25519_SOURCES) sptps_speed_SOURCES = \ + crypto.c crypto.h \ logger.c logger.h \ + prf.c prf.h \ sptps.c sptps.h \ sptps_speed.c \ utils.c utils.h \ @@ -57,8 +62,7 @@ libmeshlink_la_SOURCES = \ cipher.h \ conf.c conf.h \ connection.c connection.h \ - crypto.h \ - digest.h \ + crypto.c crypto.h \ dropin.c dropin.h \ ecdh.h \ ecdsa.h \ @@ -80,7 +84,7 @@ libmeshlink_la_SOURCES = \ net_socket.c \ netutl.c netutl.h \ node.c node.h \ - prf.h \ + prf.c prf.h \ protocol.c protocol.h \ protocol_auth.c \ protocol_edge.c \ @@ -101,28 +105,18 @@ libmeshlink_la_CFLAGS = -fPIC libmeshlink_la_LIBADD = -lpthread libmeshlink_la_SOURCES += \ - openssl/crypto.c \ - openssl/digest.c openssl/digest.h \ ed25519/ecdh.c \ ed25519/ecdsa.c \ - ed25519/ecdsagen.c \ - openssl/prf.c + ed25519/ecdsagen.c sptps_test_SOURCES += \ - openssl/crypto.c \ - openssl/digest.c openssl/digest.h \ ed25519/ecdh.c \ - ed25519/ecdsa.c \ - openssl/prf.c + ed25519/ecdsa.c sptps_keypair_SOURCES += \ - openssl/crypto.c \ ed25519/ecdsagen.c sptps_speed_SOURCES += \ - openssl/crypto.c \ - openssl/digest.c openssl/digest.h \ ed25519/ecdh.c \ ed25519/ecdsa.c \ - ed25519/ecdsagen.c \ - openssl/prf.c + ed25519/ecdsagen.c sptps_speed_LDADD = -lrt diff --git a/src/crypto.c b/src/crypto.c new file mode 100644 index 00000000..cf000c8a --- /dev/null +++ b/src/crypto.c @@ -0,0 +1,46 @@ +/* + crypto.c -- Cryptographic miscellaneous functions and initialisation + Copyright (C) 2014 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "system.h" + +#include "crypto.h" + +//TODO: use a strict random source once to seed a PRNG? + +static int random_fd = -1; + +void crypto_init(void) { + random_fd = open("/dev/urandom", O_RDONLY); + if(random_fd < 0) + random_fd = open("/dev/random", O_RDONLY); + if(random_fd < 0) { + fprintf(stderr, "Could not open source of random numbers: %s\n", strerror(errno)); + abort(); + } +} + +void crypto_exit(void) { +} + +void randomize(void *out, size_t outlen) { + if(read(random_fd, out, outlen) != outlen) { + fprintf(stderr, "Error reading random numbers: %s\n", strerror(errno)); + abort(); + } +} diff --git a/src/invitation.c b/src/invitation.c index 6c0b0afb..d027e0d9 100644 --- a/src/invitation.c +++ b/src/invitation.c @@ -265,7 +265,7 @@ int cmd_invite(int argc, char *argv[]) { } } - char hash[25]; + char hash[64]; xasprintf(&filename, "%s" SLASH "invitations", confbase); if(mkdir(filename, 0700) && errno != EEXIST) { @@ -361,10 +361,7 @@ int cmd_invite(int argc, char *argv[]) { // Create a hash of the key. char *fingerprint = ecdsa_get_base64_public_key(key); - digest_t *digest = digest_open_by_name("sha256", 18); - if(!digest) - abort(); - digest_create(digest, fingerprint, strlen(fingerprint), hash); + sha512(fingerprint, strlen(fingerprint), hash); b64encode_urlsafe(hash, hash, 18); // Create a random cookie for this invitation. @@ -373,10 +370,10 @@ int cmd_invite(int argc, char *argv[]) { // Create a filename that doesn't reveal the cookie itself char buf[18 + strlen(fingerprint)]; - char cookiehash[25]; + char cookiehash[64]; memcpy(buf, cookie, 18); memcpy(buf + 18, fingerprint, sizeof buf - 18); - digest_create(digest, buf, sizeof buf, cookiehash); + sha512(buf, sizeof buf, cookiehash); b64encode_urlsafe(cookiehash, cookiehash, 18); b64encode_urlsafe(cookie, cookie, 18); @@ -911,12 +908,9 @@ int cmd_join(int argc, char *argv[]) { // Check if the hash of the key he gave us matches the hash in the URL. char *fingerprint = line + 2; - digest_t *digest = digest_open_by_name("sha256", 18); - if(!digest) - abort(); - char hishash[18]; - if(!digest_create(digest, fingerprint, strlen(fingerprint), hishash)) { - fprintf(stderr, "Could not create digest\n%s\n", line + 2); + char hishash[64]; + if(!sha512(fingerprint, strlen(fingerprint), hishash)) { + fprintf(stderr, "Could not create hash\n%s\n", line + 2); return 1; } if(memcmp(hishash, hash, 18)) { diff --git a/src/openssl/cipher.c b/src/openssl/cipher.c deleted file mode 100644 index 8faed39d..00000000 --- a/src/openssl/cipher.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - cipher.c -- Symmetric block cipher handling - Copyright (C) 2014 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" - -#include -#include -#include - -#include "../cipher.h" -#include "../logger.h" -#include "../xalloc.h" - -struct cipher { - EVP_CIPHER_CTX ctx; - const EVP_CIPHER *cipher; - struct cipher_counter *counter; -}; - -typedef struct cipher_counter { - unsigned char counter[CIPHER_MAX_IV_SIZE]; - unsigned char block[CIPHER_MAX_IV_SIZE]; - int n; -} cipher_counter_t; - -static cipher_t *cipher_open(const EVP_CIPHER *evp_cipher) { - cipher_t *cipher = xzalloc(sizeof *cipher); - cipher->cipher = evp_cipher; - EVP_CIPHER_CTX_init(&cipher->ctx); - - return cipher; -} - -cipher_t *cipher_open_by_name(const char *name) { - const EVP_CIPHER *evp_cipher = EVP_get_cipherbyname(name); - if(!evp_cipher) { - logger(DEBUG_ALWAYS, LOG_ERR, "Unknown cipher name '%s'!", name); - return NULL; - } - - return cipher_open(evp_cipher); -} - -cipher_t *cipher_open_by_nid(int nid) { - const EVP_CIPHER *evp_cipher = EVP_get_cipherbynid(nid); - if(!evp_cipher) { - logger(DEBUG_ALWAYS, LOG_ERR, "Unknown cipher nid %d!", nid); - return NULL; - } - - return cipher_open(evp_cipher); -} - -cipher_t *cipher_open_blowfish_ofb(void) { - return cipher_open(EVP_bf_ofb()); -} - -void cipher_close(cipher_t *cipher) { - if(!cipher) - return; - - EVP_CIPHER_CTX_cleanup(&cipher->ctx); - free(cipher->counter); - free(cipher); -} - -size_t cipher_keylength(const cipher_t *cipher) { - if(!cipher || !cipher->cipher) - return 0; - - return cipher->cipher->key_len + cipher->cipher->iv_len; -} - -bool cipher_set_key(cipher_t *cipher, void *key, bool encrypt) { - bool result; - - if(encrypt) - result = EVP_EncryptInit_ex(&cipher->ctx, cipher->cipher, NULL, (unsigned char *)key, (unsigned char *)key + cipher->cipher->key_len); - else - result = EVP_DecryptInit_ex(&cipher->ctx, cipher->cipher, NULL, (unsigned char *)key, (unsigned char *)key + cipher->cipher->key_len); - - if(result) - return true; - - logger(DEBUG_ALWAYS, LOG_ERR, "Error while setting key: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; -} - -bool cipher_set_key_from_rsa(cipher_t *cipher, void *key, size_t len, bool encrypt) { - bool result; - - if(encrypt) - result = EVP_EncryptInit_ex(&cipher->ctx, cipher->cipher, NULL, (unsigned char *)key + len - cipher->cipher->key_len, (unsigned char *)key + len - cipher->cipher->iv_len - cipher->cipher->key_len); - else - result = EVP_DecryptInit_ex(&cipher->ctx, cipher->cipher, NULL, (unsigned char *)key + len - cipher->cipher->key_len, (unsigned char *)key + len - cipher->cipher->iv_len - cipher->cipher->key_len); - - if(result) - return true; - - logger(DEBUG_ALWAYS, LOG_ERR, "Error while setting key: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; -} - -bool cipher_set_counter(cipher_t *cipher, const void *counter, size_t len) { - if(len > cipher->cipher->iv_len - 4) { - logger(DEBUG_ALWAYS, LOG_ERR, "Counter too long"); - return false; - } - - memcpy(cipher->counter->counter, counter, len); - cipher->counter->n = 0; - - return true; -} - -bool cipher_set_counter_key(cipher_t *cipher, void *key) { - int result = EVP_EncryptInit_ex(&cipher->ctx, cipher->cipher, NULL, (unsigned char *)key, NULL); - if(!result) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error while setting key: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - - if(!cipher->counter) - cipher->counter = xzalloc(sizeof *cipher->counter); - else - cipher->counter->n = 0; - - memcpy(cipher->counter->counter, (unsigned char *)key + cipher->cipher->key_len, cipher->cipher->iv_len); - - return true; -} - -bool cipher_gcm_encrypt_start(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen) { - int len = 0; - if(!EVP_EncryptInit_ex(&cipher->ctx, NULL, NULL, NULL, cipher->counter->counter) - || (inlen && !EVP_EncryptUpdate(&cipher->ctx, (unsigned char *)outdata, &len, (unsigned char *)indata, inlen))) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - if(outlen) - *outlen = len; - return true; -} - -bool cipher_gcm_encrypt_finish(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen) { - int len = 0, pad = 0; - if((inlen && !EVP_EncryptUpdate(&cipher->ctx, (unsigned char *)outdata, &len, (unsigned char *)indata, inlen)) - || !EVP_EncryptFinal(&cipher->ctx, (unsigned char *)outdata + len, &pad)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - EVP_CIPHER_CTX_ctrl(&cipher->ctx, EVP_CTRL_GCM_GET_TAG, 16, (unsigned char *)outdata + len + pad); - if(outlen) - *outlen = len + pad + 16; - return true; -} - -bool cipher_gcm_encrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen) { - int len = 0, pad = 0; - if(!EVP_EncryptInit_ex(&cipher->ctx, NULL, NULL, NULL, cipher->counter->counter) || - !EVP_EncryptUpdate(&cipher->ctx, (unsigned char *)outdata, &len, (unsigned char *)indata, inlen) || - !EVP_EncryptFinal(&cipher->ctx, (unsigned char *)outdata + len, &pad)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - EVP_CIPHER_CTX_ctrl(&cipher->ctx, EVP_CTRL_GCM_GET_TAG, 16, (unsigned char *)outdata + len + pad); - if(outlen) - *outlen = len + pad + 16; - return true; -} - -bool cipher_gcm_decrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen) { - if(inlen < 16) - return false; - - int len = 0, pad = 0; - if(!EVP_DecryptInit_ex(&cipher->ctx, NULL, NULL, NULL, cipher->counter->counter)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - - EVP_CIPHER_CTX_ctrl(&cipher->ctx, EVP_CTRL_GCM_SET_TAG, 16, (unsigned char *)indata + inlen - 16); - - if(!EVP_DecryptUpdate(&cipher->ctx, (unsigned char *)outdata, &len, (unsigned char *)indata, inlen - 16) || - !EVP_DecryptFinal(&cipher->ctx, (unsigned char *)outdata + len, &pad)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - if(outlen) - *outlen = len; - return true; -} - -bool cipher_gcm_decrypt_start(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen) { - int len = 0; - if(!EVP_DecryptInit_ex(&cipher->ctx, NULL, NULL, NULL, cipher->counter->counter) - || (inlen && !EVP_DecryptUpdate(&cipher->ctx, (unsigned char *)outdata, &len, (unsigned char *)indata, inlen))) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - if(outlen) - *outlen = len; - return true; -} - -bool cipher_gcm_decrypt_finish(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen) { - if(inlen < 16) - return false; - - EVP_CIPHER_CTX_ctrl(&cipher->ctx, EVP_CTRL_GCM_SET_TAG, 16, (unsigned char *)indata + inlen - 16); - - int len = 0, pad = 0; - if((inlen > 16 && !EVP_DecryptUpdate(&cipher->ctx, (unsigned char *)outdata, &len, (unsigned char *)indata, inlen - 16)) - || !EVP_DecryptFinal(&cipher->ctx, (unsigned char *)outdata + len, &pad)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - return true; -} - - -bool cipher_encrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) { - if(oneshot) { - int len, pad; - if(EVP_EncryptInit_ex(&cipher->ctx, NULL, NULL, NULL, NULL) - && EVP_EncryptUpdate(&cipher->ctx, (unsigned char *)outdata, &len, indata, inlen) - && EVP_EncryptFinal(&cipher->ctx, (unsigned char *)outdata + len, &pad)) { - if(outlen) *outlen = len + pad; - return true; - } - } else { - int len; - if(EVP_EncryptUpdate(&cipher->ctx, outdata, &len, indata, inlen)) { - if(outlen) *outlen = len; - return true; - } - } - - logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; -} - -bool cipher_decrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) { - if(oneshot) { - int len, pad; - if(EVP_DecryptInit_ex(&cipher->ctx, NULL, NULL, NULL, NULL) - && EVP_DecryptUpdate(&cipher->ctx, (unsigned char *)outdata, &len, indata, inlen) - && EVP_DecryptFinal(&cipher->ctx, (unsigned char *)outdata + len, &pad)) { - if(outlen) *outlen = len + pad; - return true; - } - } else { - int len; - if(EVP_EncryptUpdate(&cipher->ctx, outdata, &len, indata, inlen)) { - if(outlen) *outlen = len; - return true; - } - } - - logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; -} - -int cipher_get_nid(const cipher_t *cipher) { - if(!cipher || !cipher->cipher) - return 0; - - return cipher->cipher->nid; -} - -bool cipher_active(const cipher_t *cipher) { - return cipher && cipher->cipher && cipher->cipher->nid != 0; -} diff --git a/src/openssl/crypto.c b/src/openssl/crypto.c deleted file mode 100644 index 8fc63e3c..00000000 --- a/src/openssl/crypto.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - crypto.c -- Cryptographic miscellaneous functions and initialisation - Copyright (C) 2014 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" - -#include -#include -#include - -#include "../crypto.h" - -void crypto_init(void) { - RAND_load_file("/dev/urandom", 1024); - - ENGINE_load_builtin_engines(); - ENGINE_register_all_complete(); - - ERR_load_crypto_strings(); - OpenSSL_add_all_algorithms(); - - if(!RAND_status()) { - fprintf(stderr, "Not enough entropy for the PRNG!\n"); - abort(); - } -} - -void crypto_exit(void) { - EVP_cleanup(); -} - -void randomize(void *out, size_t outlen) { - RAND_pseudo_bytes(out, outlen); -} diff --git a/src/openssl/digest.c b/src/openssl/digest.c deleted file mode 100644 index 8d6e64da..00000000 --- a/src/openssl/digest.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - digest.c -- Digest handling - Copyright (C) 2014 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" -#include "../utils.h" -#include "../xalloc.h" - -#include -#include - -#include "digest.h" -#include "../digest.h" -#include "../logger.h" - -static digest_t *digest_open(const EVP_MD *evp_md, int maclength) { - digest_t *digest = xzalloc(sizeof *digest); - digest->digest = evp_md; - - int digestlen = EVP_MD_size(digest->digest); - - if(maclength > digestlen || maclength < 0) - digest->maclength = digestlen; - else - digest->maclength = maclength; - - return digest; -} - -digest_t *digest_open_by_name(const char *name, int maclength) { - const EVP_MD *evp_md = EVP_get_digestbyname(name); - - if(!evp_md) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "Unknown digest name '%s'!", name); - return false; - } - - return digest_open(evp_md, maclength); -} - -digest_t *digest_open_by_nid(int nid, int maclength) { - const EVP_MD *evp_md = EVP_get_digestbynid(nid); - - if(!evp_md) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "Unknown digest nid %d!", nid); - return false; - } - - return digest_open(evp_md, maclength); -} - -digest_t *digest_open_sha1(int maclength) { - return digest_open(EVP_sha1(), maclength); -} - -bool digest_set_key(digest_t *digest, const void *key, size_t len) { - digest->key = xrealloc(digest->key, len); - memcpy(digest->key, key, len); - digest->keylength = len; - return true; -} - -void digest_close(digest_t *digest) { - if(!digest) - return; - - free(digest->key); - free(digest); -} - -bool digest_create(digest_t *digest, const void *indata, size_t inlen, void *outdata) { - size_t len = EVP_MD_size(digest->digest); - unsigned char tmpdata[len]; - - if(digest->key) { - if(!HMAC(digest->digest, digest->key, digest->keylength, indata, inlen, tmpdata, NULL)) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "Error creating digest: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - } else { - EVP_MD_CTX ctx; - - if(!EVP_DigestInit(&ctx, digest->digest) - || !EVP_DigestUpdate(&ctx, indata, inlen) - || !EVP_DigestFinal(&ctx, tmpdata, NULL)) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "Error creating digest: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - } - - memcpy(outdata, tmpdata, digest->maclength); - return true; -} - -bool digest_verify(digest_t *digest, const void *indata, size_t inlen, const void *cmpdata) { - size_t len = digest->maclength; - unsigned char outdata[len]; - - return digest_create(digest, indata, inlen, outdata) && !memcmp(cmpdata, outdata, digest->maclength); -} - -int digest_get_nid(const digest_t *digest) { - if(!digest || !digest->digest) - return 0; - - return digest->digest->type; -} - -size_t digest_keylength(const digest_t *digest) { - if(!digest || !digest->digest) - return 0; - - return digest->digest->md_size; -} - -size_t digest_length(const digest_t *digest) { - if(!digest) - return 0; - - return digest->maclength; -} - -bool digest_active(const digest_t *digest) { - return digest && digest->digest && digest->digest->type != 0; -} diff --git a/src/openssl/digest.h b/src/openssl/digest.h deleted file mode 100644 index 0a0c9125..00000000 --- a/src/openssl/digest.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - digest.h -- header file digest.c - Copyright (C) 2014 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_OPENSSL_DIGEST_H__ -#define __TINC_OPENSSL_DIGEST_H__ - -#include - -struct digest { - const EVP_MD *digest; - int maclength; - int keylength; - char *key; -}; - -#endif diff --git a/src/openssl/ecdh.c b/src/openssl/ecdh.c deleted file mode 100644 index 14e62176..00000000 --- a/src/openssl/ecdh.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - ecdh.c -- Diffie-Hellman key exchange handling - Copyright (C) 2014 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" - -#include -#include -#include -#include - -#define __TINC_ECDH_INTERNAL__ -typedef EC_KEY ecdh_t; - -#include "../ecdh.h" -#include "../logger.h" -#include "../utils.h" -#include "../xalloc.h" - -ecdh_t *ecdh_generate_public(void *pubkey) { - ecdh_t *ecdh = EC_KEY_new_by_curve_name(NID_secp521r1); - if(!ecdh) { - logger(DEBUG_ALWAYS, LOG_ERR, "Generating EC key_by_curve_name failed: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - - if(!EC_KEY_generate_key(ecdh)) { - EC_KEY_free(ecdh); - logger(DEBUG_ALWAYS, LOG_ERR, "Generating EC key failed: %s", ERR_error_string(ERR_get_error(), NULL)); - return NULL; - } - - const EC_POINT *point = EC_KEY_get0_public_key(ecdh); - if(!point) { - EC_KEY_free(ecdh); - logger(DEBUG_ALWAYS, LOG_ERR, "Getting public key failed: %s", ERR_error_string(ERR_get_error(), NULL)); - return NULL; - } - - size_t result = EC_POINT_point2oct(EC_KEY_get0_group(ecdh), point, POINT_CONVERSION_COMPRESSED, pubkey, ECDH_SIZE, NULL); - if(!result) { - EC_KEY_free(ecdh); - logger(DEBUG_ALWAYS, LOG_ERR, "Converting EC_POINT to binary failed: %s", ERR_error_string(ERR_get_error(), NULL)); - return NULL; - } - - return ecdh; -} - -bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared) { - EC_POINT *point = EC_POINT_new(EC_KEY_get0_group(ecdh)); - if(!point) { - logger(DEBUG_ALWAYS, LOG_ERR, "EC_POINT_new() failed: %s", ERR_error_string(ERR_get_error(), NULL)); - EC_KEY_free(ecdh); - return false; - } - - int result = EC_POINT_oct2point(EC_KEY_get0_group(ecdh), point, pubkey, ECDH_SIZE, NULL); - if(!result) { - EC_POINT_free(point); - EC_KEY_free(ecdh); - logger(DEBUG_ALWAYS, LOG_ERR, "Converting binary to EC_POINT failed: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - - result = ECDH_compute_key(shared, ECDH_SIZE, point, ecdh, NULL); - EC_POINT_free(point); - EC_KEY_free(ecdh); - - if(!result) { - logger(DEBUG_ALWAYS, LOG_ERR, "Computing Elliptic Curve Diffie-Hellman shared key failed: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - - return true; -} - -void ecdh_free(ecdh_t *ecdh) { - if(ecdh) - EC_KEY_free(ecdh); -} diff --git a/src/openssl/ecdsa.c b/src/openssl/ecdsa.c deleted file mode 100644 index d0307455..00000000 --- a/src/openssl/ecdsa.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - ecdsa.c -- ECDSA key handling - Copyright (C) 2014 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" - -#include -#include - -#define __TINC_ECDSA_INTERNAL__ -typedef EC_KEY ecdsa_t; - -#include "../logger.h" -#include "../ecdsa.h" -#include "../utils.h" -#include "../xalloc.h" - -// Get and set ECDSA keys -// -ecdsa_t *ecdsa_set_base64_public_key(const char *p) { - ecdsa_t *ecdsa = EC_KEY_new_by_curve_name(NID_secp521r1); - if(!ecdsa) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "EC_KEY_new_by_curve_name failed: %s", ERR_error_string(ERR_get_error(), NULL)); - return NULL; - } - - int len = strlen(p); - unsigned char pubkey[len / 4 * 3 + 3]; - const unsigned char *ppubkey = pubkey; - len = b64decode(p, (char *)pubkey, len); - - if(!o2i_ECPublicKey(&ecdsa, &ppubkey, len)) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "o2i_ECPublicKey failed: %s", ERR_error_string(ERR_get_error(), NULL)); - EC_KEY_free(ecdsa); - return NULL; - } - - return ecdsa; -} - -char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa) { - unsigned char *pubkey = NULL; - int len = i2o_ECPublicKey(ecdsa, &pubkey); - - char *base64 = xmalloc(len * 4 / 3 + 5); - b64encode((char *)pubkey, base64, len); - - free(pubkey); - - return base64; -} - -// Read PEM ECDSA keys - -ecdsa_t *ecdsa_read_pem_public_key(FILE *fp) { - ecdsa_t *ecdsa = PEM_read_EC_PUBKEY(fp, NULL, NULL, NULL); - - if(!ecdsa) - logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read ECDSA public key: %s", ERR_error_string(ERR_get_error(), NULL)); - - return ecdsa; -} - -ecdsa_t *ecdsa_read_pem_private_key(FILE *fp) { - ecdsa_t *ecdsa = PEM_read_ECPrivateKey(fp, NULL, NULL, NULL); - - if(!ecdsa) - logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read ECDSA private key: %s", ERR_error_string(ERR_get_error(), NULL)); - - return ecdsa; -} - -size_t ecdsa_size(ecdsa_t *ecdsa) { - return ECDSA_size(ecdsa); -} - -// TODO: standardise output format? - -bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t len, void *sig) { - unsigned int siglen = ECDSA_size(ecdsa); - - unsigned char hash[SHA512_DIGEST_LENGTH]; - SHA512(in, len, hash); - - memset(sig, 0, siglen); - - if(!ECDSA_sign(0, hash, sizeof hash, sig, &siglen, ecdsa)) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "ECDSA_sign() failed: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - - return true; -} - -bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t len, const void *sig) { - unsigned int siglen = ECDSA_size(ecdsa); - - unsigned char hash[SHA512_DIGEST_LENGTH]; - SHA512(in, len, hash); - - if(!ECDSA_verify(0, hash, sizeof hash, sig, siglen, ecdsa)) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "ECDSA_verify() failed: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - - return true; -} - -bool ecdsa_active(ecdsa_t *ecdsa) { - return ecdsa; -} - -void ecdsa_free(ecdsa_t *ecdsa) { - if(ecdsa) - EC_KEY_free(ecdsa); -} diff --git a/src/openssl/ecdsagen.c b/src/openssl/ecdsagen.c deleted file mode 100644 index 8794da03..00000000 --- a/src/openssl/ecdsagen.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - ecdsagen.c -- ECDSA key generation and export - Copyright (C) 2014 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" - -#include -#include -#include - -#define __TINC_ECDSA_INTERNAL__ -typedef EC_KEY ecdsa_t; - -#include "../ecdsagen.h" -#include "../utils.h" -#include "../xalloc.h" - -// Generate ECDSA key - -ecdsa_t *ecdsa_generate(void) { - ecdsa_t *ecdsa = EC_KEY_new_by_curve_name(NID_secp521r1); - - if(!ecdsa || !EC_KEY_generate_key(ecdsa)) { - fprintf(stderr, "Generating EC key failed: %s", ERR_error_string(ERR_get_error(), NULL)); - ecdsa_free(ecdsa); - return false; - } - - EC_KEY_set_asn1_flag(ecdsa, OPENSSL_EC_NAMED_CURVE); - EC_KEY_set_conv_form(ecdsa, POINT_CONVERSION_COMPRESSED); - - return ecdsa; -} - -// Write PEM ECDSA keys - -bool ecdsa_write_pem_public_key(ecdsa_t *ecdsa, FILE *fp) { - return PEM_write_EC_PUBKEY(fp, ecdsa); -} - -bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp) { - return PEM_write_ECPrivateKey(fp, ecdsa, NULL, NULL, 0, NULL, NULL); -} diff --git a/src/openssl/prf.c b/src/openssl/prf.c deleted file mode 100644 index 88bb914b..00000000 --- a/src/openssl/prf.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - prf.c -- Pseudo-Random Function for key material generation - Copyright (C) 2014 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" - -#include - -#include "digest.h" -#include "../digest.h" -#include "../prf.h" - -/* Generate key material from a master secret and a seed, based on RFC 4346 section 5. - We use SHA512 instead of MD5 and SHA1. - */ - -static bool prf_xor(int nid, const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, ssize_t outlen) { - digest_t *digest = digest_open_by_nid(nid, -1); - - if(!digest) - return false; - - if(!digest_set_key(digest, secret, secretlen)) { - digest_close(digest); - return false; - } - - size_t len = digest_length(digest); - - /* Data is what the "inner" HMAC function processes. - It consists of the previous HMAC result plus the seed. - */ - - char data[len + seedlen]; - memset(data, 0, len); - memcpy(data + len, seed, seedlen); - - char hash[len]; - - while(outlen > 0) { - /* Inner HMAC */ - if(!digest_create(digest, data, len + seedlen, data)) { - digest_close(digest); - return false; - } - - /* Outer HMAC */ - if(!digest_create(digest, data, len + seedlen, hash)) { - digest_close(digest); - return false; - } - - /* XOR the results of the outer HMAC into the out buffer */ - for(int i = 0; i < len && i < outlen; i++) - *out++ ^= hash[i]; - - outlen -= len; - } - - digest_close(digest); - return true; -} - -bool prf(const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, size_t outlen) { - /* This construction allows us to easily switch back to a scheme where the PRF is calculated using two different digest algorithms. */ - memset(out, 0, outlen); - - return prf_xor(NID_sha512, secret, secretlen, seed, seedlen, out, outlen); -} diff --git a/src/prf.c b/src/prf.c new file mode 100644 index 00000000..354eb42d --- /dev/null +++ b/src/prf.c @@ -0,0 +1,105 @@ +/* + prf.c -- Pseudo-Random Function for key material generation + Copyright (C) 2014 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "system.h" + +#include "prf.h" +#include "ed25519/sha512.h" + +static void memxor(char *buf, char c, size_t len) { + for(size_t i = 0; i < len; i++) + buf[i] ^= c; +} + +static const size_t mdlen = 64; + +// TODO: separate key setup from hmac_sha512 + +static bool hmac_sha512(const char *key, size_t keylen, const char *msg, size_t msglen, char *out) { + char tmp[2 * mdlen]; + sha512_context md; + + if(keylen <= mdlen) { + memcpy(tmp, key, keylen); + memset(tmp + keylen, 0, mdlen - keylen); + } else { + if(sha512(key, keylen, tmp) != 0) + return false; + } + + if(sha512_init(&md) != 0) + return false; + + // ipad + memxor(tmp, 0x36, mdlen); + if(sha512_update(&md, tmp, mdlen) != 0) + return false; + + // message + if(sha512_update(&md, msg, msglen) != 0) + return false; + + if(sha512_final(&md, tmp + mdlen) != 0) + return false; + + // opad + memxor(tmp, 0x36 ^ 0x5c, mdlen); + if(sha512(tmp, sizeof tmp, out) != 0) + return false; + + return true; +} + +/* Generate key material from a master secret and a seed, based on RFC 4346 section 5. + We use SHA512 instead of MD5 and SHA1. + */ + +bool prf(const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, size_t outlen) { + /* Data is what the "inner" HMAC function processes. + It consists of the previous HMAC result plus the seed. + */ + + char data[mdlen + seedlen]; + memset(data, 0, mdlen); + memcpy(data + mdlen, seed, seedlen); + + char hash[mdlen]; + + while(outlen > 0) { + /* Inner HMAC */ + if(!hmac_sha512(data, sizeof data, secret, secretlen, data)) + return false; + + /* Outer HMAC */ + if(outlen >= mdlen) { + if(!hmac_sha512(data, sizeof data, secret, secretlen, out)) + return false; + out += mdlen; + outlen -= mdlen; + } else { + if(!hmac_sha512(data, sizeof data, secret, secretlen, hash)) + return false; + memcpy(out, hash, outlen); + out += outlen; + outlen = 0; + } + } + + return true; +} diff --git a/src/protocol_auth.c b/src/protocol_auth.c index 1255ff08..e667baf0 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -37,6 +37,7 @@ #include "sptps.h" #include "utils.h" #include "xalloc.h" +#include "ed25519/sha512.h" ecdsa_t *invitation_key = NULL; @@ -182,17 +183,14 @@ static bool receive_invitation_sptps(void *handle, uint8_t type, const char *dat return false; // Recover the filename from the cookie and the key - digest_t *digest = digest_open_by_name("sha256", 18); - if(!digest) - abort(); char *fingerprint = ecdsa_get_base64_public_key(invitation_key); + char hash[64]; char hashbuf[18 + strlen(fingerprint)]; char cookie[25]; memcpy(hashbuf, data, 18); memcpy(hashbuf + 18, fingerprint, sizeof hashbuf - 18); - digest_create(digest, hashbuf, sizeof hashbuf, cookie); - b64encode_urlsafe(cookie, cookie, 18); - digest_close(digest); + sha512(hashbuf, sizeof hashbuf, hash); + b64encode_urlsafe(hash, cookie, 18); free(fingerprint); char filename[PATH_MAX], usedname[PATH_MAX];