Update documentation.
This commit is contained in:
parent
bf3a118988
commit
1dcbdf48eb
8 changed files with 212 additions and 486 deletions
363
doc/CONNECTIVITY
363
doc/CONNECTIVITY
|
@ -12,343 +12,34 @@ maintain a stable network.
|
|||
provided that the entire resulting derived work is distributed
|
||||
under the terms of a permission notice identical to this one.
|
||||
|
||||
$Id: CONNECTIVITY,v 1.1.2.9 2002/06/21 10:11:10 guus Exp $
|
||||
$Id: CONNECTIVITY,v 1.1.2.10 2002/09/15 22:19:37 guus Exp $
|
||||
|
||||
1. Problem
|
||||
1. Synchronisation
|
||||
==================
|
||||
|
||||
Each tinc daemon has zero or more connections to other tinc daemons. It will
|
||||
try to keep it's own information synchronised with the other tinc daemons. If
|
||||
one of it's peers sends information, the tinc daemon will check if it is new
|
||||
information. If so, it will update it's 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
|
||||
==========
|
||||
|
||||
We have a set of nodes (A, B, C, ...) that are part of the same VPN. They need
|
||||
to connect to eachother and form a single graph that satisfies the tree
|
||||
property.
|
||||
Every node tells it's 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.
|
||||
|
||||
There is the possibility that loops are formed, the offending connections must
|
||||
be eliminated.
|
||||
|
||||
Suppose we start with two smaller graphs that want to form a single larger
|
||||
graph. Both graphs consist of three nodes:
|
||||
|
||||
A-----B-----C
|
||||
|
||||
|
||||
|
||||
D-----E-----F
|
||||
|
||||
It is very well possible that A wants to connect to D, and F wants to connect
|
||||
to C, both at the same time. The following loop will occur:
|
||||
|
||||
A-----B-----C
|
||||
| ^
|
||||
| |
|
||||
v |
|
||||
D-----E-----F
|
||||
|
||||
The situation described here is totally symmetric, there is no preference to
|
||||
one connection over the other. The problem of resolving the loop, maintaining
|
||||
consistency and stability is therefore not a trivial one.
|
||||
|
||||
What happens when A---D and C---F are connected to eachother? They exchange
|
||||
lists of known hosts. A knows of B and C, and D knows of E and F. The protocol
|
||||
defines ADD_HOST messages, from now on we will say that "node X sends and
|
||||
ADD_HOST(Y) to Z".
|
||||
|
||||
There are two possible scenarios: either both A---D and C---F finish
|
||||
authentication at the same time, or A---D finishes first, so that ADD_HOST
|
||||
messages will reach C and F before they finish authentication.
|
||||
|
||||
1.1 A---D finishes first
|
||||
------------------------
|
||||
|
||||
After A---D authentication finishes the following actions are taken:
|
||||
|
||||
1 A sends ADD_HOST(B) to D
|
||||
A sends ADD_HOST(C) to D
|
||||
D sends ADD_HOST(E) to A
|
||||
D sends ADD_HOST(F) to A
|
||||
|
||||
2 A sends ADD_HOST(D) to B
|
||||
A receives ADD_HOST(E) from D:
|
||||
A sends ADD_HOST(E) to B
|
||||
A receives ADD_HOST(F) from D:
|
||||
A sends ADD_HOST(F) to B
|
||||
D sends ADD_HOST(A) to E
|
||||
D receives ADD_HOST(B) from A:
|
||||
D sends ADD_HOST(B) to E
|
||||
D receives ADD_HOST(C) from A:
|
||||
D sends ADD_HOST(C) to E
|
||||
|
||||
3 B receives ADD_HOST(D) from A,
|
||||
B sends ADD_HOST(D) to C
|
||||
B receives ADD_HOST(E) from A:
|
||||
B sends ADD_HOST(E) to C
|
||||
B receives ADD_HOST(F) from A:
|
||||
B sends ADD_HOST(F) to C
|
||||
E receives ADD_HOST(A) from D:
|
||||
E sends ADD_HOST(A) to F
|
||||
E receives ADD_HOST(B) from D:
|
||||
E sends ADD_HOST(B) to F
|
||||
E receives ADD_HOST(C) from D:
|
||||
E sends ADD_HOST(C) to F
|
||||
|
||||
4 C receives ADD_HOST(D) from B.
|
||||
C receives ADD_HOST(E) from B.
|
||||
C receives ADD_HOST(F) from B.
|
||||
F receives ADD_HOST(A) from E.
|
||||
F receives ADD_HOST(B) from E.
|
||||
F receives ADD_HOST(C) from E.
|
||||
|
||||
Then C---F authentication finishes, the following actions are taken:
|
||||
|
||||
1 C notes that F is already known:
|
||||
Connection is closed.
|
||||
F notes that C is already known:
|
||||
Connection is closed.
|
||||
|
||||
1.2 Both A---D and C---F finish at the same time.
|
||||
-------------------------------------------------
|
||||
|
||||
1 A sends ADD_HOST(B) to D
|
||||
A sends ADD_HOST(C) to D
|
||||
D sends ADD_HOST(E) to A
|
||||
D sends ADD_HOST(F) to A
|
||||
|
||||
C sends ADD_HOST(A) to F
|
||||
C sends ADD_HOST(B) to F
|
||||
F sends ADD_HOST(D) to C
|
||||
F sends ADD_HOST(E) to C
|
||||
|
||||
2 A sends ADD_HOST(D) to B
|
||||
A receives ADD_HOST(E) from D:
|
||||
A sends ADD_HOST(E) to B
|
||||
A receives ADD_HOST(F) from D:
|
||||
A sends ADD_HOST(F) to B
|
||||
D sends ADD_HOST(A) to E
|
||||
D receives ADD_HOST(B) from A:
|
||||
D sends ADD_HOST(B) to E
|
||||
D receives ADD_HOST(C) from A:
|
||||
D sends ADD_HOST(C) to E
|
||||
|
||||
C sends ADD_HOST(F) to B
|
||||
C receives ADD_HOST(D) from F:
|
||||
A sends ADD_HOST(D) to B
|
||||
C receives ADD_HOST(E) from F:
|
||||
A sends ADD_HOST(E) to B
|
||||
F sends ADD_HOSTS(C) to E
|
||||
F receives ADD_HOST(A) from C:
|
||||
D sends ADD_HOST(A) to E
|
||||
F receives ADD_HOST(B) from C:
|
||||
D sends ADD_HOST(B) to E
|
||||
|
||||
3 B receives ADD_HOST(D) from A,
|
||||
B sends ADD_HOST(D) to C
|
||||
B receives ADD_HOST(E) from A:
|
||||
B sends ADD_HOST(E) to C
|
||||
B receives ADD_HOST(F) from A:
|
||||
B sends ADD_HOST(F) to C
|
||||
E receives ADD_HOST(A) from D:
|
||||
E sends ADD_HOST(A) to F
|
||||
E receives ADD_HOST(B) from D:
|
||||
E sends ADD_HOST(B) to F
|
||||
E receives ADD_HOST(C) from D:
|
||||
E sends ADD_HOST(C) to F
|
||||
|
||||
B receives ADD_HOST(F) from C, and notes that is is already known:
|
||||
<insert solution here>
|
||||
B receives ADD_HOST(D) from C, and notes that is is already known:
|
||||
<insert solution here>
|
||||
B receives ADD_HOST(E) from C, and notes that is is already known:
|
||||
<insert solution here>
|
||||
E receives ADD_HOST(C) from F, and notes that is is already known:
|
||||
<insert solution here>
|
||||
E receives ADD_HOST(A) from F, and notes that is is already known:
|
||||
<insert solution here>
|
||||
E receives ADD_HOST(B) from F, and notes that is is already known:
|
||||
<insert solution here>
|
||||
|
||||
4 A receives ADD_HOST(D) from B, and notes that it is already known:
|
||||
<insert solution here>
|
||||
A receives ADD_HOST(E) from B, and notes that it is already known:
|
||||
<insert solution here>
|
||||
A receives ADD_HOST(F) from B, and notes that it is already known:
|
||||
<insert solution here>
|
||||
F receives ADD_HOST(A) from E, and notes that it is already known:
|
||||
<insert solution here>
|
||||
F receives ADD_HOST(B) from E, and notes that it is already known:
|
||||
<insert solution here>
|
||||
F receives ADD_HOST(B) from E, and notes that it is already known:
|
||||
<insert solution here>
|
||||
|
||||
...
|
||||
|
||||
1.2.1 Augmenting ADD_HOST
|
||||
-------------------------
|
||||
|
||||
A solution would be to augment ADD_HOST with an extra parameter, the nexthop of
|
||||
the added host:
|
||||
|
||||
3 B receives ADD_HOST(D,A) from A,
|
||||
B sends ADD_HOST(D,A) to C
|
||||
B receives ADD_HOST(E,D) from A:
|
||||
B sends ADD_HOST(E,D) to C
|
||||
B receives ADD_HOST(F,E) from A:
|
||||
B sends ADD_HOST(F,E) to C
|
||||
E receives ADD_HOST(A,D) from D:
|
||||
E sends ADD_HOST(A,D) to F
|
||||
E receives ADD_HOST(B,A) from D:
|
||||
E sends ADD_HOST(B,A) to F
|
||||
E receives ADD_HOST(C,B) from D:
|
||||
E sends ADD_HOST(C,B) to F
|
||||
|
||||
B receives ADD_HOST(F,C) from C, and notes that F is already known:
|
||||
<insert solution here>
|
||||
B receives ADD_HOST(D,E) from C, and notes that D is already known:
|
||||
<insert solution here>
|
||||
B receives ADD_HOST(E,F) from C, and notes that E is already known:
|
||||
<insert solution here>
|
||||
E receives ADD_HOST(C,F) from F, and notes that C is already known:
|
||||
<insert solution here>
|
||||
E receives ADD_HOST(A,B) from F, and notes that A is already known:
|
||||
<insert solution here>
|
||||
E receives ADD_HOST(B,C) from F, and notes that B is already known:
|
||||
<insert solution here>
|
||||
|
||||
So, B and E have to make a choice. Which ADD_HOST is going to win? Fortunately,
|
||||
since the ADD_HOST messages are augmented, they have an extra piece of
|
||||
information they can use to decide in a deterministic way which one is going to
|
||||
win. For example, B got ADD_HOST(F,E) and ADD_HOST(F,C). Since "E" > "C", it
|
||||
could let ADD_HOST(F,E) win.
|
||||
|
||||
B receives ADD_HOST(F,C) from C, and notes that F is already known:
|
||||
since "C" < "E", B ignores ADD_HOST(F,E)
|
||||
B sends ADD_HOST(F,C) to A
|
||||
...
|
||||
E receives ADD_HOST(C,F) from F, and notes that C is already known:
|
||||
since "F" > "B", E removes the ADD_HOST(C,B) in favour of the new one
|
||||
E sends ADD_HOST(C,F) to D
|
||||
|
||||
4 A receives ADD_HOST(F,E) from B, and notes that F is already known:
|
||||
since "E" < "D", A ignores ADD_HOST(F,D).
|
||||
...
|
||||
D receives ADD_HOST(C,F) from E, and notes that C is already known:
|
||||
since "F" > "B", D removes the ADD_HOST(C,B),
|
||||
closes the connection with C, in favour of the new one.
|
||||
|
||||
Ok, time to forget this crap.
|
||||
|
||||
1.2.2
|
||||
-----
|
||||
|
||||
The problem with the current ADD/DEL_HOST technique is that each host only
|
||||
knows the general direction in which to send packets for the other hosts. It
|
||||
really doesn't know much about the true topology of the network, only about
|
||||
it's direct neighbours. With so little information each host cannot make a
|
||||
certain decision which it knows for sure all the others will decide too.
|
||||
|
||||
Let's do something totally different. Instead of notifying every host of the
|
||||
addition of a new host, which is represented by a vertex in a graph, lets send
|
||||
out notifications of new connections, which are the edges in a graph. This is
|
||||
rather cheap, since our graphs are (almost) spanning trees, there is
|
||||
approximately one edge for each vertex in the graph, so we don't need to send
|
||||
more messages. Furthermore, an edge is characterized by two vertices, so we
|
||||
only send a fixed amount of extra information. The size/complexity of the
|
||||
problem therefore does not increase much.
|
||||
|
||||
What is the advantage of notifying each vertex of new edges instead of new
|
||||
vertices? Well, all the vertices now know exactly which connections are made
|
||||
between each host. This was not known with the former schemes.
|
||||
|
||||
Ok back to our problem:
|
||||
|
||||
A-----B-----C
|
||||
|
||||
|
||||
|
||||
D-----E-----F
|
||||
|
||||
Edges are undirected, and are characterised by the vertices it connects, sorted
|
||||
alphabetically, so the edges in the two graphs are:
|
||||
|
||||
(A,B), (B,C), (D,E) and (E,F).
|
||||
|
||||
So again we have that A wants to connect to D, and F wants to connect to C,
|
||||
both at the same time. The following loop will occur:
|
||||
|
||||
A-----B-----C
|
||||
| ^
|
||||
| |
|
||||
v |
|
||||
D-----E-----F
|
||||
|
||||
Instead of sending ADD_HOSTs, lets assume the hosts send ADD_EDGEs. So, after
|
||||
making the connections:
|
||||
|
||||
1 A sends ADD_EDGE(A,D) to B
|
||||
A sends ADD_EDGE(A,B) to D
|
||||
A sends ADD_EDGE(B,C) to D
|
||||
D sends ADD_EDGE(A,D) to E
|
||||
D sends ADD_EDGE(D,E) to A
|
||||
D sends ADD_EDGE(E,F) to A
|
||||
|
||||
C sends ADD_EDGE(C,F) to B
|
||||
C sends ADD_EDGE(A,B) to F
|
||||
C sends ADD_EDGE(B,C) to F
|
||||
F sends ADD_EDGE(C,F) to E
|
||||
F sends ADD_EDGE(D,E) to C
|
||||
F sends ADD_EDGE(E,F) to C
|
||||
|
||||
2 B receives ADD_EDGE(A,D) from A:
|
||||
B sends ADD_EDGE(A,D) to C
|
||||
B receives ADD_EDGE(D,E) from A:
|
||||
B sends ADD_EDGE(D,E) to C
|
||||
B receives ADD_EDGE(E,F) from A:
|
||||
B sends ADD_EDGE(E,F) to C
|
||||
...
|
||||
|
||||
B receives ADD_EDGE(C,F) from C, notes that both C and F are already known,
|
||||
but that the edge (C,F) was not known, so a loop has been created:
|
||||
<resolve loop here>
|
||||
|
||||
Ok, how to resolve the loop? Remeber, we want to do that in such a way that it
|
||||
is consistent with the way all the other hosts resolve the loop. Here is the
|
||||
things B does when it notices that a loop is going to be formed:
|
||||
|
||||
B performs a Breadth First Search from the first element of the list of all
|
||||
known hosts sorted alfabetically, in this case A, and thereby finds a
|
||||
spanning tree. (This might later be changed into a minimum spanning tree
|
||||
alhorithm, but the key point here is that all hosts do this with exactly the
|
||||
same starting parameters.) All known edges that are not in the spanning tree
|
||||
are marked inactive.
|
||||
|
||||
An edge marked inactive does not mean anything, unless this edge is connected
|
||||
to B itself. In that case, B will stop sending messages over that edge. B might
|
||||
consider closing this edge, but this is not really needed. Keeping it means no
|
||||
DEL_EDGE has to be sent for it, and if another edge is removed (which will
|
||||
quite certainly split the graph if it's a spanning tree), this edge might be
|
||||
reactivated, without the need of sending a new ADD_EDGE for it. On the other
|
||||
hand, we mustn't keep to many inactive edges, because we want to keep the
|
||||
number of known edges linear to the number of hosts (otherwise the size of the
|
||||
problem will grow quadratically).
|
||||
|
||||
So, since B didn't deactivate one of it's own edges, it forwards the
|
||||
ADD_EDGE(C,F) to A, which also does a BFS, and so on, until it reaches F. F of
|
||||
course also does a BFS, notes that is is one of it's own edges. It deactivates
|
||||
the edge (C,F), and consequently will not forward the ADD_EDGE(C,F) to C
|
||||
anymore. In the mean time, C got messages from B which will make C do the same.
|
||||
|
||||
Ok, suppose a DEL_EDGE was sent, and it means an inactive edge has to be
|
||||
reactivated. The vertices connected by that edge must exchange their entire
|
||||
knowledge of edges again, because in the mean time other messages could have
|
||||
been sent, which were not properly forwarded. Take this example:
|
||||
|
||||
X C-----D
|
||||
| | |
|
||||
| | |
|
||||
v | |
|
||||
A-----B- - -E
|
||||
|
||||
The edge (B,E) is inactive. X is trying to make a new connection with A. A
|
||||
sends an ADD_EDGE(A,X) to B, which forwards it to C. At that time, the
|
||||
connection between C and D goes down, so C sends a DEL_EDGE(C,D) to B, and D
|
||||
sends a DEL_EDGE(C,D) to E. If we just allow (B,E) to be reactivated again
|
||||
without anything else, then E and D will never have received the ADD_EDGE(A,X).
|
||||
So, B and E have to exchange edges again, and propagate them to the hosts they
|
||||
already know.
|
||||
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.
|
||||
|
|
82
doc/PROTOCOL
82
doc/PROTOCOL
|
@ -12,7 +12,7 @@ This is the protocol documentation for tinc, a Virtual Private Network daemon.
|
|||
provided that the entire resulting derived work is distributed
|
||||
under the terms of a permission notice identical to this one.
|
||||
|
||||
$Id: PROTOCOL,v 1.1.2.7 2002/06/21 10:11:10 guus Exp $
|
||||
$Id: PROTOCOL,v 1.1.2.8 2002/09/15 22:19:37 guus Exp $
|
||||
|
||||
|
||||
1. Protocols used in tinc
|
||||
|
@ -69,24 +69,62 @@ synchronised.
|
|||
|
||||
daemon message
|
||||
--------------------------------------------------------------------------
|
||||
origin ADD_EDGE node1 12.23.34.45 655 node2 21.32.43.54 655 222 0
|
||||
| | | \___________________/ | +-> options
|
||||
| | | | +----> weight
|
||||
| | | +----------------> see below
|
||||
| | +--> UDP port
|
||||
| +----------> real address
|
||||
+------------------> name of node on one side of the edge
|
||||
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
|
||||
| +--------> IPv4 network address
|
||||
| +--------> 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
|
||||
|
@ -97,33 +135,17 @@ act as a proxy and forward its copy back to the requestor.
|
|||
|
||||
daemon message
|
||||
--------------------------------------------------------------------------
|
||||
daemon REQ_KEY origin destination
|
||||
| +--> name of the tinc daemon it wants the key from
|
||||
+----------> name of the daemon that wants the key
|
||||
|
||||
daemon 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
|
||||
|
||||
daemon KEY_CHANGED origin
|
||||
+--> daemon that has changed it's packet key
|
||||
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.
|
||||
|
||||
daemon message
|
||||
--------------------------------------------------------------------------
|
||||
origin PING
|
||||
dest. PONG
|
||||
--------------------------------------------------------------------------
|
||||
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.
|
||||
|
|
|
@ -12,7 +12,7 @@ This is the security documentation for tinc, a Virtual Private Network daemon.
|
|||
provided that the entire resulting derived work is distributed
|
||||
under the terms of a permission notice identical to this one.
|
||||
|
||||
$Id: SECURITY2,v 1.1.2.3 2002/06/21 10:11:10 guus Exp $
|
||||
$Id: SECURITY2,v 1.1.2.4 2002/09/15 22:19:37 guus Exp $
|
||||
|
||||
Proposed new authentication scheme
|
||||
----------------------------------
|
||||
|
@ -66,17 +66,15 @@ server CHAL_REPLY 928ffe
|
|||
After the correct challenge replies are recieved, both ends have proved
|
||||
their identity. Further information is exchanged.
|
||||
|
||||
client ACK 655 12.23.34.45 123 0
|
||||
| | | +-> options
|
||||
| | +----> estimated weight
|
||||
| +------------> IP address of server as seen by client
|
||||
+--------------------> UDP port of client
|
||||
client ACK 655 123 0
|
||||
| | +-> options
|
||||
| +----> estimated weight
|
||||
+--------> listening port of client
|
||||
|
||||
server ACK 655 21.32.43.54 321 0
|
||||
| | | +-> options
|
||||
| | +----> estimated weight
|
||||
| +------------> IP address of client as seen by server
|
||||
+--------------------> UDP port of server
|
||||
server ACK 655 321 0
|
||||
| | +-> options
|
||||
| +----> estimated weight
|
||||
+--------> listening port of server
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
This new scheme has several improvements, both in efficiency and security.
|
||||
|
|
|
@ -6,10 +6,13 @@
|
|||
# but for ethertap and FreeBSD this is tap0, tap1, tap2 etcetera,
|
||||
# for Solaris and OpenBSD it is tun0, tun1, etcetera.
|
||||
|
||||
# Set hardware ethernet address (required!)
|
||||
# Set hardware ethernet address, needed on Linux when in router mode
|
||||
ifconfig $INTERFACE hw ether fe:fd:0:0:0:0
|
||||
|
||||
# Give it the right ip and netmask. Remember, the subnet of the
|
||||
# tap device must be larger than that of the individual Subnets
|
||||
# as defined in the host configuration file!
|
||||
ifconfig $INTERFACE 192.168.1.1 netmask 255.255.0.0 -arp
|
||||
ifconfig $INTERFACE 192.168.1.1 netmask 255.255.0.0
|
||||
|
||||
# Disable ARP, needed on Linux when in router mode
|
||||
ifconfig $INTERFACE -arp
|
||||
|
|
|
@ -18,8 +18,8 @@ ConnectTo = beta
|
|||
# The tap device tinc will use. Required.
|
||||
# Default is /dev/tap0 for ethertap or FreeBSD,
|
||||
# /dev/tun0 for Solaris and OpenBSD,
|
||||
# and /dev/misc/net/tun for Linux tun/tap device.
|
||||
Device = /dev/misc/net/tun
|
||||
# and /dev/net/tun for Linux tun/tap device.
|
||||
Device = /dev/net/tun
|
||||
|
||||
# The file in which the private key for this host is stored. Required.
|
||||
PrivateKeyFile = /etc/tinc/example/rsa_key.priv
|
||||
|
|
|
@ -129,7 +129,7 @@ If you don't specify a host with
|
|||
.Nm tinc
|
||||
won't try to connect to other daemons at all,
|
||||
and will instead just listen for incoming connections.
|
||||
.It Va Device Li = Ar device Po /dev/tap0 or /dev/misc/net/tun Pc
|
||||
.It Va Device Li = Ar device Po /dev/tap0 or /dev/net/tun Pc
|
||||
The virtual network device to use.
|
||||
.Nm tinc
|
||||
will automatically detect what kind of device it is.
|
||||
|
|
217
doc/tinc.texi
217
doc/tinc.texi
|
@ -1,5 +1,5 @@
|
|||
\input texinfo @c -*-texinfo-*-
|
||||
@c $Id: tinc.texi,v 1.8.4.31 2002/07/16 13:18:27 guus Exp $
|
||||
@c $Id: tinc.texi,v 1.8.4.32 2002/09/15 22:19:37 guus Exp $
|
||||
@c %**start of header
|
||||
@setfilename tinc.info
|
||||
@settitle tinc Manual
|
||||
|
@ -18,7 +18,7 @@ Copyright @copyright{} 1998-2002 Ivo Timmermans
|
|||
<ivo@@o2w.nl>, Guus Sliepen <guus@@sliepen.eu.org> and
|
||||
Wessel Dankers <wsl@@nl.linux.org>.
|
||||
|
||||
$Id: tinc.texi,v 1.8.4.31 2002/07/16 13:18:27 guus Exp $
|
||||
$Id: tinc.texi,v 1.8.4.32 2002/09/15 22:19:37 guus Exp $
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of this
|
||||
manual provided the copyright notice and this permission notice are
|
||||
|
@ -43,7 +43,7 @@ Copyright @copyright{} 1998-2002 Ivo Timmermans
|
|||
<ivo@@o2w.nl>, Guus Sliepen <guus@@sliepen.eu.org> and
|
||||
Wessel Dankers <wsl@@nl.linux.org>.
|
||||
|
||||
$Id: tinc.texi,v 1.8.4.31 2002/07/16 13:18:27 guus Exp $
|
||||
$Id: tinc.texi,v 1.8.4.32 2002/09/15 22:19:37 guus Exp $
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of this
|
||||
manual provided the copyright notice and this permission notice are
|
||||
|
@ -456,8 +456,8 @@ and the corresponding network interfaces.
|
|||
@cindex requirements
|
||||
@cindex libraries
|
||||
Before you can configure or build tinc, you need to have the OpenSSL
|
||||
library installed on your system. If you try to configure tinc without
|
||||
having installed it, configure will give you an error message, and stop.
|
||||
and zlib 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::
|
||||
|
@ -565,7 +565,7 @@ 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'.
|
||||
`./configure' and then `make'.
|
||||
More detailed instructions are in the file @file{INSTALL}, which is
|
||||
included in the source distribution.
|
||||
|
||||
|
@ -651,7 +651,7 @@ mknod -m 600 /dev/tun c 10 200
|
|||
|
||||
If you use Linux, and you run the new 2.4 kernel using the devfs filesystem,
|
||||
then the tun/tap device will probably be automatically generated as
|
||||
@file{/dev/misc/net/tun}.
|
||||
@file{/dev/net/tun}.
|
||||
|
||||
Unlike the ethertap device, you do not need multiple device files if
|
||||
you are planning to run multiple tinc daemons.
|
||||
|
@ -773,9 +773,9 @@ assume that you use it.
|
|||
@section How connections work
|
||||
|
||||
When tinc starts up, it parses the command-line options and then
|
||||
reads in the configuration file.
|
||||
If it sees a `ConnectTo' value pointing to another tinc daemon in the file,
|
||||
it will try to connect to that other one.
|
||||
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,
|
||||
|
@ -783,14 +783,14 @@ 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 any network problems.
|
||||
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 eachother however.
|
||||
It does not matter if two tinc daemons have a `ConnectTo' value pointing to each other however.
|
||||
|
||||
|
||||
@c ==================================================================
|
||||
|
@ -858,7 +858,7 @@ tinc won't try to connect to other daemons at all,
|
|||
and will instead just listen for incoming connections.
|
||||
|
||||
@cindex Device
|
||||
@item @strong{Device = <device>} (/dev/tap0 or /dev/misc/net/tun)
|
||||
@item @strong{Device = <device>} (/dev/tap0 or /dev/net/tun)
|
||||
The virtual network device to use. Note that you can only use one device per
|
||||
daemon. See also @ref{Device files}.
|
||||
|
||||
|
@ -993,10 +993,8 @@ up to the length of the digest produced by the digest algorithm.
|
|||
|
||||
@cindex Port
|
||||
@item Port = <port> (655)
|
||||
Connect to the upstream host (given with the ConnectTo directive) on
|
||||
port port. port may be given in decimal (default), octal (when preceded
|
||||
by a single zero) o hexadecimal (prefixed with 0x). port is the port
|
||||
number for both the UDP and the TCP (meta) connections.
|
||||
This is the port this tinc daemon listens on.
|
||||
You can use decimal portnumbers or symbolic names (as listed in /etc/services).
|
||||
|
||||
@cindex PublicKey
|
||||
@item PublicKey = <key> [obsolete]
|
||||
|
@ -1323,7 +1321,7 @@ and in @file{/etc/tinc/company/tinc.conf}:
|
|||
@example
|
||||
Name = BranchD
|
||||
ConnectTo = BranchC
|
||||
Device = /dev/misc/net/tun
|
||||
Device = /dev/net/tun
|
||||
PrivateKeyFile = /etc/tinc/company/rsa_key.priv
|
||||
@end example
|
||||
|
||||
|
@ -1393,9 +1391,6 @@ and look in the syslog to find out what the problems are.
|
|||
Besides the settings in the configuration file, tinc also accepts some
|
||||
command line options.
|
||||
|
||||
This list is a longer version of that in the manpage. The latter is
|
||||
generated automatically, so may be more up-to-date.
|
||||
|
||||
@cindex command line
|
||||
@cindex runtime options
|
||||
@cindex options
|
||||
|
@ -1434,6 +1429,10 @@ Connect to net NETNAME. @xref{Multiple networks}.
|
|||
Don't fork and detach.
|
||||
This will also disable the automatic restart mechanism for fatal errors.
|
||||
|
||||
@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.
|
||||
|
||||
@item --version
|
||||
Output version information and exit.
|
||||
|
||||
|
@ -1456,7 +1455,7 @@ only, so keep an eye on it!
|
|||
@item You forgot to compile `Netlink device emulation' in the kernel.
|
||||
@end itemize
|
||||
|
||||
@item Can't write to /dev/misc/net/tun: No such device
|
||||
@item Can't write to /dev/net/tun: No such device
|
||||
|
||||
@itemize
|
||||
@item You forgot to `modprobe tun'.
|
||||
|
@ -1481,15 +1480,6 @@ or if that is not the case, try changing the prefix length into /32.
|
|||
|
||||
@item Network doesn't work, syslog shows only packets of length 46
|
||||
|
||||
@cindex arp
|
||||
@example
|
||||
Jan 1 12:00:00 host tinc.net[1234]: Read packet of length 46 from tap device
|
||||
Jan 1 12:00:00 host tinc.net[1234]: Trying to look up 0.0.192.168 in connection list failed!
|
||||
@end example
|
||||
@itemize
|
||||
@item Add the `ifconfig $INTERFACE -arp' to tinc-up.
|
||||
@end itemize
|
||||
|
||||
@item Network address and prefix length do not match!
|
||||
|
||||
@itemize
|
||||
|
@ -1510,9 +1500,7 @@ this message. In normal operation, these errors should not occur.
|
|||
@itemize
|
||||
@item You must specify the complete pathname.
|
||||
Specifying a relative path does not make sense here. tinc changes its
|
||||
directory to / when starting (to avoid keeping a mount point busy); and
|
||||
even if we built in a default directory to look for these files, the key
|
||||
files are bound to be in a different directory.
|
||||
directory to / when starting (to avoid keeping a mount point busy).
|
||||
@end itemize
|
||||
|
||||
@end table
|
||||
|
@ -1565,9 +1553,11 @@ 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).
|
||||
|
||||
After the destination has been determined, a sequence number will be added to the packet.
|
||||
The packet will then be encrypted and a message authentication
|
||||
code will be appended.
|
||||
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
|
||||
|
@ -1586,16 +1576,21 @@ To let the kernel on the receiving end accept the packet, 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 cannot be set
|
||||
by the sending daemons.
|
||||
tinc solves this by always overwriting the
|
||||
destination MAC address with fe:fd:0:0:0:0. That is also the reason why you must
|
||||
set the MAC address of your tap interface to that address.
|
||||
tinc solves this by letting the receiving end detect the MAC address
|
||||
and overwriting the destination MAC address of the received packet.
|
||||
However, the MAC address of the network interface at the receiver might not always be known to tinc.
|
||||
That is the reason why you should set the MAC address of your tap interface to that address
|
||||
when in routing mode.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
@c ==================================================================
|
||||
@node The meta-connection, , The UDP tunnel, The connection
|
||||
@subsection The meta-connection
|
||||
|
||||
Having only an UDP connection available is not enough. Though suitable
|
||||
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.
|
||||
|
||||
|
@ -1637,7 +1632,8 @@ 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
|
||||
daemon started with the --bypass-security option
|
||||
and to read and write requests by hand, provided that one
|
||||
understands the numeric codes sent.
|
||||
|
||||
The authentication scheme is described in @ref{Authentication protocol}. After a
|
||||
|
@ -1651,64 +1647,78 @@ synchronised.
|
|||
@example
|
||||
daemon message
|
||||
--------------------------------------------------------------------------
|
||||
origin ADD_EDGE node1 12.23.34.45 655 node2 21.32.43.54 655 222 0
|
||||
| | | \___________________/ | +-> options
|
||||
| | | | +----> weight
|
||||
| | | +----------------> see below
|
||||
| | +--> UDP port
|
||||
| +----------> real address
|
||||
+------------------> name of node on one side of the edge
|
||||
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
|
||||
| +--------> IPv4 network address
|
||||
| +--------> 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. If any hop on the way has already learned the key, it will
|
||||
act as a proxy and forward its copy back to the requester.
|
||||
|
||||
@cindex REQ_KEY
|
||||
@cindex ANS_KEY
|
||||
@cindex KEY_CHANGED
|
||||
@example
|
||||
daemon message
|
||||
--------------------------------------------------------------------------
|
||||
daemon REQ_KEY origin destination
|
||||
| +--> name of the tinc daemon it wants the key from
|
||||
+----------> name of the daemon that wants the key
|
||||
|
||||
daemon 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
|
||||
|
||||
daemon KEY_CHANGED origin
|
||||
+--> daemon that has changed it's packet key
|
||||
--------------------------------------------------------------------------
|
||||
@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.
|
||||
destination.
|
||||
|
||||
@cindex PING
|
||||
@cindex PONG
|
||||
|
@ -1720,6 +1730,14 @@ 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.
|
||||
|
||||
|
@ -1813,17 +1831,15 @@ server CHAL_REPLY 928ffe
|
|||
After the correct challenge replies are received, both ends have proved
|
||||
their identity. Further information is exchanged.
|
||||
|
||||
client ACK 655 12.23.34.45 123 0
|
||||
| | | +-> options
|
||||
| | +----> estimated weight
|
||||
| +------------> IP address of server as seen by client
|
||||
+--------------------> UDP port of client
|
||||
client ACK 655 123 0
|
||||
| | +-> options
|
||||
| +----> estimated weight
|
||||
+--------> listening port of client
|
||||
|
||||
server ACK 655 21.32.43.54 321 0
|
||||
| | | +-> options
|
||||
| | +----> estimated weight
|
||||
| +------------> IP address of client as seen by server
|
||||
+--------------------> UDP port of server
|
||||
server ACK 655 321 0
|
||||
| | +-> options
|
||||
| +----> estimated weight
|
||||
+--------> listening port of server
|
||||
--------------------------------------------------------------------------
|
||||
@end example
|
||||
|
||||
|
@ -1891,8 +1907,8 @@ The UDP packet containing the network packet from the VPN has the following layo
|
|||
Encrypted with symmetric cipher
|
||||
@end example
|
||||
|
||||
So, the entire VPN packet is encrypted using a symmetric cipher. A 32 bits
|
||||
sequence number is added in front of the actual VPN packet, to act as a unique
|
||||
So, the entire VPN packet is encrypted using a symmetric cipher, including a 32 bits
|
||||
sequence number that is added in front of the actual VPN packet, to act as a unique
|
||||
IV for each packet and to prevent replay attacks. A message authentication code
|
||||
is added to the UDP packet to prevent alteration of packets. By default the
|
||||
first 4 bytes of the digest are used for this, but this can be changed using
|
||||
|
@ -1918,8 +1934,8 @@ tinc's website is at @url{http://tinc.nl.linux.org/},
|
|||
this server is located in the Netherlands.
|
||||
|
||||
@cindex IRC
|
||||
We have an IRC channel on the Open Projects IRC network. Connect to
|
||||
@uref{http://openprojects.nu/services/irc.html, irc.openprojects.net},
|
||||
We have an IRC channel on the FreeNode IRC network. Connect to
|
||||
@uref{http://www.freenode.net/, irc.freenode.net}
|
||||
and join channel #tinc.
|
||||
|
||||
|
||||
|
@ -1929,14 +1945,7 @@ and join channel #tinc.
|
|||
|
||||
@table @asis
|
||||
@item Ivo Timmermans (zarq) (@email{ivo@@o2w.nl})
|
||||
Main coder/hacker and maintainer of the package.
|
||||
|
||||
@item Guus Sliepen (guus) (@email{guus@@sliepen.eu.org})
|
||||
Originator of it all, co-author.
|
||||
|
||||
@item Wessel Dankers (Ubiq) (@email{wsl@@nl.linux.org})
|
||||
For the name `tinc' and various suggestions.
|
||||
|
||||
@end table
|
||||
|
||||
We have received a lot of valuable input from users. With their help,
|
||||
|
|
|
@ -62,6 +62,9 @@ Connect to net
|
|||
.It Fl D, -no-detach
|
||||
Don't fork and detach.
|
||||
This will also disable the automatic restart mechanism for fatal errors.
|
||||
.It Fl 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.
|
||||
.It Fl -version
|
||||
Output version information and exit.
|
||||
.El
|
||||
|
|
Loading…
Reference in a new issue