diff --git a/i2p2www/pages/site/get-involved/todo.html b/i2p2www/pages/site/get-involved/todo.html index f8f1db40..ce70e590 100644 --- a/i2p2www/pages/site/get-involved/todo.html +++ b/i2p2www/pages/site/get-involved/todo.html @@ -14,27 +14,12 @@ will come up, especially as I2P gets more peer review, but these are the main
{% 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 %}
- -{% 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 %}
-{% 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 %}
-{% 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 %}
-{% 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 %}
-{% 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 below. -{%- endtrans %}
-{% 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 %}
-{% 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 %}
-{% 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 %}
-{% 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 %}
-{% 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 %}
-{% 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 %}
-{% trans -%} -It will be a lot of work though. -{%- endtrans %}
-{% 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 Kaffe, -as GNU/Classpath has only limited -support for NIO. (note: this may not be the case anymore, as there -has been some progress on Classpath's NIO, but it is an unknown quantity) -{%- endtrans %}
-{% trans link='http://www.eecs.harvard.edu/~mdw/proj/java-nbio/' -%} -Another alternative along the same lines is the Non -Blocking I/O 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 %}
-{% 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 %}
-{% 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 %}
-{% 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 %}
-{% 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 proposed to deal with the -predecessor attack (2008 -update), 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 %}
-{% 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 %}
-{% 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 %}
-{% 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 %}
-{% 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 %}
-