forked from I2P_Developers/i2p.www
Migrated tunnel pages
This commit is contained in:
@@ -79,10 +79,18 @@
|
||||
<li><a href="{{ site_url('docs/spec/i2np') }}"><span>I2NP</span></a></li>
|
||||
<li><a href="{{ site_url('docs/spec/plugin') }}"><span>{{ _('Plugins') }}</span></a></li>
|
||||
<li><a href="{{ site_url('docs/spec/ssu') }}"><span>SSU</span></a></li>
|
||||
<li><a href="{{ site_url('docs/spec/tunnel_creation') }}"><span>{{ _('Tunnel creation') }}</span></a></li>
|
||||
<li><a href="{{ site_url('docs/spec/tunnel_message') }}"><span>{{ _('Tunnel messages') }}</span></a></li>
|
||||
<li><a href="{{ site_url('docs/spec/updates') }}"><span>{{ _('Software updates') }}</span></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="has-sub"><a href="#"><span>{{ _('Tunnels') }}</span></a>
|
||||
<ul>
|
||||
<li><a href="{{ site_url('docs/tunnels/implementation') }}"><span>{{ _('Tunnel implementation') }}</span></a></li>
|
||||
<li><a href="{{ site_url('docs/tunnels/unidirectional') }}"><span>{{ _('Unidirectional tunnels') }}</span></a></li>
|
||||
<li><a href="{{ site_url('docs/tunnels/old') }}"><span>{{ _('Old implementation') }}</span></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="{{ site_url('docs/naming') }}"><span>{{ _('Naming and addressbook') }}</span></a></li>
|
||||
<li><a href="{{ site_url('docs/plugins') }}"><span>{{ _('Plugins') }}</span></a></li>
|
||||
</ul>
|
||||
|
326
i2p2www/pages/site/docs/spec/tunnel_creation.html
Normal file
326
i2p2www/pages/site/docs/spec/tunnel_creation.html
Normal file
@@ -0,0 +1,326 @@
|
||||
{% extends "_layout.html" %}
|
||||
{% block title %}Tunnel Creation{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
This page documents the current tunnel build implementation.
|
||||
Updated August 2010 for release 0.8
|
||||
|
||||
<h2 id="tunnelCreate.overview">Tunnel Creation Specification</h2>
|
||||
|
||||
<p>
|
||||
This document specifies the details of the encrypted tunnel build messages
|
||||
used to create tunnels using a "non-interactive telescoping" method.
|
||||
See <a href="tunnel-alt.html">the tunnel build document</a>
|
||||
for an overview of the process, including peer selection and ordering methods.
|
||||
|
||||
<p>The tunnel creation is accomplished by a single message passed along
|
||||
the path of peers in the tunnel, rewritten in place, and transmitted
|
||||
back to the tunnel creator. This single tunnel message is made up
|
||||
of a variable number of records (up to 8) - one for each potential peer in
|
||||
the tunnel. Individual records are asymmetrically
|
||||
<a href="how_cryptography.html#elgamal">(ElGamal)</a>
|
||||
encrypted to be
|
||||
read only by a specific peer along the path, while an additional
|
||||
symmetric layer of encryption
|
||||
<a href="how_cryptography.html#AES">(AES)</a>
|
||||
is added at each hop so as to expose
|
||||
the asymmetrically encrypted record only at the appropriate time.</p>
|
||||
|
||||
<h3 id="number">Number of Records</h3>
|
||||
Not all records must contain valid data.
|
||||
The build message for a 3-hop tunnel, for example, may contain more records
|
||||
to hide the actual length of the tunnel from the participants.
|
||||
There are two build message types. The original
|
||||
<a href="i2np_spec.html#msg_TunnelBuild">Tunnel Build Message</a> (TBM)
|
||||
contains 8 records, which is more than enough for any practical tunnel length.
|
||||
The recently-implemented
|
||||
<a href="i2np_spec.html#msg_VariableTunnelBuild">Variable Tunnel Build Message</a> (VTBM)
|
||||
contains 1 to 8 records. The originator may trade off the size of the message
|
||||
with the desired amount of tunnel length obfuscation.
|
||||
<p>
|
||||
In the current network, most tunnels are 2 or 3 hops long.
|
||||
The current implementation uses a 5-record VTBM to build tunnels of 4 hops or less,
|
||||
and the 8-record TBM for longer tunnels.
|
||||
The 5-record VTBM (which, when fragmented, fits in three 1KB tunnel messaages) reduces network traffic
|
||||
and increases build sucess rate, because smaller messages are less likely to be dropped.
|
||||
<p>
|
||||
The reply message must be the same type and length as the build message.
|
||||
|
||||
|
||||
<h3 id="tunnelCreate.requestRecord">Request Record Specification</h3>
|
||||
|
||||
Also specified in the
|
||||
<a href="i2np_spec.html#struct_BuildRequestRecord">I2NP Specification</a>
|
||||
|
||||
<p>Cleartext of the record, visible only to the hop being asked:</p><pre>
|
||||
bytes 0-3: tunnel ID to receive messages as
|
||||
bytes 4-35: local router identity hash
|
||||
bytes 36-39: next tunnel ID
|
||||
bytes 40-71: next router identity hash
|
||||
bytes 72-103: AES-256 tunnel layer key
|
||||
bytes 104-135: AES-256 tunnel IV key
|
||||
bytes 136-167: AES-256 reply key
|
||||
bytes 168-183: AES-256 reply IV
|
||||
byte 184: flags
|
||||
bytes 185-188: request time (in hours since the epoch)
|
||||
bytes 189-192: next message ID
|
||||
bytes 193-221: uninterpreted / random padding</pre>
|
||||
|
||||
<p>The next tunnel ID and next router identity hash fields are used to
|
||||
specify the next hop in the tunnel, though for an outbound tunnel
|
||||
endpoint, they specify where the rewritten tunnel creation reply
|
||||
message should be sent. In addition, the next message ID specifies the
|
||||
message ID that the message (or reply) should use.</p>
|
||||
|
||||
<p>The flags field contains the following:
|
||||
<pre>
|
||||
Bit order: 76543210 (bit 7 is MSB)
|
||||
bit 7: if set, allow messages from anyone
|
||||
bit 6: if set, allow messages to anyone, and send the reply to the
|
||||
specified next hop in a Tunnel Build Reply Message
|
||||
bits 5-0: Undefined
|
||||
</pre>
|
||||
|
||||
Bit 7 indicates that the hop will be an inbound gateway (IBGW).
|
||||
Bit 6 indicates that the hop will be an outbound endpoint (OBEP).
|
||||
If neither bit is set, the hop will be an intermediate participant.
|
||||
|
||||
<h4>Request Record Creation</h4>
|
||||
<p>
|
||||
Every hop gets a random Tunnel ID.
|
||||
The current and next-hop Tunnel IDs are filled in.
|
||||
Every record gets a random tunnel IV key, and reply IV.
|
||||
The layer and reply key pairs are generated.
|
||||
</p>
|
||||
|
||||
|
||||
<h4 id="encryption">Request Record Encryption</h4>
|
||||
|
||||
<p>That cleartext record is <a href="how_cryptography.html#elgamal">ElGamal 2048 encrypted</a> with the hop's
|
||||
public encryption key and formatted into a 528 byte record:</p><pre>
|
||||
bytes 0-15: First 16 bytes of the SHA-256 of the current hop's router identity
|
||||
bytes 16-527: ElGamal-2048 encrypted request record</pre>
|
||||
|
||||
In the 512-byte encrypted record,
|
||||
the ElGamal data contains bytes 1-256 and 258-513 of the
|
||||
<a href="how_cryptography.html#elgamal">514-byte ElGamal encrypted block</a>.
|
||||
The two padding bytes from the block (the zero bytes at locations 0 and 257) are removed.
|
||||
|
||||
<p>Since the cleartext uses the full field, there is no need for
|
||||
additional padding beyond <code>SHA256(cleartext) + cleartext</code>.</p>
|
||||
|
||||
<p>
|
||||
Each 528-byte record is then iteratively encrypted
|
||||
(using AES decryption, with the reply key and reply IV for each hop) so that the router identity will only be in cleartext
|
||||
for the hop in question.
|
||||
</p>
|
||||
|
||||
<h3 id="tunnelCreate.hopProcessing">Hop Processing and Encryption</h3>
|
||||
|
||||
<p>When a hop receives a TunnelBuildMessage, it looks through the
|
||||
records contained within it for one starting with their own identity
|
||||
hash (trimmed to 8 bytes). It then decrypts the ElGamal block from
|
||||
that record and retrieves the protected cleartext. At that point,
|
||||
they make sure the tunnel request is not a duplicate by feeding the
|
||||
AES-256 reply key into a bloom filter.
|
||||
Duplicates or invalid requests
|
||||
are dropped.</p>
|
||||
|
||||
<p>After deciding whether they will agree to participate in the tunnel
|
||||
or not, they replace the record that had contained the request with
|
||||
an encrypted reply block. All other records are <a href="how_cryptography.html#AES">AES-256
|
||||
encrypted</a> with the included reply key and IV. Each is
|
||||
encrypted separately, rather than chained across records.</p>
|
||||
|
||||
<p>
|
||||
Each hop knows only its own response.
|
||||
If it agrees, it will maintain the tunnel until expiration,
|
||||
even if it will not be used,
|
||||
as it cannot know whether all other hops agreed.
|
||||
</p>
|
||||
|
||||
|
||||
<h4 id="tunnelCreate.replyRecord">Reply Record Specification</h4>
|
||||
|
||||
<p>After the current hop reads their record, they replace it with a
|
||||
reply record stating whether or not they agree to participate in the
|
||||
tunnel, and if they do not, they classify their reason for
|
||||
rejection. This is simply a 1 byte value, with 0x0 meaning they
|
||||
agree to participate in the tunnel, and higher values meaning higher
|
||||
levels of rejection.
|
||||
<p>
|
||||
The following rejection codes are defined:
|
||||
<ul>
|
||||
<li>
|
||||
TUNNEL_REJECT_PROBABALISTIC_REJECT = 10
|
||||
<li>
|
||||
TUNNEL_REJECT_TRANSIENT_OVERLOAD = 20
|
||||
<li>
|
||||
TUNNEL_REJECT_BANDWIDTH = 30
|
||||
<li>
|
||||
TUNNEL_REJECT_CRIT = 50
|
||||
</ul>
|
||||
To hide other causes, such as router shutdown, from peers, the current implementation
|
||||
uses TUNNEL_REJECT_BANDWIDTH for almost all rejections.
|
||||
|
||||
<p>
|
||||
The reply is encrypted with the AES session
|
||||
key delivered to it in the encrypted block, padded with 527 bytes of random data
|
||||
to reach the full record size.
|
||||
The padding is placed before the status byte:
|
||||
</p><pre>
|
||||
AES-256-CBC(SHA-256(padding+status) + padding + status, key, IV)</pre>
|
||||
This is also described in the
|
||||
<a href="i2np_spec.html#msg_TunnelBuildReply">I2NP spec</a>.
|
||||
|
||||
<h3 id="tunnelCreate.requestPreparation">Tunnel Build Message Preparation</h3>
|
||||
|
||||
<p>When building a new Tunnel Build Messaage, all of the Build Request Records must first be
|
||||
built and asymmetrically encrypted using
|
||||
<a href="how_cryptography.html#elgamal">ElGamal</a>.
|
||||
Each record is then
|
||||
premptively decrypted with the reply keys and IVs of the hops earlier in the
|
||||
path, using
|
||||
<a href="how_cryptography.html#AES">AES</a>.
|
||||
That decryption should be run in reverse order so that the
|
||||
asymmetrically encrypted data will show up in the clear at the
|
||||
right hop after their predecessor encrypts it.</p>
|
||||
|
||||
<p>The excess records not needed for individual requests are simply
|
||||
filled with random data by the creator.</p>
|
||||
|
||||
<h3 id="tunnelCreate.requestDelivery">Tunnel Build Message Delivery</h3>
|
||||
|
||||
<p>For outbound tunnels, the delivery is done directly from the tunnel
|
||||
creator to the first hop, packaging up the TunnelBuildMessage as if
|
||||
the creator was just another hop in the tunnel. For inbound
|
||||
tunnels, the delivery is done through an existing outbound tunnel.
|
||||
The outbound tunnel is generally from the same pool as the new tunnel being built.
|
||||
If no outbound tunnel is available in that pool, an outbound exploratory tunnel is used.
|
||||
At startup, when no outbound exploratory tunnel exists yet, a fake 0-hop
|
||||
outbound tunnel is used.</p>
|
||||
|
||||
<h3 id="tunnelCreate.endpointHandling">Tunnel Build Message Endpoint Handling</h3>
|
||||
|
||||
<p>
|
||||
For creation of an outbound tunnel,
|
||||
when the request reaches an outbound endpoint (as determined by the
|
||||
'allow messages to anyone' flag), the hop is processed as usual,
|
||||
encrypting a reply in place of the record and encrypting all of the
|
||||
other records, but since there is no 'next hop' to forward the
|
||||
TunnelBuildMessage on to, it instead places the encrypted reply
|
||||
records into a
|
||||
<a href="i2np_spec.html#msg_TunnelBuildReply">TunnelBuildReplyMessage</a>
|
||||
or
|
||||
<a href="i2np_spec.html#msg_VariableTunnelBuildReply">VariableTunnelBuildReplyMessage</a>
|
||||
(the type of message and number of records must match that of the request)
|
||||
and delivers it to the
|
||||
reply tunnel specified within the request record. That reply tunnel
|
||||
forwards the Tunnel Build Reply Message back to the tunnel creator,
|
||||
<a href="tunnel-alt.html#tunnel.operation">just as for any other message</a>.
|
||||
The tunnel creator then
|
||||
processes it, as described below.</p>
|
||||
|
||||
<p>The reply tunnel was selected by the creator as follows:
|
||||
Generally it is an inbound tunnel from the same pool as the new outbound tunnel being built.
|
||||
If no inbound tunnel is available in that pool, an inbound exploratory tunnel is used.
|
||||
At startup, when no inbound exploratory tunnel exists yet, a fake 0-hop
|
||||
inbound tunnel is used.</p>
|
||||
|
||||
<p>
|
||||
For creation of an inbound tunnel,
|
||||
when the request reaches the inbound endpoint (also known as the
|
||||
tunnel creator), there is no need to generate an explicit Tunnel Build Reply Message, and
|
||||
the router processes each of the replies, as below.</p>
|
||||
|
||||
<h3 id="tunnelCreate.replyProcessing">Tunnel Build Reply Message Processing</h3>
|
||||
|
||||
<p>To process the reply records, the creator simply has to AES decrypt
|
||||
each record individually, using the reply key and IV of each hop in
|
||||
the tunnel after the peer (in reverse order). This then exposes the
|
||||
reply specifying whether they agree to participate in the tunnel or
|
||||
why they refuse. If they all agree, the tunnel is considered
|
||||
created and may be used immediately, but if anyone refuses, the
|
||||
tunnel is discarded.</p>
|
||||
|
||||
<p>
|
||||
The agreements and rejections are noted in each peer's
|
||||
<a href="how_peerselection.html">profile</a>, to be used in future assessments
|
||||
of peer tunnel capacity.
|
||||
|
||||
|
||||
<h2 id="tunnelCreate.notes">History and Notes</h2>
|
||||
<p>
|
||||
This strategy came about during a discussion on the I2P mailing list
|
||||
between Michael Rogers, Matthew Toseland (toad), and jrandom regarding
|
||||
the predecessor attack. See: <ul>
|
||||
<li><a href="http://osdir.com/ml/network.i2p/2005-10/msg00138.html">Summary</a></li>
|
||||
<li><a href="http://osdir.com/ml/network.i2p/2005-10/msg00129.html">Reasoning</a></li>
|
||||
</ul></li>
|
||||
It was introduced in release 0.6.1.10 on 2006-02-16, which was the last time
|
||||
a non-backward-compatible change was made in I2P.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Notes:
|
||||
<ul>
|
||||
<li>This design does not prevent two hostile peers within a tunnel from
|
||||
tagging one or more request or reply records to detect that they are
|
||||
within the same tunnel, but doing so can be detected by the tunnel
|
||||
creator when reading the reply, causing the tunnel to be marked as
|
||||
invalid.</li>
|
||||
<li>This design does not include a proof of work on the asymmetrically
|
||||
encrypted section, though the 16 byte identity hash could be cut in
|
||||
half with the latter replaced by a hashcash function of up to 2^64
|
||||
cost.</li>
|
||||
<li>This design alone does not prevent two hostile peers within a tunnel from
|
||||
using timing information to determine whether they are in the same
|
||||
tunnel. The use of batched and synchronized request delivery
|
||||
could help (batching up requests and sending them off on the
|
||||
(ntp-synchronized) minute). However, doing so lets peers 'tag' the
|
||||
requests by delaying them and detecting the delay later in the
|
||||
tunnel, though perhaps dropping requests not delivered in a small
|
||||
window would work (though doing that would require a high degree of
|
||||
clock synchronization). Alternately, perhaps individual hops could
|
||||
inject a random delay before forwarding on the request?</li>
|
||||
<li>Are there any nonfatal methods of tagging the request?</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="ref">References</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="http://prisms.cs.umass.edu/brian/pubs/wright-tissec.pdf">Predecessor
|
||||
attack</a>
|
||||
<li>
|
||||
<a href="http://prisms.cs.umass.edu/brian/pubs/wright.tissec.2008.pdf">2008
|
||||
update</a>
|
||||
<li>
|
||||
<a href="http://www-users.cs.umn.edu/~hopper/hashing_it_out.pdf">Hashing it out in Public</a>
|
||||
</ul>
|
||||
|
||||
<h2 id="future">Future Work</h2>
|
||||
<ul>
|
||||
<li>
|
||||
In the current implementation, the originator leaves one record empty
|
||||
for itself. Thus a message of n records can only build a
|
||||
tunnel of n-1 hops.
|
||||
This appears to be necessary for inbound tunnels (where the next-to-last hop
|
||||
can see the hash prefix for the next hop), but not for outbound tunnels.
|
||||
This is to be researched and verified.
|
||||
If it is possible to use the remaining record without compromising anonymity,
|
||||
we should do so.
|
||||
<li>
|
||||
The usefulness of a timestamp with an hour resolution is questionable,
|
||||
and the constraint is not currently enforced.
|
||||
Therefore the request time field is unused.
|
||||
This should be researched and possibly changed.
|
||||
<li>
|
||||
Further analysis of possible tagging and timing attacks described in the above notes.
|
||||
</li><li>
|
||||
The Bloom filter rotation time should be evaluated.
|
||||
</li><li>
|
||||
Use only VTBM; do not select old peers that don't support it.
|
||||
</li></ul>
|
||||
|
||||
|
||||
{% endblock %}
|
440
i2p2www/pages/site/docs/tunnels/implementation.html
Normal file
440
i2p2www/pages/site/docs/tunnels/implementation.html
Normal file
@@ -0,0 +1,440 @@
|
||||
{% extends "global/layout.html" %}
|
||||
{% block title %}Tunnel Implementation{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
This page documents the current tunnel implementation.
|
||||
Updated October 2010 for release 0.8
|
||||
|
||||
|
||||
<h2 id="tunnel.overview">Tunnel overview</h2>
|
||||
|
||||
<p>Within I2P, messages are passed in one direction through a virtual
|
||||
tunnel of peers, using whatever means are available to pass the
|
||||
message on to the next hop. Messages arrive at the tunnel's
|
||||
</i>gateway</i>, get bundled up and/or fragmented into fixed-size tunnel messages,
|
||||
and are forwarded on to the next hop in the tunnel, which processes and verifies
|
||||
the validity of the message and sends it on to the next hop, and so on, until
|
||||
it reaches the tunnel endpoint. That <i>endpoint</i> takes the messages
|
||||
bundled up by the gateway and forwards them as instructed - either
|
||||
to another router, to another tunnel on another router, or locally.</p>
|
||||
|
||||
<p>Tunnels all work the same, but can be segmented into two different
|
||||
groups - inbound tunnels and outbound tunnels. The inbound tunnels
|
||||
have an untrusted gateway which passes messages down towards the
|
||||
tunnel creator, which serves as the tunnel endpoint. For outbound
|
||||
tunnels, the tunnel creator serves as the gateway, passing messages
|
||||
out to the remote endpoint.</p>
|
||||
|
||||
<p>The tunnel's creator selects exactly which peers will participate
|
||||
in the tunnel, and provides each with the necessary configuration
|
||||
data. They may have any number of hops.
|
||||
It is the intent to make
|
||||
it hard for either participants or third parties to determine the length of
|
||||
a tunnel, or even for colluding participants to determine whether they are a
|
||||
part of the same tunnel at all (barring the situation where colluding peers are
|
||||
next to each other in the tunnel).</p>
|
||||
|
||||
<p>In practice, a series of tunnel pools are used for different
|
||||
purposes - each local client destination has its own set of inbound
|
||||
tunnels and outbound tunnels, configured to meet its anonymity and
|
||||
performance needs. In addition, the router itself maintains a series
|
||||
of pools for participating in the network database and for managing
|
||||
the tunnels themselves.</p>
|
||||
|
||||
<p>I2P is an inherently packet switched network, even with these
|
||||
tunnels, allowing it to take advantage of multiple tunnels running
|
||||
in parallel, increasing resilience and balancing load. Outside of
|
||||
the core I2P layer, there is an optional end to end streaming library
|
||||
available for client applications, exposing TCP-esque operation,
|
||||
including message reordering, retransmission, congestion control, etc.</p>
|
||||
|
||||
<p>
|
||||
An overview of I2P tunnel terminology is
|
||||
<a href="{{ site_url('docs/how/tunnelrouting') }}">on the tunnel overview page</a>.
|
||||
</p>
|
||||
|
||||
<h2 id="tunnel.operation">Tunnel Operation (Message Processing)</h2>
|
||||
<h3>Overview</h3>
|
||||
|
||||
<p>After a tunnel is built, <a href="{{ site_url('docs/spec/i2np') }}">I2NP messages</a> are processed and passed through it.
|
||||
Tunnel operation has four distinct processes, taken on by various
|
||||
peers in the tunnel. <ol><li>First, the tunnel gateway accumulates a number
|
||||
of I2NP messages and preprocesses them into tunnel messages for
|
||||
delivery. </li><li>Next, that gateway encrypts that preprocessed data, then
|
||||
forwards it to the first hop. </li><li>That peer, and subsequent tunnel
|
||||
participants, unwrap a layer of the encryption, verifying that it isn't
|
||||
a duplicate, then forward it on to the next peer.
|
||||
</li><li>Eventually, the tunnel messages arrive at the endpoint where the I2NP messages
|
||||
originally bundled by the gateway are reassembled and forwarded on as
|
||||
requested.</li></ol></p>
|
||||
|
||||
<p>
|
||||
Intermediate tunnel participants do not know whether they are in an
|
||||
inbound or an outbound tunnel; they always "encrypt" for the next hop.
|
||||
Therefore, we take advantage of symmetric AES encryption
|
||||
to "decrypt" at the outbound tunnel gateway,
|
||||
so that the plaintext is revealed at the outbound endpoint.
|
||||
</p>
|
||||
<p>
|
||||
<center>
|
||||
<img src="{{ url_for('static', filename='images/tunnels.png') }}" alt="Inbound and outbound tunnel schematic" title="Inbound and outbound tunnel schematic" />
|
||||
</center>
|
||||
</p>
|
||||
|
||||
<table><tr>
|
||||
<th>Role</th>
|
||||
<th>Preprocessing</th>
|
||||
<th>Encryption Operation</th>
|
||||
<th>Postprocessing</th>
|
||||
</tr>
|
||||
|
||||
<tr><td>Outbound Gateway (Creator)</td>
|
||||
<td>Fragment, Batch, and Pad</td>
|
||||
<td>Iteratively encrypt (using decryption operations)</td>
|
||||
<td>Forward to next hop</td>
|
||||
</tr>
|
||||
|
||||
<tr><td>Participant</td>
|
||||
<td> </td>
|
||||
<td>Decrypt (using an encryption operation)</td>
|
||||
<td>Forward to next hop</td>
|
||||
</tr>
|
||||
|
||||
<tr><td>Outbound Endpoint</td>
|
||||
<td> </td>
|
||||
<td>Decrypt (using an encryption operation) to reveal plaintext tunnel message</td>
|
||||
<td>Reassemble Fragments, Forward as instructed to Inbound Gateway or Router</td>
|
||||
</tr>
|
||||
|
||||
<tr><td colspan="4"><hr></td></tr>
|
||||
|
||||
<tr><td>Inbound Gateway</td>
|
||||
<td>Fragment, Batch, and Pad</td>
|
||||
<td>Encrypt</td>
|
||||
<td>Forward to next hop</td>
|
||||
</tr>
|
||||
|
||||
<tr><td>Participant</td>
|
||||
<td> </td>
|
||||
<td>Encrypt</td>
|
||||
<td>Forward to next hop</td>
|
||||
</tr>
|
||||
|
||||
<tr><td>Inbound Endpoint (Creator)</td>
|
||||
<td> </td>
|
||||
<td>Iteratively decrypt to reveal plaintext tunnel message</td>
|
||||
<td>Reassemble Fragments, Receive data</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
<h3 id="tunnel.gateway">Gateway Processing</h3>
|
||||
<h4 id="tunnel.preprocessing">Message Preprocessing</h4>
|
||||
|
||||
<p>A tunnel gateway's function is to fragment and pack
|
||||
<a href="{{ site_url('docs/spec/i2np') }}">I2NP messages</a> into fixed-size
|
||||
<a href="{{ site_url('docs/spec/tunnel_message') }}">tunnel messages</a>
|
||||
and encrypt the tunnel messages.
|
||||
Tunnel messages contain the following:
|
||||
|
||||
<ul>
|
||||
<li>A 4 byte Tunnel ID</li>
|
||||
<li>A 16 byte IV (initialization vector)</li>
|
||||
<li>A checksum
|
||||
<li>Padding, if necessary</li>
|
||||
<li>One or more { delivery instruction, I2NP message fragment } pairs</li>
|
||||
</ul>
|
||||
|
||||
<p>Tunnel IDs are 4 byte numbers used at each hop - participants know what
|
||||
tunnel ID to listen for messages with and what tunnel ID they should be forwarded
|
||||
on as to the next hop, and each hop chooses the tunnel ID which they receive messages
|
||||
on. Tunnels themselves are short-lived (10 minutes).
|
||||
Even if subsequent tunnels are built using the same sequence of
|
||||
peers, each hop's tunnel ID will change.</p>
|
||||
|
||||
<p>To prevent adversaries from tagging the messages along the path by adjusting
|
||||
the message size, all tunnel messages are a fixed 1024 bytes in size. To accommodate
|
||||
larger I2NP messages as well as to support smaller ones more efficiently, the
|
||||
gateway splits up the larger I2NP messages into fragments contained within each
|
||||
tunnel message. The endpoint will attempt to rebuild the I2NP message from the
|
||||
fragments for a short period of time, but will discard them as necessary.</p>
|
||||
|
||||
<p>
|
||||
|
||||
Details are in the
|
||||
<a href="{{ site_url('docs/spec/tunnel_message') }}">tunnel message specification</a>.
|
||||
|
||||
|
||||
|
||||
<h3>Gateway Encryption</h3>
|
||||
|
||||
<p>After the preprocessing of messages into a padded payload, the gateway builds
|
||||
a random 16 byte IV value, iteratively encrypting it and the tunnel message as
|
||||
necessary, and forwards the tuple {tunnelID, IV, encrypted tunnel message} to the next hop.</p>
|
||||
|
||||
<p>How encryption at the gateway is done depends on whether the tunnel is an
|
||||
inbound or an outbound tunnel. For inbound tunnels, they simply select a random
|
||||
IV, postprocessing and updating it to generate the IV for the gateway and using
|
||||
that IV along side their own layer key to encrypt the preprocessed data. For outbound
|
||||
tunnels they must iteratively decrypt the (unencrypted) IV and preprocessed
|
||||
data with the IV and layer keys for all hops in the tunnel. The result of the outbound
|
||||
tunnel encryption is that when each peer encrypts it, the endpoint will recover
|
||||
the initial preprocessed data.</p>
|
||||
|
||||
<h3 id="tunnel.participant">Participant Processing</h3>
|
||||
|
||||
<p>When a peer receives a tunnel message, it checks that the message came from
|
||||
the same previous hop as before (initialized when the first message comes through
|
||||
the tunnel). If the previous peer is a different router, or if the message has
|
||||
already been seen, the message is dropped. The participant then encrypts the
|
||||
received IV with AES256/ECB using their IV key to determine the current IV, uses
|
||||
that IV with the participant's layer key to encrypt the data, encrypts the
|
||||
current IV with AES256/ECB using their IV key again, then forwards the tuple
|
||||
{nextTunnelId, nextIV, encryptedData} to the next hop. This double encryption
|
||||
of the IV (both before and after use) help address a certain class of
|
||||
confirmation attacks.</p>
|
||||
|
||||
<p>Duplicate message detection is handled by a decaying Bloom filter on message
|
||||
IVs. Each router maintains a single Bloom filter to contain the XOR of the IV and
|
||||
the first block of the message received for all of the tunnels it is participating
|
||||
in, modified to drop seen entries after 10-20 minutes (when the tunnels will have
|
||||
expired). The size of the bloom filter and the parameters used are sufficient to
|
||||
more than saturate the router's network connection with a negligible chance of
|
||||
false positive. The unique value fed into the Bloom filter is the XOR of the IV
|
||||
and the first block so as to prevent nonsequential colluding peers in the tunnel
|
||||
from tagging a message by resending it with the IV and first block switched.</p>
|
||||
|
||||
<h3 id="tunnel.endpoint">Endpoint Processing</h3>
|
||||
|
||||
<p>After receiving and validating a tunnel message at the last hop in the tunnel,
|
||||
how the endpoint recovers the data encoded by the gateway depends upon whether
|
||||
the tunnel is an inbound or an outbound tunnel. For outbound tunnels, the
|
||||
endpoint encrypts the message with its layer key just like any other participant,
|
||||
exposing the preprocessed data. For inbound tunnels, the endpoint is also the
|
||||
tunnel creator so they can merely iteratively decrypt the IV and message, using the
|
||||
layer and IV keys of each step in reverse order.</p>
|
||||
|
||||
<p>At this point, the tunnel endpoint has the preprocessed data sent by the gateway,
|
||||
which it may then parse out into the included I2NP messages and forwards them as
|
||||
requested in their delivery instructions.</p>
|
||||
|
||||
|
||||
<h2 id="tunnel.building">Tunnel Building</h2>
|
||||
|
||||
<p>When building a tunnel, the creator must send a request with the necessary
|
||||
configuration data to each of the hops and wait for all of them to agree before
|
||||
enabling the tunnel. The requests are encrypted so that only the peers who need
|
||||
to know a piece of information (such as the tunnel layer or IV key) has that
|
||||
data. In addition, only the tunnel creator will have access to the peer's
|
||||
reply. There are three important dimensions to keep in mind when producing
|
||||
the tunnels: what peers are used (and where), how the requests are sent (and
|
||||
replies received), and how they are maintained.</p>
|
||||
|
||||
<h3 id="tunnel.peerselection">Peer Selection</h3>
|
||||
|
||||
<p>Beyond the two types of tunnels - inbound and outbound - there are two styles
|
||||
of peer selection used for different tunnels - exploratory and client.
|
||||
Exploratory tunnels are used for both network database maintenance and tunnel
|
||||
maintenance, while client tunnels are used for end to end client messages. </p>
|
||||
|
||||
<h4 id="tunnel.selection.exploratory">Exploratory tunnel peer selection</h4>
|
||||
|
||||
<p>Exploratory tunnels are built out of a random selection of peers from a subset
|
||||
of the network. The particular subset varies on the local router and on what their
|
||||
tunnel routing needs are. In general, the exploratory tunnels are built out of
|
||||
randomly selected peers who are in the peer's "not failing but active" profile
|
||||
category. The secondary purpose of the tunnels, beyond merely tunnel routing,
|
||||
is to find underutilized high capacity peers so that they can be promoted for
|
||||
use in client tunnels.</p>
|
||||
|
||||
<p>
|
||||
Exploratory peer selection is discussed further on the
|
||||
<a href="{{ site_url('docs/how/peerselection') }}">Peer Profiling and Selection page</a>.
|
||||
|
||||
|
||||
<h4 id="tunnel.selection.client">Client tunnel peer selection</h4>
|
||||
|
||||
<p>Client tunnels are built with a more stringent set of requirements - the local
|
||||
router will select peers out of its "fast and high capacity" profile category so
|
||||
that performance and reliability will meet the needs of the client application.
|
||||
However, there are several important details beyond that basic selection that
|
||||
should be adhered to, depending upon the client's anonymity needs.</p>
|
||||
|
||||
<p>
|
||||
Client peer selection is discussed further on the
|
||||
<a href="{{ site_url('docs/how/peerselection') }}">Peer Profiling and Selection page</a>.
|
||||
|
||||
<h4 id="ordering">Peer Ordering within Tunnels</h4>
|
||||
|
||||
Peers are ordered within tunnels to
|
||||
to deal with the <a href="http://prisms.cs.umass.edu/brian/pubs/wright-tissec.pdf">predecessor
|
||||
attack</a> <a href="http://prisms.cs.umass.edu/brian/pubs/wright.tissec.2008.pdf">(2008
|
||||
update)</a>.
|
||||
<p>To frustrate the predecessor
|
||||
attack, the tunnel selection keeps the peers selected in a strict order -
|
||||
if A, B, and C are in a tunnel for a particular tunnel pool, the hop after A is always B, and the hop after
|
||||
B is always C.
|
||||
|
||||
<p>Ordering is implemented by generating a random 32-byte key for each
|
||||
tunnel pool at startup.
|
||||
Peers should not be able to guess the ordering, or an attacker could
|
||||
craft two router hashes far apart to maximize the chance of being at both
|
||||
ends of a tunnel.
|
||||
Peers are sorted by XOR distance of the
|
||||
SHA256 Hash of (the peer's hash concatenated with the random key) from the random key
|
||||
<pre>
|
||||
p = peer hash
|
||||
k = random key
|
||||
d = XOR(H(p+k), k)
|
||||
</pre>
|
||||
|
||||
<p>Because each tunnel pool uses a different random key, ordering is consistent
|
||||
within a single pool but not between different pools.
|
||||
New keys are generated at each router restart.
|
||||
|
||||
|
||||
<h3 id="tunnel.request">Request delivery</h3>
|
||||
|
||||
<p>
|
||||
A multi-hop tunnel is built using a single build message which is repeatedly
|
||||
decrypted and forwarded.
|
||||
In the terminology of
|
||||
<a href="http://www-users.cs.umn.edu/~hopper/hashing_it_out.pdf">Hashing it out in Public</a>,
|
||||
this is "non-interactive" telescopic tunnel building.
|
||||
|
||||
|
||||
<p>This tunnel request preparation, delivery, and response method is
|
||||
<a href="{{ site_url('docs/spec/tunnel_creation') }}">designed</a> to reduce the number of
|
||||
predecessors exposed, cuts the number of messages transmitted, verifies proper
|
||||
connectivity, and avoids the message counting attack of traditional telescopic
|
||||
tunnel creation.
|
||||
(This method, which sends messages to extend a tunnel through the already-established
|
||||
part of the tunnel, is termed "interactive" telescopic tunnel building in
|
||||
the "Hashing it out" paper.)
|
||||
|
||||
<p>The details of tunnel request and response messages, and their encryption,
|
||||
<a href="{{ site_url('docs/spec/tunnel_creation') }}">are specified here</a>.
|
||||
|
||||
<p>Peers may reject tunnel creation requests for a variety of reasons, though
|
||||
a series of four increasingly severe rejections are known: probabilistic rejection
|
||||
(due to approaching the router's capacity, or in response to a flood of requests),
|
||||
transient overload, bandwidth overload, and critical failure. When received,
|
||||
those four are interpreted by the tunnel creator to help adjust their profile of
|
||||
the router in question.
|
||||
<p>
|
||||
For more information on peer profiling, see the
|
||||
<a href="{{ site_url('docs/how/peerselection') }}">Peer Profiling and Selection page</a>.
|
||||
|
||||
<h3 id="tunnel.pooling">Tunnel Pools</h3>
|
||||
|
||||
<p>To allow efficient operation, the router maintains a series of tunnel pools,
|
||||
each managing a group of tunnels used for a specific purpose with their own
|
||||
configuration. When a tunnel is needed for that purpose, the router selects one
|
||||
out of the appropriate pool at random. Overall, there are two exploratory tunnel
|
||||
pools - one inbound and one outbound - each using the router's default configuration.
|
||||
In addition, there is a pair of pools for each local destination -
|
||||
one inbound and one outbound tunnel pool. Those pools use the configuration specified
|
||||
when the local destination connects to the router via <a href="{{ site_url('docs/spec/i2cp') }}">I2CP</a>, or the router's defaults if
|
||||
not specified.</p>
|
||||
|
||||
<p>Each pool has within its configuration a few key settings, defining how many
|
||||
tunnels to keep active, how many backup tunnels to maintain in case of failure,
|
||||
how long the tunnels should be, whether those
|
||||
lengths should be randomized, as
|
||||
well as any of the other settings allowed when configuring individual tunnels.
|
||||
Configuration options are specified on the <a href="i2cp.html">I2CP page</a>.
|
||||
|
||||
<h3 id="length">Tunnel Lengths and Defaults</h3>
|
||||
|
||||
<a href="{{ site_url('docs/how/tunnelrouting') }}#length">On the tunnel overview page</a>.
|
||||
|
||||
<h3 id="strategy">Anticipatory Build Strategy and Priority</h3>
|
||||
|
||||
<p>
|
||||
Tunnel building is expensive, and tunnels expire a fixed time after they are built.
|
||||
However, when a pool that runs out of tunnels, the Destination is essentially dead.
|
||||
In addition, tunnel build success rate may vary greatly with both local and global
|
||||
network conditions.
|
||||
Therefore, it is important to maintain an anticipatory, adaptive build strategy
|
||||
to ensure that new tunnels are successfully built before they are needed,
|
||||
without building an excess of tunnels, building them too soon,
|
||||
or consuming too much CPU or bandwidth creating and sending the encrypted build messages.
|
||||
</p>
|
||||
<p>
|
||||
For each tuple {exploratory/client, in/out, length, length variance}
|
||||
the router maintains statistics on the time required for a successful
|
||||
tunnel build.
|
||||
Using these statistics, it calculates how long before a tunnel's expiration
|
||||
it should start attempting to build a replacement.
|
||||
As the expiration time approaches without a successful replacement,
|
||||
it starts multiple build attempts in parallel, and then
|
||||
will increase the number of parallel attempts if necessary.
|
||||
</p>
|
||||
<p>
|
||||
To cap bandwidth and CPU usage,
|
||||
the router also limits the maximum number of build attempts outstanding
|
||||
across all pools.
|
||||
Critical builds (those for exploratory tunnels, and for pools that have
|
||||
run out of tunnels) are prioritized.
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="tunnel.throttling">Tunnel Message Throttling</h2>
|
||||
|
||||
<p>Even though the tunnels within I2P bear a resemblance to a circuit switched
|
||||
network, everything within I2P is strictly message based - tunnels are merely
|
||||
accounting tricks to help organize the delivery of messages. No assumptions are
|
||||
made regarding reliability or ordering of messages, and retransmissions are left
|
||||
to higher levels (e.g. I2P's client layer streaming library). This allows I2P
|
||||
to take advantage of throttling techniques available to both packet switched and
|
||||
circuit switched networks. For instance, each router may keep track of the
|
||||
moving average of how much data each tunnel is using, combine that with all of
|
||||
the averages used by other tunnels the router is participating in, and be able
|
||||
to accept or reject additional tunnel participation requests based on its
|
||||
capacity and utilization. On the other hand, each router can simply drop
|
||||
messages that are beyond its capacity, exploiting the research used on the
|
||||
normal Internet.</p>
|
||||
|
||||
<p>
|
||||
In the current implementation, routers implement a
|
||||
weighted random early discard (WRED) strategy.
|
||||
For all participating routers (internal participant, inbound gateway, and outbound endpoint),
|
||||
the router will start randomly dropping a portion of messages as the
|
||||
bandwidth limits are approached.
|
||||
As traffic gets closer to, or exceeds, the limits, more messages are dropped.
|
||||
For an internal participant, all messages are fragmented and padded and therefore are the same size.
|
||||
At the inbound gateway and outbound endpoint, however, the dropping decision is made
|
||||
on the full (coalesced) message, and the message size is taken into account.
|
||||
Larger messages are more likely to be dropped.
|
||||
Also, messages are more likely to be dropped at the outbound endpoint than the inbound gateway,
|
||||
as those messages are not as "far along" in their journey and thus the network cost of
|
||||
dropping those messages is lower.
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="future">Future Work</h3>
|
||||
<h3 id="tunnel.mixing">Mixing/batching</h3>
|
||||
|
||||
<p>What strategies could be used at the gateway and at each hop for delaying,
|
||||
reordering, rerouting, or padding messages? To what extent should this be done
|
||||
automatically, how much should be configured as a per tunnel or per hop setting,
|
||||
and how should the tunnel's creator (and in turn, user) control this operation?
|
||||
All of this is left as unknown, to be worked out for a distant future release.
|
||||
|
||||
|
||||
<h3>Padding</h3>
|
||||
<p>The padding strategies can be used on a variety of levels, addressing the
|
||||
exposure of message size information to different adversaries.
|
||||
The current fixed tunnel message size is 1024 bytes. Within this however, the fragmented
|
||||
messages themselves are not padded by the tunnel at all, though for end to end
|
||||
messages, they may be padded as part of the garlic wrapping.</p>
|
||||
|
||||
<h3>WRED</h3>
|
||||
<p>
|
||||
WRED strategies have a significant impact on end-to-end performance,
|
||||
and prevention of network congestion collapse.
|
||||
The current WRED strategy should be carefully evaluated and improved.
|
||||
</p>
|
||||
|
||||
{% endblock %}
|
534
i2p2www/pages/site/docs/tunnels/old.html
Normal file
534
i2p2www/pages/site/docs/tunnels/old.html
Normal file
@@ -0,0 +1,534 @@
|
||||
{% extends "global/layout.html" %}
|
||||
{% block title %}Old Tunnel Implementation{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<b>Note: Obsolete - NOT used! Replaced in 0.6.1.10 - see <a href="tunnel-alt.html">tunnel-alt.html</a> for the current implementation</b>
|
||||
<br>
|
||||
<pre>
|
||||
1) <a href="#tunnel.overview">Tunnel overview</a>
|
||||
2) <a href="#tunnel.operation">Tunnel operation</a>
|
||||
2.1) <a href="#tunnel.preprocessing">Message preprocessing</a>
|
||||
2.2) <a href="#tunnel.gateway">Gateway processing</a>
|
||||
2.3) <a href="#tunnel.participant">Participant processing</a>
|
||||
2.4) <a href="#tunnel.endpoint">Endpoint processing</a>
|
||||
2.5) <a href="#tunnel.padding">Padding</a>
|
||||
2.6) <a href="#tunnel.fragmentation">Tunnel fragmentation</a>
|
||||
2.7) <a href="#tunnel.alternatives">Alternatives</a>
|
||||
2.7.1) <a href="#tunnel.nochecksum">Don't use a checksum block</a>
|
||||
2.7.2) <a href="#tunnel.reroute">Adjust tunnel processing midstream</a>
|
||||
2.7.3) <a href="#tunnel.bidirectional">Use bidirectional tunnels</a>
|
||||
2.7.4) <a href="#tunnel.smallerhashes">Use smaller hashes</a>
|
||||
3) <a href="#tunnel.building">Tunnel building</a>
|
||||
3.1) <a href="#tunnel.peerselection">Peer selection</a>
|
||||
3.1.1) <a href="#tunnel.selection.exploratory">Exploratory tunnel peer selection</a>
|
||||
3.1.2) <a href="#tunnel.selection.client">Client tunnel peer selection</a>
|
||||
3.2) <a href="#tunnel.request">Request delivery</a>
|
||||
3.3) <a href="#tunnel.pooling">Pooling</a>
|
||||
3.4) <a href="#tunnel.building.alternatives">Alternatives</a>
|
||||
3.4.1) <a href="#tunnel.building.telescoping">Telescopic building</a>
|
||||
3.4.2) <a href="#tunnel.building.nonexploratory">Non-exploratory tunnels for management</a>
|
||||
4) <a href="#tunnel.throttling">Tunnel throttling</a>
|
||||
5) <a href="#tunnel.mixing">Mixing/batching</a>
|
||||
</pre>
|
||||
|
||||
<h2>1) <a name="tunnel.overview">Tunnel overview</a></h2>
|
||||
|
||||
<p>Within I2P, messages are passed in one direction through a virtual
|
||||
tunnel of peers, using whatever means are available to pass the
|
||||
message on to the next hop. Messages arrive at the tunnel's
|
||||
gateway, get bundled up for the path, and are forwarded on to the
|
||||
next hop in the tunnel, which processes and verifies the validity
|
||||
of the message and sends it on to the next hop, and so on, until
|
||||
it reaches the tunnel endpoint. That endpoint takes the messages
|
||||
bundled up by the gateway and forwards them as instructed - either
|
||||
to another router, to another tunnel on another router, or locally.</p>
|
||||
|
||||
<p>Tunnels all work the same, but can be segmented into two different
|
||||
groups - inbound tunnels and outbound tunnels. The inbound tunnels
|
||||
have an untrusted gateway which passes messages down towards the
|
||||
tunnel creator, which serves as the tunnel endpoint. For outbound
|
||||
tunnels, the tunnel creator serves as the gateway, passing messages
|
||||
out to the remote endpoint.</p>
|
||||
|
||||
<p>The tunnel's creator selects exactly which peers will participate
|
||||
in the tunnel, and provides each with the necessary configuration
|
||||
data. They may vary in length from 0 hops (where the gateway
|
||||
is also the endpoint) to 7 hops (where there are 6 peers after
|
||||
the gateway and before the endpoint). It is the intent to make
|
||||
it hard for either participants or third parties to determine
|
||||
the length of a tunnel, or even for colluding participants to
|
||||
determine whether they are a part of the same tunnel at all
|
||||
(barring the situation where colluding peers are next to each other
|
||||
in the tunnel). Messages that have been corrupted are also dropped
|
||||
as soon as possible, reducing network load.</p>
|
||||
|
||||
<p>Beyond their length, there are additional configurable parameters
|
||||
for each tunnel that can be used, such as a throttle on the size or
|
||||
frequency of messages delivered, how padding should be used, how
|
||||
long a tunnel should be in operation, whether to inject chaff
|
||||
messages, whether to use fragmentation, and what, if any, batching
|
||||
strategies should be employed.</p>
|
||||
|
||||
<p>In practice, a series of tunnel pools are used for different
|
||||
purposes - each local client destination has its own set of inbound
|
||||
tunnels and outbound tunnels, configured to meet its anonymity and
|
||||
performance needs. In addition, the router itself maintains a series
|
||||
of pools for participating in the network database and for managing
|
||||
the tunnels themselves.</p>
|
||||
|
||||
<p>I2P is an inherently packet switched network, even with these
|
||||
tunnels, allowing it to take advantage of multiple tunnels running
|
||||
in parallel, increasing resilience and balancing load. Outside of
|
||||
the core I2P layer, there is an optional end to end streaming library
|
||||
available for client applications, exposing TCP-esque operation,
|
||||
including message reordering, retransmission, congestion control, etc.</p>
|
||||
|
||||
<h2>2) <a name="tunnel.operation">Tunnel operation</a></h2>
|
||||
|
||||
<p>Tunnel operation has four distinct processes, taken on by various
|
||||
peers in the tunnel. First, the tunnel gateway accumulates a number
|
||||
of tunnel messages and preprocesses them into something for tunnel
|
||||
delivery. Next, that gateway encrypts that preprocessed data, then
|
||||
forwards it to the first hop. That peer, and subsequent tunnel
|
||||
participants, unwrap a layer of the encryption, verifying the
|
||||
integrity of the message, then forward it on to the next peer.
|
||||
Eventually, the message arrives at the endpoint where the messages
|
||||
bundled by the gateway are split out again and forwarded on as
|
||||
requested.</p>
|
||||
|
||||
<p>Tunnel IDs are 4 byte numbers used at each hop - participants know what
|
||||
tunnel ID to listen for messages with and what tunnel ID they should be forwarded
|
||||
on as to the next hop. Tunnels themselves are short lived (10 minutes at the
|
||||
moment), but depending upon the tunnel's purpose, and though subsequent tunnels
|
||||
may be built using the same sequence of peers, each hop's tunnel ID will change.</p>
|
||||
|
||||
<h3>2.1) <a name="tunnel.preprocessing">Message preprocessing</a></h3>
|
||||
|
||||
<p>When the gateway wants to deliver data through the tunnel, it first
|
||||
gathers zero or more I2NP messages (no more than 32KB worth),
|
||||
selects how much padding will be used, and decides how each I2NP
|
||||
message should be handled by the tunnel endpoint, encoding that
|
||||
data into the raw tunnel payload:</p>
|
||||
<ul>
|
||||
<li>2 byte unsigned integer specifying the # of padding bytes</li>
|
||||
<li>that many random bytes</li>
|
||||
<li>a series of zero or more { instructions, message } pairs</li>
|
||||
</ul>
|
||||
|
||||
<p>The instructions are encoded as follows:</p>
|
||||
<ul>
|
||||
<li>1 byte value:<pre>
|
||||
bits 0-1: delivery type
|
||||
(0x0 = LOCAL, 0x01 = TUNNEL, 0x02 = ROUTER)
|
||||
bit 2: delay included? (1 = true, 0 = false)
|
||||
bit 3: fragmented? (1 = true, 0 = false)
|
||||
bit 4: extended options? (1 = true, 0 = false)
|
||||
bits 5-7: reserved</pre></li>
|
||||
<li>if the delivery type was TUNNEL, a 4 byte tunnel ID</li>
|
||||
<li>if the delivery type was TUNNEL or ROUTER, a 32 byte router hash</li>
|
||||
<li>if the delay included flag is true, a 1 byte value:<pre>
|
||||
bit 0: type (0 = strict, 1 = randomized)
|
||||
bits 1-7: delay exponent (2^value minutes)</pre></li>
|
||||
<li>if the fragmented flag is true, a 4 byte message ID, and a 1 byte value:<pre>
|
||||
bits 0-6: fragment number
|
||||
bit 7: is last? (1 = true, 0 = false)</pre></li>
|
||||
<li>if the extended options flag is true:<pre>
|
||||
= a 1 byte option size (in bytes)
|
||||
= that many bytes</pre></li>
|
||||
<li>2 byte size of the I2NP message</li>
|
||||
</ul>
|
||||
|
||||
<p>The I2NP message is encoded in its standard form, and the
|
||||
preprocessed payload must be padded to a multiple of 16 bytes.</p>
|
||||
|
||||
<h3>2.2) <a name="tunnel.gateway">Gateway processing</a></h3>
|
||||
|
||||
<p>After the preprocessing of messages into a padded payload, the gateway
|
||||
encrypts the payload with the eight keys, building a checksum block so
|
||||
that each peer can verify the integrity of the payload at any time, as
|
||||
well as an end to end verification block for the tunnel endpoint to
|
||||
verify the integrity of the checksum block. The specific details follow.</p>
|
||||
|
||||
<p>The encryption used is such that decryption
|
||||
merely requires running over the data with AES in CBC mode, calculating the
|
||||
SHA256 of a certain fixed portion of the message (bytes 16 through $size-144),
|
||||
and searching for the first 16 bytes of that hash in the checksum block. There is a fixed number
|
||||
of hops defined (8 peers) so that we can verify the message
|
||||
without either leaking the position in the tunnel or having the message
|
||||
continually "shrink" as layers are peeled off. For tunnels shorter than 8
|
||||
hops, the tunnel creator will take the place of the excess hops, decrypting
|
||||
with their keys (for outbound tunnels, this is done at the beginning, and for
|
||||
inbound tunnels, the end).</p>
|
||||
|
||||
<p>The hard part in the encryption is building that entangled checksum block,
|
||||
which requires essentially finding out what the hash of the payload will look
|
||||
like at each step, randomly ordering those hashes, then building a matrix of
|
||||
what each of those randomly ordered hashes will look like at each step. The
|
||||
gateway itself must pretend that it is one of the peers within the checksum
|
||||
block so that the first hop cannot tell that the previous hop was the gateway.
|
||||
To visualize this a bit:</p>
|
||||
|
||||
<table border="1">
|
||||
<tr><td colspan="2"></td>
|
||||
<td><b>IV</b></td><td><b>Payload</b></td>
|
||||
<td><b>eH[0]</b></td><td><b>eH[1]</b></td>
|
||||
<td><b>eH[2]</b></td><td><b>eH[3]</b></td>
|
||||
<td><b>eH[4]</b></td><td><b>eH[5]</b></td>
|
||||
<td><b>eH[6]</b></td><td><b>eH[7]</b></td>
|
||||
<td><b>V</b></td>
|
||||
</tr>
|
||||
<tr><td rowspan="2"><b>peer0</b><br /><font size="-2">key=K[0]</font></td><td><b>recv</b></td>
|
||||
<td colspan="11"><hr /></td>
|
||||
</tr>
|
||||
<tr><td><b>send</b></td>
|
||||
<td rowspan="2">IV[0]</td><td rowspan="2">P[0]</td>
|
||||
<td rowspan="2"></td><td rowspan="2"></td><td rowspan="2"></td><td rowspan="2">H(P[0])</td>
|
||||
<td rowspan="2"></td><td rowspan="2"></td><td rowspan="2"></td><td rowspan="2"></td>
|
||||
<td rowspan="2">V[0]</td>
|
||||
</tr>
|
||||
<tr><td rowspan="2"><b>peer1</b><br /><font size="-2">key=K[1]</font></td><td><b>recv</b></td>
|
||||
</tr>
|
||||
<tr><td><b>send</b></td>
|
||||
<td rowspan="2">IV[1]</td><td rowspan="2">P[1]</td>
|
||||
<td rowspan="2"></td><td rowspan="2"></td><td rowspan="2"></td><td rowspan="2"></td>
|
||||
<td rowspan="2"></td><td rowspan="2"></td><td rowspan="2">H(P[1])</td><td rowspan="2"></td>
|
||||
<td rowspan="2">V[1]</td>
|
||||
</tr>
|
||||
<tr><td rowspan="2"><b>peer2</b><br /><font size="-2">key=K[2]</font></td><td><b>recv</b></td>
|
||||
</tr>
|
||||
<tr><td><b>send</b></td>
|
||||
<td rowspan="2">IV[2]</td><td rowspan="2">P[2]</td>
|
||||
<td rowspan="2"></td><td rowspan="2"></td><td rowspan="2"></td><td rowspan="2"></td>
|
||||
<td rowspan="2"></td><td rowspan="2"></td><td rowspan="2"></td><td rowspan="2">H(P[2])</td>
|
||||
<td rowspan="2">V[2]</td>
|
||||
</tr>
|
||||
<tr><td rowspan="2"><b>peer3</b><br /><font size="-2">key=K[3]</font></td><td><b>recv</b></td>
|
||||
</tr>
|
||||
<tr><td><b>send</b></td>
|
||||
<td rowspan="2">IV[3]</td><td rowspan="2">P[3]</td>
|
||||
<td rowspan="2">H(P[3])</td><td rowspan="2"></td><td rowspan="2"></td><td rowspan="2"></td>
|
||||
<td rowspan="2"></td><td rowspan="2"></td><td rowspan="2"></td><td rowspan="2"></td>
|
||||
<td rowspan="2">V[3]</td>
|
||||
</tr>
|
||||
<tr><td rowspan="2"><b>peer4</b><br /><font size="-2">key=K[4]</font></td><td><b>recv</b></td>
|
||||
</tr>
|
||||
<tr><td><b>send</b></td>
|
||||
<td rowspan="2">IV[4]</td><td rowspan="2">P[4]</td>
|
||||
<td rowspan="2"></td><td rowspan="2"></td><td rowspan="2">H(P[4])</td><td rowspan="2"></td>
|
||||
<td rowspan="2"></td><td rowspan="2"></td><td rowspan="2"></td><td rowspan="2"></td>
|
||||
<td rowspan="2">V[4]</td>
|
||||
</tr>
|
||||
<tr><td rowspan="2"><b>peer5</b><br /><font size="-2">key=K[5]</font></td><td><b>recv</b></td>
|
||||
</tr>
|
||||
<tr><td><b>send</b></td>
|
||||
<td rowspan="2">IV[5]</td><td rowspan="2">P[5]</td>
|
||||
<td rowspan="2"></td><td rowspan="2">H(P[5])</td><td rowspan="2"></td><td rowspan="2"></td>
|
||||
<td rowspan="2"></td><td rowspan="2"></td><td rowspan="2"></td><td rowspan="2"></td>
|
||||
<td rowspan="2">V[5]</td>
|
||||
</tr>
|
||||
<tr><td rowspan="2"><b>peer6</b><br /><font size="-2">key=K[6]</font></td><td><b>recv</b></td>
|
||||
</tr>
|
||||
<tr><td><b>send</b></td>
|
||||
<td rowspan="2">IV[6]</td><td rowspan="2">P[6]</td>
|
||||
<td rowspan="2"></td><td rowspan="2"></td><td rowspan="2"></td><td rowspan="2"></td>
|
||||
<td rowspan="2"></td><td rowspan="2">H(P[6])</td><td rowspan="2"></td><td rowspan="2"></td>
|
||||
<td rowspan="2">V[6]</td>
|
||||
</tr>
|
||||
<tr><td rowspan="2"><b>peer7</b><br /><font size="-2">key=K[7]</font></td><td><b>recv</b></td>
|
||||
</tr>
|
||||
<tr><td><b>send</b></td>
|
||||
<td>IV[7]</td><td>P[7]</td>
|
||||
<td></td><td></td><td></td><td></td><td>H(P[7])</td><td></td><td></td><td></td>
|
||||
<td>V[7]</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>In the above, P[7] is the same as the original data being passed through the
|
||||
tunnel (the preprocessed messages), and V[7] is the first 16 bytes of the SHA256 of eH[0-7] as seen on
|
||||
peer7 after decryption. For
|
||||
cells in the matrix "higher up" than the hash, their value is derived by encrypting
|
||||
the cell below it with the key for the peer below it, using the end of the column
|
||||
to the left of it as the IV. For cells in the matrix "lower down" than the hash,
|
||||
they're equal to the cell above them, decrypted by the current peer's key, using
|
||||
the end of the previous encrypted block on that row.</p>
|
||||
|
||||
<p>With this randomized matrix of checksum blocks, each peer will be able to find
|
||||
the hash of the payload, or if it is not there, know that the message is corrupt.
|
||||
The entanglement by using CBC mode increases the difficulty in tagging the
|
||||
checksum blocks themselves, but it is still possible for that tagging to go
|
||||
briefly undetected if the columns after the tagged data have already been used
|
||||
to check the payload at a peer. In any case, the tunnel endpoint (peer 7) knows
|
||||
for certain whether any of the checksum blocks have been tagged, as that would
|
||||
corrupt the verification block (V[7]).</p>
|
||||
|
||||
<p>The IV[0] is a random 16 byte value, and IV[i] is the first 16 bytes of
|
||||
H(D(IV[i-1], K[i-1]) xor IV_WHITENER). We don't use the same IV along the path, as that would
|
||||
allow trivial collusion, and we use the hash of the decrypted value to propagate
|
||||
the IV so as to hamper key leakage. IV_WHITENER is a fixed 16 byte value.</p>
|
||||
|
||||
<p>When the gateway wants to send the message, they export the right row for the
|
||||
peer who is the first hop (usually the peer1.recv row) and forward that entirely.</p>
|
||||
|
||||
<h3>2.3) <a name="tunnel.participant">Participant processing</a></h3>
|
||||
|
||||
<p>When a participant in a tunnel receives a message, they decrypt a layer with their
|
||||
tunnel key using AES256 in CBC mode with the first 16 bytes as the IV. They then
|
||||
calculate the hash of what they see as the payload (bytes 16 through $size-144) and
|
||||
search for that first 16 bytes of that hash within the decrypted checksum block. If no match is found, the
|
||||
message is discarded. Otherwise, the IV is updated by decrypting it, XORing that value
|
||||
with the IV_WHITENER, and replacing it with the first 16 bytes of its hash. The
|
||||
resulting message is then forwarded on to the next peer for processing.</p>
|
||||
|
||||
<p>To prevent replay attacks at the tunnel level, each participant keeps track of
|
||||
the IVs received during the tunnel's lifetime, rejecting duplicates. The memory
|
||||
usage required should be minor, as each tunnel has only a very short lifespan (10m
|
||||
at the moment). A constant 100KBps through a tunnel with full 32KB messages would
|
||||
give 1875 messages, requiring less than 30KB of memory. Gateways and endpoints
|
||||
handle replay by tracking the message IDs and expirations on the I2NP messages
|
||||
contained in the tunnel.</p>
|
||||
|
||||
<h3>2.4) <a name="tunnel.endpoint">Endpoint processing</a></h3>
|
||||
|
||||
<p>When a message reaches the tunnel endpoint, they decrypts and verifies it like
|
||||
a normal participant. If the checksum block has a valid match, the endpoint then
|
||||
computes the hash of the checksum block itself (as seen after decryption) and compares
|
||||
that to the decrypted verification hash (the last 16 bytes). If that verification
|
||||
hash does not match, the endpoint takes note of the tagging attempt by one of the
|
||||
tunnel participants and perhaps discards the message.</p>
|
||||
|
||||
<p>At this point, the tunnel endpoint has the preprocessed data sent by the gateway,
|
||||
which it may then parse out into the included I2NP messages and forwards them as
|
||||
requested in their delivery instructions.</p>
|
||||
|
||||
<h3>2.5) <a name="tunnel.padding">Padding</a></h3>
|
||||
|
||||
<p>Several tunnel padding strategies are possible, each with their own merits:</p>
|
||||
|
||||
<ul>
|
||||
<li>No padding</li>
|
||||
<li>Padding to a random size</li>
|
||||
<li>Padding to a fixed size</li>
|
||||
<li>Padding to the closest KB</li>
|
||||
<li>Padding to the closest exponential size (2^n bytes)</li>
|
||||
</ul>
|
||||
|
||||
<p><i>Which to use? no padding is most efficient, random padding is what
|
||||
we have now, fixed size would either be an extreme waste or force us to
|
||||
implement fragmentation. Padding to the closest exponential size (ala Freenet)
|
||||
seems promising. Perhaps we should gather some stats on the net as to what size
|
||||
messages are, then see what costs and benefits would arise from different
|
||||
strategies?</i></p>
|
||||
|
||||
<h3>2.6) <a name="tunnel.fragmentation">Tunnel fragmentation</a></h3>
|
||||
|
||||
<p>For various padding and mixing schemes, it may be useful from an anonymity
|
||||
perspective to fragment a single I2NP message into multiple parts, each delivered
|
||||
separately through different tunnel messages. The endpoint may or may not
|
||||
support that fragmentation (discarding or hanging on to fragments as needed),
|
||||
and handling fragmentation will not immediately be implemented.</p>
|
||||
|
||||
<h3>2.7) <a name="tunnel.alternatives">Alternatives</a></h3>
|
||||
|
||||
<h4>2.7.1) <a name="tunnel.nochecksum">Don't use a checksum block</a></h4>
|
||||
|
||||
<p>One alternative to the above process is to remove the checksum block
|
||||
completely and replace the verification hash with a plain hash of the payload.
|
||||
This would simplify processing at the tunnel gateway and save 144 bytes of
|
||||
bandwidth at each hop. On the other hand, attackers within the tunnel could
|
||||
trivially adjust the message size to one which is easily traceable by
|
||||
colluding external observers in addition to later tunnel participants. The
|
||||
corruption would also incur the waste of the entire bandwidth necessary to
|
||||
pass on the message. Without the per-hop validation, it would also be possible
|
||||
to consume excess network resources by building extremely long tunnels, or by
|
||||
building loops into the tunnel.</p>
|
||||
|
||||
<h4>2.7.2) <a name="tunnel.reroute">Adjust tunnel processing midstream</a></h4>
|
||||
|
||||
<p>While the simple tunnel routing algorithm should be sufficient for most cases,
|
||||
there are three alternatives that can be explored:</p>
|
||||
<ul>
|
||||
<li>Delay a message within a tunnel at an arbitrary hop for either a specified
|
||||
amount of time or a randomized period. This could be achieved by replacing the
|
||||
hash in the checksum block with e.g. the first 8 bytes of the hash, followed by
|
||||
some delay instructions. Alternately, the instructions could tell the
|
||||
participant to actually interpret the raw payload as it is, and either discard
|
||||
the message or continue to forward it down the path (where it would be
|
||||
interpreted by the endpoint as a chaff message). The later part of this would
|
||||
require the gateway to adjust its encryption algorithm to produce the cleartext
|
||||
payload on a different hop, but it shouldn't be much trouble.</li>
|
||||
<li>Allow routers participating in a tunnel to remix the message before
|
||||
forwarding it on - bouncing it through one of that peer's own outbound tunnels,
|
||||
bearing instructions for delivery to the next hop. This could be used in either
|
||||
a controlled manner (with en-route instructions like the delays above) or
|
||||
probabilistically.</li>
|
||||
<li>Implement code for the tunnel creator to redefine a peer's "next hop" in
|
||||
the tunnel, allowing further dynamic redirection.</li>
|
||||
</ul>
|
||||
|
||||
<h4>2.7.3) <a name="tunnel.bidirectional">Use bidirectional tunnels</a></h4>
|
||||
|
||||
<p>The current strategy of using two separate tunnels for inbound and outbound
|
||||
communication is not the only technique available, and it does have anonymity
|
||||
implications. On the positive side, by using separate tunnels it lessens the
|
||||
traffic data exposed for analysis to participants in a tunnel - for instance,
|
||||
peers in an outbound tunnel from a web browser would only see the traffic of
|
||||
an HTTP GET, while the peers in an inbound tunnel would see the payload
|
||||
delivered along the tunnel. With bidirectional tunnels, all participants would
|
||||
have access to the fact that e.g. 1KB was sent in one direction, then 100KB
|
||||
in the other. On the negative side, using unidirectional tunnels means that
|
||||
there are two sets of peers which need to be profiled and accounted for, and
|
||||
additional care must be taken to address the increased speed of predecessor
|
||||
attacks. The tunnel pooling and building process outlined below should
|
||||
minimize the worries of the predecessor attack, though if it were desired,
|
||||
it wouldn't be much trouble to build both the inbound and outbound tunnels
|
||||
along the same peers.</p>
|
||||
|
||||
<h4>2.7.4) <a name="tunnel.smallerhashes">Use smaller blocksize</a></h4>
|
||||
|
||||
<p>At the moment, our use of AES limits our block size to 16 bytes, which
|
||||
in turn provides the minimum size for each of the checksum block columns.
|
||||
If another algorithm was used with a smaller block size, or could otherwise
|
||||
allow the safe building of the checksum block with smaller portions of the
|
||||
hash, it might be worth exploring. The 16 bytes used now at each hop should
|
||||
be more than sufficient.</p>
|
||||
|
||||
<h2>3) <a name="tunnel.building">Tunnel building</a></h2>
|
||||
|
||||
<p>When building a tunnel, the creator must send a request with the necessary
|
||||
configuration data to each of the hops, then wait for the potential participant
|
||||
to reply stating that they either agree or do not agree. These tunnel request
|
||||
messages and their replies are garlic wrapped so that only the router who knows
|
||||
the key can decrypt it, and the path taken in both directions is tunnel routed
|
||||
as well. There are three important dimensions to keep in mind when producing
|
||||
the tunnels: what peers are used (and where), how the requests are sent (and
|
||||
replies received), and how they are maintained.</p>
|
||||
|
||||
<h3>3.1) <a name="tunnel.peerselection">Peer selection</a></h3>
|
||||
|
||||
<p>Beyond the two types of tunnels - inbound and outbound - there are two styles
|
||||
of peer selection used for different tunnels - exploratory and client.
|
||||
Exploratory tunnels are used for both network database maintenance and tunnel
|
||||
maintenance, while client tunnels are used for end to end client messages. </p>
|
||||
|
||||
<h4>3.1.1) <a name="tunnel.selection.exploratory">Exploratory tunnel peer selection</a></h4>
|
||||
|
||||
<p>Exploratory tunnels are built out of a random selection of peers from a subset
|
||||
of the network. The particular subset varies on the local router and on what their
|
||||
tunnel routing needs are. In general, the exploratory tunnels are built out of
|
||||
randomly selected peers who are in the peer's "not failing but active" profile
|
||||
category. The secondary purpose of the tunnels, beyond merely tunnel routing,
|
||||
is to find underutilized high capacity peers so that they can be promoted for
|
||||
use in client tunnels.</p>
|
||||
|
||||
<h4>3.1.2) <a name="tunnel.selection.client">Client tunnel peer selection</a></h4>
|
||||
|
||||
<p>Client tunnels are built with a more stringent set of requirements - the local
|
||||
router will select peers out of its "fast and high capacity" profile category so
|
||||
that performance and reliability will meet the needs of the client application.
|
||||
However, there are several important details beyond that basic selection that
|
||||
should be adhered to, depending upon the client's anonymity needs.</p>
|
||||
|
||||
<p>For some clients who are worried about adversaries mounting a predecessor
|
||||
attack, the tunnel selection can keep the peers selected in a strict order -
|
||||
if A, B, and C are in a tunnel, the hop after A is always B, and the hop after
|
||||
B is always C. A less strict ordering is also possible, assuring that while
|
||||
the hop after A may be B, B may never be before A. Other configuration options
|
||||
include the ability for just the inbound tunnel gateways and outbound tunnel
|
||||
endpoints to be fixed, or rotated on an MTBF rate.</p>
|
||||
|
||||
<h3>3.2) <a name="tunnel.request">Request delivery</a></h3>
|
||||
|
||||
<p>As mentioned above, once the tunnel creator knows what peers should go into
|
||||
a tunnel and in what order, the creator builds a series of tunnel request
|
||||
messages, each containing the necessary information for that peer. For instance,
|
||||
participating tunnels will be given the 4 byte tunnel ID on which they are to
|
||||
receive messages, the 4 byte tunnel ID on which they are to send out the messages,
|
||||
the 32 byte hash of the next hop's identity, and the 32 byte layer key used to
|
||||
remove a layer from the tunnel. Of course, outbound tunnel endpoints are not
|
||||
given any "next hop" or "next tunnel ID" information. Inbound tunnel gateways
|
||||
are however given the 8 layer keys in the order they should be encrypted (as
|
||||
described above). To allow replies, the request contains a random session tag
|
||||
and a random session key with which the peer may garlic encrypt their decision,
|
||||
as well as the tunnel to which that garlic should be sent. In addition to the
|
||||
above information, various client specific options may be included, such as
|
||||
what throttling to place on the tunnel, what padding or batch strategies to use,
|
||||
etc.</p>
|
||||
|
||||
<p>After building all of the request messages, they are garlic wrapped for the
|
||||
target router and sent out an exploratory tunnel. Upon receipt, that peer
|
||||
determines whether they can or will participate, creating a reply message and
|
||||
both garlic wrapping and tunnel routing the response with the supplied
|
||||
information. Upon receipt of the reply at the tunnel creator, the tunnel is
|
||||
considered valid on that hop (if accepted). Once all peers have accepted, the
|
||||
tunnel is active.</p>
|
||||
|
||||
<h3>3.3) <a name="tunnel.pooling">Pooling</a></h3>
|
||||
|
||||
<p>To allow efficient operation, the router maintains a series of tunnel pools,
|
||||
each managing a group of tunnels used for a specific purpose with their own
|
||||
configuration. When a tunnel is needed for that purpose, the router selects one
|
||||
out of the appropriate pool at random. Overall, there are two exploratory tunnel
|
||||
pools - one inbound and one outbound - each using the router's exploration
|
||||
defaults. In addition, there is a pair of pools for each local destination -
|
||||
one inbound and one outbound tunnel. Those pools use the configuration specified
|
||||
when the local destination connected to the router, or the router's defaults if
|
||||
not specified.</p>
|
||||
|
||||
<p>Each pool has within its configuration a few key settings, defining how many
|
||||
tunnels to keep active, how many backup tunnels to maintain in case of failure,
|
||||
how frequently to test the tunnels, how long the tunnels should be, whether those
|
||||
lengths should be randomized, how often replacement tunnels should be built, as
|
||||
well as any of the other settings allowed when configuring individual tunnels.</p>
|
||||
|
||||
<h3>3.4) <a name="tunnel.building.alternatives">Alternatives</a></h3>
|
||||
|
||||
<h4>3.4.1) <a name="tunnel.building.telescoping">Telescopic building</a></h4>
|
||||
|
||||
<p>One question that may arise regarding the use of the exploratory tunnels for
|
||||
sending and receiving tunnel creation messages is how that impacts the tunnel's
|
||||
vulnerability to predecessor attacks. While the endpoints and gateways of
|
||||
those tunnels will be randomly distributed across the network (perhaps even
|
||||
including the tunnel creator in that set), another alternative is to use the
|
||||
tunnel pathways themselves to pass along the request and response, as is done
|
||||
in <a href="http://www.torproject.org/">TOR</a>. This, however, may lead to leaks
|
||||
during tunnel creation, allowing peers to discover how many hops there are later
|
||||
on in the tunnel by monitoring the timing or packet count as the tunnel is
|
||||
built. Techniques could be used to minimize this issue, such as using each of
|
||||
the hops as endpoints (per <a href="#tunnel.reroute">2.7.2</a>) for a random
|
||||
number of messages before continuing on to build the next hop.</p>
|
||||
|
||||
<h4>3.4.2) <a name="tunnel.building.nonexploratory">Non-exploratory tunnels for management</a></h4>
|
||||
|
||||
<p>A second alternative to the tunnel building process is to give the router
|
||||
an additional set of non-exploratory inbound and outbound pools, using those for
|
||||
the tunnel request and response. Assuming the router has a well integrated view
|
||||
of the network, this should not be necessary, but if the router was partitioned
|
||||
in some way, using non-exploratory pools for tunnel management would reduce the
|
||||
leakage of information about what peers are in the router's partition.</p>
|
||||
|
||||
<h2>4) <a name="tunnel.throttling">Tunnel throttling</a></h2>
|
||||
|
||||
<p>Even though the tunnels within I2P bear a resemblance to a circuit switched
|
||||
network, everything within I2P is strictly message based - tunnels are merely
|
||||
accounting tricks to help organize the delivery of messages. No assumptions are
|
||||
made regarding reliability or ordering of messages, and retransmissions are left
|
||||
to higher levels (e.g. I2P's client layer streaming library). This allows I2P
|
||||
to take advantage of throttling techniques available to both packet switched and
|
||||
circuit switched networks. For instance, each router may keep track of the
|
||||
moving average of how much data each tunnel is using, combine that with all of
|
||||
the averages used by other tunnels the router is participating in, and be able
|
||||
to accept or reject additional tunnel participation requests based on its
|
||||
capacity and utilization. On the other hand, each router can simply drop
|
||||
messages that are beyond its capacity, exploiting the research used on the
|
||||
normal Internet.</p>
|
||||
|
||||
<h2>5) <a name="tunnel.mixing">Mixing/batching</a></h2>
|
||||
|
||||
<p>What strategies should be used at the gateway and at each hop for delaying,
|
||||
reordering, rerouting, or padding messages? To what extent should this be done
|
||||
automatically, how much should be configured as a per tunnel or per hop setting,
|
||||
and how should the tunnel's creator (and in turn, user) control this operation?
|
||||
All of this is left as unknown, to be worked out for
|
||||
<a href="http://www.i2p.net/roadmap#3.0">I2P 3.0</a></p>
|
||||
|
||||
{% endblock %}
|
138
i2p2www/pages/site/docs/tunnels/unidirectional.html
Normal file
138
i2p2www/pages/site/docs/tunnels/unidirectional.html
Normal file
@@ -0,0 +1,138 @@
|
||||
{% extends "global/layout.html" %}
|
||||
{% block title %}Unidirectional Tunnels{% endblock %}
|
||||
{% block content %}
|
||||
<p>
|
||||
Updated July 2011 for release 0.8.7
|
||||
</p>
|
||||
|
||||
<h2>Overview</h2>
|
||||
<p>
|
||||
This page describes the origins and design of I2P's unidirectional tunnels.
|
||||
For further infomrmation see:
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ site_url('docs/how/tunnelrouting') }}">tunnel overview page</a>
|
||||
<li>
|
||||
<a href="{{ site_url('docs/tunnels/implementation') }}">tunnel specification</a>
|
||||
</li><li>
|
||||
<a href="{{ site_url('docs/spec/tunnel_creation') }}">tunnel creation specification</a>
|
||||
</li><li>
|
||||
<a href="{{ site_url('docs/discussions/tunnel') }}">tunnel design discussion</a>
|
||||
</li><li>
|
||||
<a href="{{ site_url('docs/how/peerselection') }}">peer selection</a>
|
||||
</li><li>
|
||||
<a href="{{ url_for('meetings_show', id=125) }}">Meeting 125 (~13:12-13:30)</a>
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h2>Review</h2>
|
||||
|
||||
<p>
|
||||
While we aren't aware of any published research on the advantages of
|
||||
unidirecdtional tunnels,
|
||||
they appear to make it harder to detect a
|
||||
request/response pattern, which is quite possible to detect over a
|
||||
bidirectional tunnel.
|
||||
Several apps and protocols, notably HTTP,
|
||||
do transfer data in such manner. Having the traffic follow the same
|
||||
route to its destination and back could make it easier for an
|
||||
attacker who has only timing and traffic volume data to infer the path a
|
||||
tunnel is taking.
|
||||
Having the response come back along a different path arguably
|
||||
makes it harder.
|
||||
|
||||
</p><p>
|
||||
When dealing with
|
||||
an internal adversary or most external adversaries, I2P's undirectional tunnels
|
||||
expose half as much traffic data than would be exposed with bidirectional circuits
|
||||
by simply looking at the flows themselves - an HTTP request and response would
|
||||
follow the same path in Tor, while in I2P the packets making up the request
|
||||
would go out through one or more outbound tunnels and the packets making up
|
||||
the response would come back through one or more different inbound tunnels.
|
||||
|
||||
</p><p>
|
||||
The strategy of using two separate tunnels for inbound and outbound
|
||||
communication is not the only technique available, and it does have anonymity
|
||||
implications. On the positive side, by using separate tunnels it lessens the
|
||||
traffic data exposed for analysis to participants in a tunnel - for instance,
|
||||
peers in an outbound tunnel from a web browser would only see the traffic of
|
||||
an HTTP GET, while the peers in an inbound tunnel would see the payload
|
||||
delivered along the tunnel. With bidirectional tunnels, all participants would
|
||||
have access to the fact that e.g. 1KB was sent in one direction, then 100KB
|
||||
in the other. On the negative side, using unidirectional tunnels means that
|
||||
there are two sets of peers which need to be profiled and accounted for, and
|
||||
additional care must be taken to address the increased speed of predecessor
|
||||
attacks. The tunnel pooling and building process
|
||||
(peer selection and ordering strategies)
|
||||
should minimize the worries of the predecessor attack.
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
<h2>Anonymity</h2>
|
||||
|
||||
<p>
|
||||
A recent
|
||||
<a href="http://grothoff.org/christian/i2p.pdf">paper by Hermann and Grothoff</a>
|
||||
declared that I2P's unidirectional tunnels "seems to be a bad design decision".
|
||||
|
||||
The paper's main point is that
|
||||
deanonymizations on unidirectional tunnels take a longer time, which is an
|
||||
advantage, but that an attacker can be more certain in the unidirectional case.
|
||||
Therefore, the paper claims it isn't an advantage at all, but a disadvantage, at least
|
||||
with long-living eepsites.
|
||||
|
||||
</p><p>
|
||||
This conclusion is not fully supported by the paper. Unidirectional tunnels clearly
|
||||
mitigate other attacks and it's not clear how to trade off the risk of the
|
||||
attack in the paper
|
||||
with attacks on a bidirectional tunnel architecture.
|
||||
|
||||
</p><p>
|
||||
This conclusion is based on an arbitrary certainty vs. time weighting
|
||||
(tradeoff) that may not be applicable in all cases. For
|
||||
example, somebody could make a list of possible IPs then issue subpoenas to
|
||||
each. Or the attacker could DDoS each in turn and via a simple
|
||||
intersection attack see if the eepsite goes down or is slowed down. So close
|
||||
may be good enough, or time may be more important.
|
||||
|
||||
The conclusion is based on a specific weighting of the importance of certainty
|
||||
vs. time, and that weighting may be wrong, and it's definitely debatable,
|
||||
especially in a real world with subpoenas, search warrants, and other methods
|
||||
available for final confirmation.
|
||||
|
||||
</p><p>
|
||||
A full analysis of the tradeoffs of unidirectional vs. bidirectional
|
||||
tunnels is clearly outside the scope of the paper, and has not been done
|
||||
elsewhere. For example, how does this attack compare to the numerous possible
|
||||
timing attacks published about onion-routed networks? Clearly the authors have not
|
||||
done that analysis, if it's even possible to do it
|
||||
effectively.
|
||||
|
||||
</p><p>
|
||||
Tor uses bidirectional tunnels and has had a lot of academic review. I2P
|
||||
uses unidirectional tunnels and has had very little review. Does the lack of a
|
||||
research paper defending unidirectional tunnels mean that it is a poor design
|
||||
choice, or just that it needs more study? Timing attacks and
|
||||
distributed attacks are difficult to defend against in both I2P and Tor. The
|
||||
design intent (see references above) was that unidirectional tunnels are more
|
||||
resistant to timing attacks. However, the paper presents a somewhat different type of timing
|
||||
attack. Is this attack, innovative as it is, sufficient to label I2P's
|
||||
tunnel architecture (and thus I2P as a whole) a "bad design", and by
|
||||
implication clearly inferior to Tor, or is it just a design alternative that
|
||||
clearly needs further investigation and analysis? There are several other reasons
|
||||
to consider I2P currently inferior to Tor and other projects (small network
|
||||
size, lack of funding, lack of review) but is unidirectional tunnels really a
|
||||
reason?
|
||||
|
||||
</p><p>
|
||||
In summary, "bad design decision" is apparently (since the paper does
|
||||
not label bidirectional tunnels "bad") shorthand for "unidirectional
|
||||
tunnels are unequivocally inferior to bidirectional tunnels", yet this
|
||||
conclusion is not supported by the paper.
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
{% endblock %}
|
Reference in New Issue
Block a user