forked from I2P_Developers/i2p.www
Drop todo sections that have been completed
This commit is contained in:
@@ -14,27 +14,12 @@ will come up, especially as I2P gets more peer review, but these are the main
|
||||
|
||||
<h2>{{ _('Core functionality') }} <span class="permalink"><a href="#core">[{{ _('link') }}]</a></span></h2>
|
||||
<ul class="targetlist">
|
||||
<li><a href="#nat">{% trans -%}
|
||||
NAT/Firewall bridging via 1-hop restricted routes
|
||||
{%- endtrans %}</a></li>
|
||||
<li><a href="#transport">{% trans -%}
|
||||
High degree transport layer with UDP, NBIO, or NIO
|
||||
{%- endtrans %}</a></li>
|
||||
<li><a href="#netdb">{% trans -%}
|
||||
NetworkDB and profile tuning and ejection policy for large nets
|
||||
{%- endtrans %}</a></li>
|
||||
</ul>
|
||||
<h2>{{ _('Security / anonymity') }} <span class="permalink"><a href="#security">[{{ _('link') }}]</a></span></h2>
|
||||
<ul class="targetlist">
|
||||
<li><a href="#tunnelId">{% trans -%}
|
||||
Per-hop tunnel id & new permuted TunnelVerificationStructure encryption
|
||||
{%- endtrans %}</a></li>
|
||||
<li><a href="#ordering">{% trans -%}
|
||||
Strict ordering of participants within tunnels
|
||||
{%- endtrans %}</a></li>
|
||||
<li><a href="#tunnelLength">{% trans -%}
|
||||
Randomly permuted tunnel lengths
|
||||
{%- endtrans %}</a></li>
|
||||
<li><a href="#fullRestrictedRoutes">{% trans -%}
|
||||
Full blown n-hop restricted routes with optional trusted links
|
||||
{%- endtrans %}</a></li>
|
||||
@@ -51,167 +36,6 @@ Stop & go mix w/ garlics & tunnels
|
||||
<h2>{{ _('Performance') }} <span class="permalink"><a href="{{ site_url('about/performance/future') }}">[{{ _('link') }}]</a></span></h2>
|
||||
|
||||
<h2 id="core">{{ _('Core functionality') }}</h2>
|
||||
<ul class="targetlist">
|
||||
<li>
|
||||
<h3 id="nat">{% trans -%}
|
||||
NAT/Firewall bridging via 1-hop restricted routes
|
||||
{%- endtrans %}</h3>
|
||||
</li>
|
||||
<!-- <li style="list-style: none; display: inline"> -->
|
||||
<b><i>{{ _('Implemented in I2P 0.6.0.6') }}</i></b>
|
||||
<p>{% trans -%}
|
||||
The functionality of allowing routers to fully participate within the network
|
||||
while behind firewalls and NATs that they do not control requires some basic
|
||||
restricted route operation (since those peers will not be able to receive
|
||||
inbound connections). To do this successfully, you consider peers one of
|
||||
two ways:
|
||||
{%- endtrans %}</p>
|
||||
<!-- </li> -->
|
||||
</ul>
|
||||
<ul>
|
||||
<li>{% trans -%}
|
||||
<b>Peers who have reachable interfaces</b> - these peers do not need to
|
||||
do anything special
|
||||
{%- endtrans %}</li>
|
||||
<li>{% trans -%}
|
||||
<b>Peers who do not have reachable interfaces</b> - these peers must build
|
||||
a tunnel pointing at them where the gateway is one of the peers they have
|
||||
established a connection with who has both a publicly reachable interface
|
||||
and who has agreed to serve as their 'introducer'.
|
||||
{%- endtrans %}</li>
|
||||
</ul>
|
||||
<div style="margin-left:25px;">
|
||||
<p>{% trans -%}
|
||||
To do this, peers who have no IP address simply connect to a few peers,
|
||||
build a tunnel through them, and publish a reference to those tunnels within
|
||||
their RouterInfo structure in the network database.
|
||||
{%- endtrans %}</p>
|
||||
<p>{% trans -%}
|
||||
When someone wants to contact any particular router, they first must get
|
||||
its RouterInfo from the network database, which will tell them whether they
|
||||
can connect directly (e.g. the peer has a publicly reachable interface)
|
||||
or whether they need to contact them indirectly. Direct connections occur
|
||||
as normal, while indirect connections are done through one of the published
|
||||
tunnels.
|
||||
{%- endtrans %}</p>
|
||||
<p>{% trans -%}
|
||||
When a router just wants to get a message or two to a specific hidden peer,
|
||||
they can just use the indirect tunnel for sending the payload. However,
|
||||
if the router wants to talk to the hidden peer often (for instance, as part
|
||||
of a tunnel), they will send a garlic routed message through the indirect
|
||||
tunnel to that hidden peer which unwraps to contain a message which should
|
||||
be sent to the originating router. That hidden peer then establishes an
|
||||
outbound connection to the originating router and from then on, those two
|
||||
routers can talk to each other directly over that newly established direct
|
||||
connection.
|
||||
{%- endtrans %}</p>
|
||||
<p>{% trans -%}
|
||||
Of course, that only works if the originating peer can receive connections
|
||||
(they aren't also hidden). However, if the originating peer is hidden, they
|
||||
can simply direct the garlic routed message to come back to the originating
|
||||
peer's inbound tunnel.
|
||||
{%- endtrans %}</p>
|
||||
<p>{% trans -%}
|
||||
This is not meant to provide a way for a peer's IP address to be concealed,
|
||||
merely as a way to let people behind firewalls and NATs fully operate within
|
||||
the network. Concealing the peer's IP address adds a little more work, as
|
||||
described <a href="#fullRestrictedRoutes">below.</a>
|
||||
{%- endtrans %}</p>
|
||||
<p>{% trans -%}
|
||||
With this technique, any router can participate as any part of a tunnel.
|
||||
For efficiency purposes, a hidden peer would be a bad choice for an inbound
|
||||
gateway, and within any given tunnel, two neighboring peers wouldn't want
|
||||
to be hidden. But that is not technically necessary.
|
||||
{%- endtrans %}</p>
|
||||
</div>
|
||||
<ul class="targetlist">
|
||||
<li>
|
||||
<h3 id="transport">{% trans -%}
|
||||
High degree transport layer with UDP, NBIO, or NIO
|
||||
{%- endtrans %}</h3>
|
||||
<b><i>{{ _('Both UDP and NIO have been Implemented in I2P') }}</i></b>
|
||||
<p>{% trans -%}
|
||||
Standard TCP communication in Java generally requires blocking socket
|
||||
calls, and to keep a blocked socket from hanging the entire system, those
|
||||
blocking calls are done on their own threads. Our current TCP transport
|
||||
is implemented in a naive fashion - for each peer we are talking to, we
|
||||
have one thread reading and one thread writing. The reader thread simply
|
||||
loops a bunch of read() calls, building I2NP messages and adding them
|
||||
to our internal inbound message queue, and the writer thread pulls messages
|
||||
off a per-connection outbound message queue and shoves the data through
|
||||
write() calls.
|
||||
{%- endtrans %}</p>
|
||||
<p>{% trans -%}
|
||||
We do this fairly efficiently, from a CPU perspective - at any time,
|
||||
almost all of these threads are sitting idle, blocked waiting for something
|
||||
to do. However, each thread consumes real resources (on older Linux kernels,
|
||||
for instance, each thread would often be implemented as a fork()'ed process).
|
||||
As the network grows, the number of peers each router will want to talk
|
||||
with will increase (remember, I2P is fully connected, meaning that any
|
||||
given peer should know how to get a message to any other peer, and restricted
|
||||
route support will probably not significantly reduce the number of connections
|
||||
necessary). This means that with a 100,000 router network, each router
|
||||
will have up to 199,998 threads just to deal with the TCP connections!
|
||||
{%- endtrans %}</p>
|
||||
<p>{% trans -%}
|
||||
Obviously, that just won't work. We need to use a transport layer that
|
||||
can scale. In Java, we have two main camps:
|
||||
{%- endtrans %}</p>
|
||||
<h4>UDP</h4>
|
||||
<b><i>{% trans ssu=site_url('docs/transport/ssu') -%}
|
||||
Implemented in I2P 0.6 ("SSU") as documented <a href="{{ ssu }}">elsewhere</a>
|
||||
{%- endtrans %}</i></b>
|
||||
<p>{% trans -%}
|
||||
Sending and receiving UDP datagrams is a connectionless operation - if
|
||||
we are communicating with 100,000 peers, we simply stick the UDP packets
|
||||
in a queue and have a single thread pulling them off the queue and shoving
|
||||
them out the pipe (and to receive, have a single thread pulling in any
|
||||
UDP packets received and adding them to an inbound queue).
|
||||
{%- endtrans %}</p>
|
||||
<p>{% trans -%}
|
||||
However, moving to UDP means losing the benefits of TCP's ordering, congestion
|
||||
control, MTU discovery, etc. Implementing that code will take significant
|
||||
work, however I2P doesn't need it to be as strong as TCP. Specifically,
|
||||
a while ago I was taking some measurements in the simulator and on the
|
||||
live net, and the vast majority of messages transferred would fit easily
|
||||
within a single unfragmented UDP packet, and the largest of the messages
|
||||
would fit within 20-30 packets. As mule pointed out, TCP adds a significant
|
||||
overhead when dealing with so many small packets, as the ACKs are within
|
||||
an order of magnitude in size. With UDP, we can optimize the transport
|
||||
for both efficiency and resilience by taking into account I2P's particular
|
||||
needs.
|
||||
{%- endtrans %}</p>
|
||||
<p>{% trans -%}
|
||||
It will be a lot of work though.
|
||||
{%- endtrans %}</p>
|
||||
<h4>{{ _('NIO or NBIO') }}</h4>
|
||||
<b><i>{% trans -%}
|
||||
NIO Implemented in I2P 0.6.1.22 ("NTCP")
|
||||
{%- endtrans %}</i></b>
|
||||
<p>{% trans -%}
|
||||
In Java 1.4, a set of "New I/O" packages was introduced, allowing Java
|
||||
developers to take advantage of the operating system's nonblocking IO
|
||||
capabilities - allowing you to maintain a large number of concurrent IO
|
||||
operations without requiring a separate thread for each. There is much
|
||||
promise with this approach, as we can scalable handle a large number of
|
||||
concurrent connections and we don't have to write a mini-TCP stack with
|
||||
UDP. However, the NIO packages have not proven themselves to be battle-ready,
|
||||
as the Freenet developer's found. In addition, requiring NIO support would
|
||||
mean we can't run on any of the open source JVMs like <a href="http://www.kaffe.org/">Kaffe</a>,
|
||||
as <a href="http://www.classpath.org/">GNU/Classpath</a> has only limited
|
||||
support for NIO. <i>(note: this may not be the case anymore, as there
|
||||
has been some progress on Classpath's NIO, but it is an unknown quantity)</i>
|
||||
{%- endtrans %}</p>
|
||||
<p>{% trans link='http://www.eecs.harvard.edu/~mdw/proj/java-nbio/' -%}
|
||||
Another alternative along the same lines is the <a href="{{ link }}">Non
|
||||
Blocking I/O</a> package - essentially a cleanroom NIO implementation
|
||||
(written before NIO was around). It works by using some native OS code
|
||||
to do the nonblocking IO, passing off events through Java. It seems to
|
||||
be working with Kaffe, though there doesn't seem to be much development
|
||||
activity on it lately (likely due to 1.4's NIO deployment).
|
||||
{%- endtrans %}</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="targetlist">
|
||||
<li>
|
||||
<h3 id="netdb">{% trans -%}
|
||||
@@ -240,118 +64,6 @@ in mind. We will have some work to do, but we can put it off for later.
|
||||
</ul>
|
||||
<h2 id="security">{{ _('Security / anonymity') }}</h2>
|
||||
<ul class="targetlist">
|
||||
<li>
|
||||
<h3 id="tunnelId">{% trans -%}
|
||||
Per-hop tunnel id & new permuted TunnelVerificationStructure encryption
|
||||
{%- endtrans %}</h3>
|
||||
<b><i>{% trans tunnelimpl=site_url('docs/tunnels/implementation') -%}
|
||||
Addressed in I2P 0.5 as documented <a href="{{ tunnelimpl }}">elsewhere</a>
|
||||
{%- endtrans %}</i></b>
|
||||
<p>{% trans -%}
|
||||
Right now, if Alice builds a four hop inbound tunnel starting at Elvis,
|
||||
going to Dave, then to Charlie, then Bob, and finally Alice (A<--B<--C<--D<--E),
|
||||
all five of them will know they are participating in tunnel "123", as
|
||||
the messages are tagged as such. What we want to do is give each hop their
|
||||
own unique tunnel hop ID - Charlie will receive messages on tunnel 234
|
||||
and forward them to tunnel 876 on Bob. The intent is to prevent Bob or
|
||||
Charlie from knowing that they are in Alice's tunnel, as if each hop in
|
||||
the tunnel had the same tunnel ID, collusion attacks aren't much work.
|
||||
{%- endtrans %}</p>
|
||||
<p>{% trans -%}
|
||||
Adding a unique tunnel ID per hop isn't hard, but by itself, insufficient.
|
||||
If Dave and Bob are under the control of the same attacker, they wouldn't
|
||||
be able to tell they are in the same tunnel due to the tunnel ID, but
|
||||
would be able to tell by the message bodies and verification structures
|
||||
by simply comparing them. To prevent that, the tunnel must use layered
|
||||
encryption along the path, both on the payload of the tunneled message
|
||||
and on the verification structure (used to prevent simple tagging attacks).
|
||||
This requires some simple modifications to the TunnelMessage, as well
|
||||
as the inclusion of per-hop secret keys delivered during tunnel creation
|
||||
and given to the tunnel's gateway. We must fix a maximum tunnel length
|
||||
(e.g. 16 hops) and instruct the gateway to encrypt the message to each
|
||||
of the 16 delivered secret keys, in reverse order, and to encrypt the
|
||||
signature of the hash of the (encrypted) payload at each step. The gateway
|
||||
then sends that 16-step encrypted message, along with a 16-step and 16-wide
|
||||
encrypted mapping to the first hop, which then decrypts the mapping and
|
||||
the payload with their secret key, looking in the 16-wide mapping for
|
||||
the entry associated with their own hop (keyed by the per-hop tunnel ID)
|
||||
and verifying the payload by checking it against the associated signed
|
||||
hash.
|
||||
{%- endtrans %}</p>
|
||||
<p>{% trans -%}
|
||||
The tunnel gateway does still have more information than the other peers
|
||||
in the tunnel, and compromising both the gateway and a tunnel participant
|
||||
would allow those peers to collude, exposing the fact that they are both
|
||||
in the same tunnel. In addition, neighboring peers know that they are
|
||||
in the same tunnel anyway, as they know who they send the message to (and
|
||||
with IP-based transports without restricted routes, they know who they
|
||||
got it from). However, the above two techniques significantly increase
|
||||
the cost of gaining meaningful samples when dealing with longer tunnels.
|
||||
{%- endtrans %}</p>
|
||||
</li></ul>
|
||||
<ul class="targetlist">
|
||||
<li>
|
||||
<h3 id="ordering">{% trans -%}
|
||||
Strict ordering of participants within tunnels
|
||||
{%- endtrans %}</h3>
|
||||
<b><i>{{ _('Implemented in release 0.6.2') }}</i></b></li>
|
||||
</ul>
|
||||
<div style="margin-left:25px">
|
||||
<p>{% trans link='http://article.gmane.org/gmane.network.i2p/22/',
|
||||
pdf1='http://forensics.umass.edu/pubs/wright-tissec.pdf',
|
||||
pdf2='http://forensics.umass.edu/pubs/wright.tissec.2008.pdf' -%}
|
||||
As Connelly <a href="{{ link }}">proposed</a> to deal with the
|
||||
<a href="{{ pdf1 }}">predecessor attack</a> <a href="{{ pdf2 }}">(2008
|
||||
update)</a>, keeping the order of peers within our tunnels consistent
|
||||
(aka whenever Alice creates a tunnel with both Bob and Charlie in it,
|
||||
Bob's next hop is always Charlie), we address the issue as Bob doesn't
|
||||
get to substantially sample Alice's peer selection group. We may even
|
||||
want to explicitly allow Bob to participate in Alice's tunnels in only
|
||||
one way - receiving a message from Dave and sending it to Charlie - and
|
||||
if any of those peers are not available to participate in the tunnel (due
|
||||
to overload, network disconnection, etc), avoid asking Bob to participate
|
||||
in any tunnels until they are back online.
|
||||
{%- endtrans %}</p>
|
||||
<p>{% trans -%}
|
||||
More analysis is necessary for revising the tunnel creation - at the
|
||||
moment, we simply select and order randomly within the peer's top tier
|
||||
of peers (ones with fast + high capacity).
|
||||
{%- endtrans %}</p>
|
||||
<p>{% trans -%}
|
||||
Adding a strict ordering to peers in a tunnel also improves the anonymity
|
||||
of peers with 0-hop tunnels, as otherwise the fact that a peer's gateway
|
||||
is always the same would be particularly damning. However, peers with
|
||||
0-hop tunnels may want to periodically use a 1-hop tunnel to simulate
|
||||
the failure of a normally reliable gateway peer (so every MTBF*(tunnel
|
||||
duration) minutes, use a 1-hop tunnel).
|
||||
{%- endtrans %}</p>
|
||||
</div>
|
||||
<ul class="targetlist"><li>
|
||||
<h3 id="tunnelLength">Randomly permuted tunnel lengths</h3>
|
||||
<b><i>{% trans tunnelimpl=site_url('docs/tunnels/implementation') -%}
|
||||
Addressed in I2P 0.5 as documented <a href="{{ tunnelimpl }}">elsewhere</a>
|
||||
{%- endtrans %}</i></b></li>
|
||||
</ul>
|
||||
<ul class="targetlist">
|
||||
<!-- <li style="list-style: none; display: inline"> -->
|
||||
<p>{% trans -%}
|
||||
Without tunnel length permutation, if someone were to somehow detect that
|
||||
a destination had a particular number of hops, it might be able to use that
|
||||
information to identify the router the destination is located on, per the
|
||||
predecessor attack. For instance, if everyone has 2-hop tunnels, if Bob
|
||||
receives a tunnel message from Charlie and forwards it to Alice, Bob knows
|
||||
Alice is the final router in the tunnel. If Bob were to identify what destination
|
||||
that tunnel served (by means of colluding with the gateway and harvesting
|
||||
the network database for all of the LeaseSets), he would know the router
|
||||
on which that destination is located (and without restricted routes, that
|
||||
would mean what IP address the destination is on).
|
||||
{%- endtrans %}</p>
|
||||
<p>{% trans -%}
|
||||
It is to counter user behavior that tunnel lengths should be permuted,
|
||||
using algorithms based on the length requested (for example, the 1/MTBF
|
||||
length change for 0-hop tunnels outlined above).
|
||||
{%- endtrans %}</p>
|
||||
<!-- </li> -->
|
||||
<li>
|
||||
<h3 id="fullRestrictedRoutes">{% trans -%}
|
||||
Full blown n-hop restricted routes with optional trusted links
|
||||
|
Reference in New Issue
Block a user