propagate from branch 'i2p.www' (head 450ad476f29b19837b174d3f5308c0cad1a343cb)

to branch 'i2p.www.revamp' (head becf05e00adefe160827d157a8a1fe3d4d2fa5b7)
This commit is contained in:
str4d
2013-09-16 12:58:56 +00:00
1400 changed files with 203482 additions and 59187 deletions

View File

@@ -0,0 +1,5 @@
{% extends "blog/index.html" %}
{% block title %}{{ _('Blog Category') }}: {{ category }}{% endblock %}
{% block headextra %}
<link href="{{ get_url('blog_atom', category=category) }}" type="application/atom+xml" rel="alternate" title="{% trans %}I2P Blog ATOM Feed for Category: {{ category }}{% endtrans %}" />
{%- endblock %}

View File

@@ -0,0 +1,24 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Blog') }}{% endblock %}
{% block headextra %}
<link href="{{ get_url('blog_atom') }}" type="application/atom+xml" rel="alternate" title="{{ _('I2P Blog ATOM Feed') }}" />
{%- endblock %}
{% block content %}
<ul id="posts">
{% for (slug, post) in posts %}
<li>
<article>
<header>
<a href="{{ get_url('blog_post', slug=slug) }}">{{ post.title }}</a>
</header>
{%- if post.excerpt %}
<p>{{ post.excerpt }}</p>
{%- endif %}
<footer>{% trans date=post.date, author=post.author %}Posted {{ date }} by {{ author }}{% endtrans %}</footer>
</article>
</li>
{% endfor %}
</ul>
{%- from "global/macros" import render_pagination with context -%}
{{ render_pagination(pagination) | safe }}
{% endblock %}

View File

@@ -0,0 +1,6 @@
<ul>
{% for slug, post in blog_posts -%}
<li>{{ post.date }} - <a href="{{ get_url('blog_post', slug=slug) }}">{{ post.title }}</a></li>
{%- endfor %}
<li><a href="{{ get_url('blog_index') }}"><em>{{ _('More blog posts&hellip;') }}</em></a></li>
</ul>

View File

@@ -0,0 +1,13 @@
{% extends "global/layout.html" %}
{%- from "global/macros" import render_categories with context -%}
{% block title %}{{ title }} - {{ _('Blog') }}{% endblock %}
{% block content %}
<ul id="post-info" class="lastupdated">
<li class="date">{{ _('Posted:') }} {{ meta.date }}</li>
<li class="author">{{ _('Author:') }} {{ meta.author }}</li>
<li class="category">{{ render_categories(meta.category)|safe }}</li>
</ul>
{% autoescape false %}
{{ body }}
{% endautoescape %}
{% endblock %}

View File

@@ -0,0 +1,200 @@
{% extends "global/layout.html" %}
{% block title %}Debian/Ubuntu{% endblock %}
{% block content %}
<h1>{{ _('Debian I2P Packages') }}</h1>
{% trans -%}
The packages hosted on <a href="https://launchpad.net/%7Ei2p-maintainers/+archive/i2p">the I2P Launchpad site</a>
have been tested and <em>should </em>work on x86/x86_64 platforms running:
{%- endtrans %}
<ul>
<li>{% trans %}<a href="#ubuntu">Ubuntu</a> (Precise <em>12.04</em> and newer){% endtrans %}</li>
<li><a href="#ubuntu">Mint</a></li>
<li>{% trans %}<a href="#debian">Debian Linux</a> (Wheezy and newer) &amp; <a href="#nonlinux">kFreeBSD</a>{% endtrans %}</li>
<li><a href="#debian">Knoppix</a></li>
</ul>
{% trans trac=i2pconv('trac.i2p2.i2p') -%}
The I2P packages <em>may</em> work on systems not listed above. Please report any issues
with these packages on <a href="http://{{ trac }}">Trac</a> at
<a href="http://{{ trac }}">http://{{ trac }}</a>.
{%- endtrans %}
<ul>
<li>{% trans %}Option 1: <a href="#ubuntu">Recent versions</a> of Ubuntu and its derivatives (<em>Try this if you're not using Debian)</em>{% endtrans %}</li>
<li>{% trans %}Option 2: <a href="#debian">Debian</a> (including Debian-derivatives){% endtrans %}</li>
<li>{% trans %}Option 3: <a href="#nonlinux">Non-Linux</a> (and possibly Non-x86 architectures){% endtrans %}</li>
</ul>
<h2 id="ubuntu">{{ _('Instructions for Ubuntu Precise Pangolin (and newer) and derivatives like Linux Mint &amp; Trisquel') }}</h2>
<h5>{{ _('Adding the PPA via the command line and installing I2P') }}</h5>
<ol>
<li>
{% trans %}Open a terminal and enter:{% endtrans %}<br />
<code>&nbsp;&nbsp;&nbsp; sudo apt-add-repository ppa:i2p-maintainers/i2p</code><br />
{% trans -%}
This command will add the PPA to /etc/apt/sources.list.d and fetch the
gpg key that the repository has been signed with. The GPG key ensures
that the packages have not been tampered with since being built.
{%- endtrans %}
</li>
<li>
{% trans %}Notify your package manager of the new PPA by entering:{% endtrans %}<br />
<code>&nbsp;&nbsp;&nbsp; sudo apt-get update</code><br />
{% trans -%}
This command will retrieve the latest list of software from each
repository that is enabled on your system, including the I2P PPA that
was added with the earlier command.
{%- endtrans %}
</li>
<li>{% trans %}You are now ready to install I2P!{% endtrans %}<br />
<code>&nbsp;&nbsp;&nbsp;&nbsp;sudo apt-get install i2p</code></li>
</ol>
<h5>{{ _('Adding the PPA Using Synaptic') }}</h5>
<ol>
<li>
{% trans -%}
Open Synaptic (System -&gt; Administration -&gt; Synaptic Package Manager).
{%- endtrans %}
</li>
<li>
{% trans -%}
Once Synaptic opens, select <em>Repositories</em> from the <em>Settings</em> menu.
{%- endtrans %}
</li>
<li>
{% trans -%}
Click the <em>Other Sources</em> tab and click <em>Add</em>. Paste <code>ppa:i2p-maintainers/i2p</code> into the APT-line field and click <em>Add Source</em>. Click the <em>Close</em> button then <em>Reload</em>.
{%- endtrans %}
</li>
<li>
{% trans -%}
In the Quick Filter box, type in <code>i2p</code> and press enter. When <code>i2p</code> is returned in the results list, right click <code>i2p</code> and select <em>Mark for Installation</em>. After doing so you may see a <em>Mark additional required changes?</em> popup. If so, click <em>Mark</em> then <em>Apply</em>.
{%- endtrans %}
</li>
</ol>
{% trans -%}
After the installation process completes you can move on to the next
part of <a href="#Post-install_work">starting I2P</a> and configuring it for your system.
{%- endtrans %}
<h2 id="debian">{{ _('Instructions for Debian Lenny and newer') }}</h2>
<p>(<em>{% trans %}For Squeeze you can follow the instructions <a href="#nonlinux">here</a>.{% endtrans %}</em>)</p>
{% trans -%}
The steps below should be performed with root access (i.e., switching
user to root with "su" or by prefixing each command with "sudo").
{%- endtrans %}
<ol>
<li>
{% trans %}Add the GPG key that signs the repository with the following command:{% endtrans %}<br />
<code>&nbsp;&nbsp;&nbsp; apt-key adv --keyserver keyserver.ubuntu.com --recv-keys <a href="http://keyserver.ubuntu.com:11371/pks/lookup?search=0x474BC46576FAE76E97C1A1A1AB9660B9EB2CC88B&amp;op=index">EB2CC88B</a></code><br />
{% trans %}You'll have output like the following if the command was successful:{% endtrans %}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<img src="{{ url_for('static', filename='images/add-key-terminal.png') }}" alt="" />
</li>
<li>
{% trans %}Add the following entries to <code>/etc/apt/sources.list.d/i2p.list</code>{% endtrans %}<br />
<code>&nbsp;&nbsp;&nbsp; deb http://ppa.launchpad.net/i2p-maintainers/i2p/ubuntu precise main <br />
&nbsp;&nbsp;&nbsp; deb-src http://ppa.launchpad.net/i2p-maintainers/i2p/ubuntu precise main </code><br />
</li>
<li>
{% trans %}Notify your package manager of the new PPA by entering{% endtrans %}<br />
<code>&nbsp;&nbsp;&nbsp; apt-get update</code><br />
{% trans -%}
This command will retrieve the latest list of software from every
repository enabled on your system, including the I2P PPA added in step
1.
{%- endtrans %}
</li>
<li>
{% trans %}You are now ready to install I2P!{% endtrans %}<br />
<code>&nbsp;&nbsp;&nbsp; apt-get install i2p</code></li>
</ol>
{% trans -%}
After the installation process completes you can move on to the next part of <a href="#Post-install_work">starting I2P</a> and configuring it for your system.
{%- endtrans %}
<h2 id="nonlinux">{{ _('Instructions for Non-Linux / Non-x86') }}</h2>
{% trans -%}
The steps below should be performed with root access (i.e., switching
user to root with "<code>su</code>" or by prefixing each command with "<code>sudo</code>").
{%- endtrans %}<br />
<ol>
<li>
{% trans ppa='http://ppa.launchpad.net/i2p-maintainers/i2p/ubuntu/pool/main/i/i2p/',
kytv='http://'+i2pconv('killyourtv.i2p')+'/debian/' -%}
Download the <a href="{{ ppa }}">i2p-router</a> package from the <a href="{{ ppa }}">PPA</a>.
Alternatively, there are unofficial packages available <a href="{{ kytv }}">here</a> for <code>armel, armhf, and kfreebsd</code>.
{%- endtrans %}
</li>
<li>
{% trans -%}
Make sure that you have Java installed. Running <em><code>apt-get install default-jre</code></em> should be sufficient.{% endtrans %}<br />
{% trans %}You are now ready to install I2P!{% endtrans %}<br />
<code>&nbsp;&nbsp;&nbsp; dpkg -i i2p-router_*.deb</code>
</li>
<li>
{% trans jbigi=site_url('misc/jbigi') -%}
It is recommended to compile <a href="{{ jbigi }}">jbigi</a> for your system to achieve better performance. Instructions are available <a href="{{ jbigi }}">here</a>.
{%- endtrans %}
</li>
</ol>
{% trans -%}
After the installation process completes you can move on to the next part of <a href="#Post-install_work">starting I2P</a> and configuring it for your system.
{%- endtrans %}
<h2 id="Post-install_work">{{ _('Post-install work') }}</h2>
{% trans -%}
Using these I2P packages the I2P router can be started in the following
three ways:
{%- endtrans %}
<ul>
<li>
{% trans -%}
&quot;on demand&quot; using the i2prouter script. Simply run &quot;<code>i2prouter
start</code>&quot; from a command prompt. (Note: Do <strong><u>not</u></strong> use
sudo or run it as root!)
{%- endtrans %}
</li>
<li>
{% trans -%}
&quot;on demand&quot; without the <a href="http://wrapper.tanukisoftware.com/">java service wrapper</a>
(needed on non-Linux/non-x86 systems) by running "<code>i2prouter-nowrapper</code>".
(Note: Do <strong><u>not</u></strong>
use sudo or run it as root!)
{%- endtrans %}
</li>
<li>
{% trans -%}
as a service that automatically runs when your system boots, even
before logging in. The service can be enabled with "<code>dpkg-reconfigure
i2p</code>" as root or using sudo. This is the recommended means of operation.
{%- endtrans %}
</li>
</ul>
<p>{% trans -%}
When installing for the first time, please remember to <b>adjust your NAT/firewall</b>
if you can. The ports to forward can be found on the <a href="http://127.0.0.1:7657/confignet">
network configuration page</a> in the router console. If guidance with respect to forwarding ports is needed,
you may find <a href="http://portforward.com">portforward.com</a> to be helpful.
{%- endtrans %}</p>
<p>{% trans -%}
Please review and <b>adjust the bandwidth settings</b> on the
<a href="http://127.0.0.1:7657/config.jsp">configuration page</a>,
as the default settings of 96 KB/s down / 40 KB/s up are fairly conservative.
{%- endtrans %}</p>
<p>{% trans browserconfig=site_url('about/browser-config') -%}
If you want to reach eepsites via your browser, have a look on the <a href="{{ browserconfig }}">browser proxy setup</a> page for an easy howto.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,308 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Download') }}{% endblock %}
{% set i2pinstall_windows_sig = '293f445196a2f35c4d580f65b548135399e1f4443450b5ecf1cc53b1203fdad1' %}
{% set i2pinstall_jar_sig = '9fae874a4d680f50f5efd7be70cfcf55f2f4687e011bde9c4b4899bafb002e97' %}
{% set i2p_android_sig = 'a6120e19186246458a01e498eeb9e5afcb3901b9c058244410bda85d5a474113' %}
{% set i2psource_sig = '7b73bdb23c53798054741cbaa4e7d8cce832ee566fbb17df0c803d0c22d099e1' %}
{% set i2pupdate_sig = '69ca22a77a2de87f726d86555317f8688891d31f5312cf71d5a43febe2729b38' %}
{% block content %}
<h1>{{ _('Download I2P') }}</h1>
<h3>{{ _('Dependency') }}</h3>
<p>{% trans java='http://java.com/download/',
openjdk='http://openjdk.java.net/install/',
icedtea='http://icedtea.classpath.org/wiki/Main_Page' %}
Java Runtime 1.5 or higher.
(<a href="{{ java }}">Oracle Java Version 6/7</a>,
<a href="{{ openjdk }}">OpenJDK 6/7</a>, or
<a href="{{ icedtea }}">IcedTea6/7</a>
recommended)
<br />
<a href="http://java.com/en/download/installed.jsp?detect=jre&amp;try=1">Determine your installed Java version here</a>
or type <tt>java -version</tt> at your command prompt.
{% endtrans %}</p>
<h3>{{ _('Clean installs') }}</h3>
<div class="downloadlist">
<div class="package">
<h1>Windows</h1>
<div class="file">
<a href="{{ url_for('downloads_redirect', version=ver(), protocol=def_mirror.protocol, domain=def_mirror.domain, file=ver('i2pinstall_%s_windows.exe')) }}">i2pinstall_{{ ver() }}_windows.exe</a> ({{ def_mirror.org }})
(<a href="{{ get_url('downloads_select', version=ver(), file=ver('i2pinstall_%s_windows.exe')) }}">{{ _('select alternate link') }}</a>)
<div class="sig">
(SHA256 <code>{{ i2pinstall_windows_sig }}</code>
<a href="{{ url_for('downloads_redirect', version=ver(), protocol=def_mirror.protocol, domain=def_mirror.domain, file=ver('i2pinstall_%s_windows.exe.sig')) }}">sig</a>)
</div>
</div>
<div class="details">
{% trans -%}
Download that file and run it.
{%- endtrans %}
</div>
</div>
<div class="package">
<h1>Mac OS X</h1>
<div class="file">
<a href="{{ url_for('downloads_redirect', version=ver(), protocol=def_mirror.protocol, domain=def_mirror.domain, file=ver('i2pinstall_%s.jar')) }}">i2pinstall_{{ ver() }}.jar</a> ({{ def_mirror.org }})
(<a href="{{ get_url('downloads_select', version=ver(), file=ver('i2pinstall_%s.jar')) }}">{{ _('select alternate link') }}</a>)
<div class="sig">
(SHA256 <code>{{ i2pinstall_jar_sig }}</code>
<a href="{{ url_for('downloads_redirect', version=ver(), protocol=def_mirror.protocol, domain=def_mirror.domain, file=ver('i2pinstall_%s.jar.sig')) }}">sig</a>)
</div>
</div>
<div class="details">
{% trans i2pversion=ver() -%}
Download that file and double-click it (if that works) or
type <code>java -jar i2pinstall_{{ i2pversion }}.jar</code> in a terminal to run the
installer.
You may be able to right-click and select
&quot;Open with Java&quot;.
{%- endtrans %}
<h2>{% trans %}Command line (headless) install:{% endtrans %}</h2>
{% trans i2pversion=ver() -%}
Download the {{ i2pversion }} OSX graphical installer file above and
run <code>java -jar i2pinstall_{{ i2pversion }}.jar -console</code> from the command line.
{%- endtrans %}
</div>
</div>
<div class="package">
<h1>GNU/Linux / BSD / Solaris</h1>
<div class="file">
<a href="{{ url_for('downloads_redirect', version=ver(), protocol=def_mirror.protocol, domain=def_mirror.domain, file=ver('i2pinstall_%s.jar')) }}">i2pinstall_{{ ver() }}.jar</a> ({{ def_mirror.org }})
(<a href="{{ get_url('downloads_select', version=ver(), file=ver('i2pinstall_%s.jar')) }}">{{ _('select alternate link') }}</a>)
<div class="sig">
(SHA256 <code>{{ i2pinstall_jar_sig }}</code>
<a href="{{ url_for('downloads_redirect', version=ver(), protocol=def_mirror.protocol, domain=def_mirror.domain, file=ver('i2pinstall_%s.jar.sig')) }}">sig</a>)
</div>
</div>
<div class="details">
{% trans i2pversion=ver() -%}
Download that file and double-click it (if that works) or
type <code>java -jar i2pinstall_{{ i2pversion }}.jar</code> in a terminal to run the
installer.
On some platforms you may be able to right-click and select
&quot;Open with Java&quot;.
{%- endtrans %}
<h2>{% trans %}Command line (headless) install:{% endtrans %}</h2>
{% trans i2pversion=ver() -%}
Download the graphical installer file above and
run <code>java -jar i2pinstall_{{ i2pversion }}.jar -console</code> from the command line.
{%- endtrans %}
</div>
</div>
<div class="package">
<h1>Debian / Ubuntu</h1>
<div class="details">
<a href="{{ get_url('downloads_debian') }}">{% trans %}Packages for Debian &amp; Ubuntu are available.{% endtrans %}</a>
</div>
</div>
<div class="package">
<h1>Android</h1>
<div class="file">
<a href="http://{{ i2pconv('stats.i2p') }}/i2p.apk">i2p-android-0.9.7.1-0_b4-API8.apk</a>
<div class="sig">
(SHA256 <code>{{ i2p_android_sig }}</code>
)
</div>
</div>
<div class="details">
{% trans devbuild='0.9.7.1-23_b2-API8', str4durl='http://'+i2pconv('str4d.i2p')+'/android/' -%}
The above file is the current release build.
The latest dev build is version {{ devbuild }}, and is available from
<a href="{{ str4durl }}">str4d's eepsite</a>.
{%- endtrans %}
<div class="warning">
{% trans -%}
The release and dev versions of the I2P APK are not compatible, as they
are signed by zzz and str4d respectively. Uninstall one before installing
the other.
{%- endtrans %}
</div>
</div>
</div>
<div class="package">
<h1>{{ _('Source package') }}</h1>
<div class="file">
<a href="{{ url_for('downloads_redirect', version=ver(), protocol=def_mirror.protocol, domain=def_mirror.domain, file=ver('i2psource_%s.tar.bz2')) }}">i2psource_{{ ver() }}.tar.bz2</a> ({{ def_mirror.org }})
(<a href="{{ get_url('downloads_select', version=ver(), file=ver('i2psource_%s.tar.bz2')) }}">{{ _('select alternate link') }}</a>)
<div class="sig">
(SHA256 <code>{{ i2psource_sig }}</code>
<a href="{{ url_for('downloads_redirect', version=ver(), protocol=def_mirror.protocol, domain=def_mirror.domain, file=ver('i2psource_%s.tar.bz2.sig')) }}">sig</a>)
</div>
</div>
<div class="details">
{% trans monotoneurl=site_url('get-involved/guides/new-developers'),
gitrepo='http://'+i2pconv('git.repo.i2p')+'/w/i2p.i2p.git',
github='https://github.com/i2p/i2p.i2p',
i2pversion=ver() -%}
Alternately, you can fetch the source from <a href="{{ monotoneurl }}#getting-the-i2p-code">monotone</a>
or via Git from <a href="{{ gitrepo }}">git.repo.i2p</a> or <a href="{{ github }}">Github</a>.
<br />
Run <code>(tar xjvf i2psource_{{ i2pversion }}.tar.bz2 ; cd i2p-{{ i2pversion }} ; ant pkg)</code> then either
run the GUI installer or headless install as above.
{%- endtrans %}
</div>
</div>
</div>
{% trans signingkey=site_url('get-involved/develop/release-signing-key') -%}
The files are signed by zzz,
<a href="{{ signingkey }}">whose key is here</a>.
{%- endtrans %}
<p>{% trans -%}
I2P can also be downloaded from our project pages on <a href="https://launchpad.net/i2p/trunk">Launchpad</a> and <a href="http://code.google.com/p/i2p/">Google Code</a>.
{%- endtrans %}</p>
<h3>{{ _('Post-install work') }}</h3>
<p>{% trans -%}
After running the installer on windows, simply click on the "Start I2P" button
which will bring up the <a href="http://localhost:7657/index.jsp">router console</a>,
which has further instructions.
{%- endtrans %}</p>
<p>{% trans -%}
On Unix-like systems, I2P can be started as a service
using the "i2prouter" script, located in the directory you selected for I2P.
Changing to that directory in a console and issuing "sh i2prouter status"
should tell you the router's status. The arguments "start", "stop" and "restart"
control the service. The <a href="http://localhost:7657/index.jsp">router console</a>
can be accessed at its usual location.
For users on OpenSolaris and other systems for which the wrapper (i2psvc) is not supported,
start the router with "sh runplain.sh" instead.
{%- endtrans %}</p>
<p>{% trans faq=site_url('faq') -%}
When installing for the first time, please remember to <b>adjust your NAT/firewall</b>
if you can, bearing in mind the Internet-facing ports I2P uses,
<a href="{{ faq }}#ports">described here</a> among other ports.
If you have successfully opened your port to inbound TCP, also enable inbound TCP on the
<a href="http://localhost:7657/confignet.jsp">configuration page</a>.
{%- endtrans %}</p>
<p>{% trans -%}
Also, please review and <b>adjust the bandwidth settings</b> on the
<a href="http://localhost:7657/config.jsp">configuration page</a>,
as the default settings of 96 KBps down / 40 KBps up are fairly slow.
{%- endtrans %}</p>
<p>{% trans browserconfig=site_url('about/browser-config') -%}
If you want to reach eepsites via your browser, have a look on the <a href="{{ browserconfig }}">browser proxy setup</a> page for an easy howto.
{%- endtrans %}</p>
<h3>{{ _('Updates from earlier releases:') }}</h3>
<p>{% trans -%}
Both automatic and manual upgrades are available for the release.
{%- endtrans %}</p>
<div class="package">
<h1>{{ _('Automatic updates') }}</h1>
<div class="details">
<p>{% trans -%}
If you are running 0.7.5 or later, your router should detect the
new release. To upgrade simply click the 'Download Update' button on your router console
when it appears.
{%- endtrans %}</p>
<div class="warning">
<p>{% trans -%}
Due to a bug in release 0.7.6, those whose first I2P installation was that version
and have not upgraded manually
may get a "downloaded version is not greater than current version" error,
and should use the manual update method below.
{%- endtrans %}</p>
</div>
<div class="warning">
<p>{% trans blogpost=get_url('blog_post', slug='2009/06/29/0.7.5-Release') -%}
If you are running 0.7.4 or earlier, please see
<a href="{{ blogpost }}">the 0.7.5 release notes</a>
for important information about how to configure your router to automatically
receive the release.
{%- endtrans %}</p>
</div>
<div class="warning">
<p>{% trans instructions=site_url('misc/upgrade-0.6.1.30') -%}
If you are running 0.6.1.30 or earlier, please see
<a href="{{ instructions }}">instructions</a>
for important information about how to configure your router to automatically
receive the release.
{%- endtrans %}</p>
<ol>
<li>
{% trans instructions=site_url('misc/upgrade-0.6.1.30') -%}
If you have reconfigured your router following the <a href="{{ instructions }}">instructions</a>, you should see a link on your
<a href="http://localhost:7657/index.jsp">router console</a> allowing
you to download and install the new release by just clicking on that
link.
{%- endtrans %}
</li>
<li>
{% trans -%}
Alternately, you can use the manual method specified below.
{%- endtrans %}
</li>
</ol>
</div>
</div>
</div>
<div class="package">
<h1>{{ _('Manual updates') }}</h1>
<div class="file">
<a href="{{ url_for('downloads_redirect', version=ver(), protocol=def_mirror.protocol, domain=def_mirror.domain, file=ver('i2pupdate_%s.zip')) }}">i2pupdate_{{ ver() }}.zip</a> ({{ def_mirror.org }})
(<a href="{{ get_url('downloads_select', version=ver(), file=ver('i2pupdate_%s.zip')) }}">{{ _('select alternate link') }}</a>)
<div class="sig">
(SHA256 <code>{{ i2pupdate_sig }}</code>
<a href="{{ url_for('downloads_redirect', version=ver(), protocol=def_mirror.protocol, domain=def_mirror.domain, file=ver('i2pupdate_%s.zip.sig')) }}">sig</a>)
</div>
</div>
<div class="details">
<ol>
<li>
{% trans -%}
Download that file to your I2P
installation directory and <b>rename as i2pupdate.zip</b>.
(alternately, you can get the source as above and run "ant updater", then copy the
resulting i2pupdate.zip to your I2P installation directory). You do
NOT need to unzip that file.
{%- endtrans %}
</li>
<li>
{% trans -%}
Click <a href="http://localhost:7657/configservice.jsp">"Restart"</a>
{%- endtrans %}
</li>
<li>
{% trans -%}
Grab a cup of coffee and come back in 11 minutes
{%- endtrans %}
</li>
</ol>
</div>
</div>
{% trans signingkey=site_url('get-involved/develop/release-signing-key') -%}
The file is signed by zzz,
<a href="{{ signingkey }}">whose key is here</a>.
{%- endtrans %}
<h3>{{ _('Previous Releases') }}</h3>
{% trans echelon=i2pconv('echelon.i2p') -%}
Previous releases are available on <a href="http://code.google.com/p/i2p/downloads/list?can=1">Google Code</a>
and <a href="https://launchpad.net/i2p/trunk">Launchpad</a>
and within the I2P network on <a href="http://{{ echelon }}/">{{ echelon }}</a>.
{%- endtrans %}
{% endblock %}

View File

@@ -0,0 +1,6 @@
{"protocol": "http", "domain": "i2p.googlecode.com", "path": "/files/%(file)s", "org": "Google Code", "org_url": "http://code.google.com", "country": "us"}
{"protocol": "https", "domain": "i2p.googlecode.com", "path": "/files/%(file)s", "org": "Google Code", "org_url": "https://code.google.com", "country": "us"}
{"protocol": "https", "domain": "launchpad.net", "path": "/i2p/trunk/%(version)s/+download/%(file)s", "org": "Launchpad", "org_url": "https://launchpad.net", "country": "us"}
{"protocol": "http", "domain": "a.mirror.geti2p.net", "path": "/releases/%(version)s/%(file)s", "org": "welterde", "country": "de"}
{"protocol": "http", "domain": "download.i2p2.no", "path": "/releases/%(version)s/%(file)s", "org": "meeh", "country": "no"}
{"protocol": "https", "domain": "googledrive.com", "path": "/host/0B4jHEq5G7_EPWV9UeERwdGplZXc/%(version)s/%(file)s", "org": "Google Drive", "country": "us"}

View File

@@ -0,0 +1,17 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Mirror selection') }}{% endblock %}
{% block content %}
<h1>{{ _('Mirror selection') }}</h1>
<h2>{{ _('File:') }} /{{ file }}</h2>
{% for protocol in mirrors -%}
<div class="protocol">
<h3>{{ protocol.name | upper }}</h3>
<ul>
<li><a href="{{ url_for('downloads_redirect', version=version, protocol=protocol.name, file=file) }}">{{ _('Any mirror') }}</a></li>
{% for domain, mirror in protocol.mirrors.items() -%}
<li><img src="{{ url_for('static', filename='images/flags/'+mirror.country+'.png') }}" />&nbsp;{% if mirror.org_url %}<a href="{{ mirror.org_url }}">{% endif %}{{ mirror.org }}{% if mirror.org_url %}</a>{% endif %} <a href="{{ url_for('downloads_redirect', version=version, protocol=protocol.name, domain=domain, file=file) }}">[{{ _('Download') }}]</a> <a href="{{ url_for('downloads_redirect', version=version, protocol=protocol.name, domain=domain, file=file+'.sig') }}">[sig]</a></li>
{%- endfor %}
</ul>
</div>
{%- endfor %}
{% endblock %}

View File

@@ -0,0 +1,38 @@
{% extends "global/layout.html" %}
{% block content %}
<!-- {% block donatename %}{% endblock %} -->
<div id="bounty">
<div class="details">
{% block bountydetails %}{% endblock %}
</div>
<div class="judge">
{% block bountyjudge %}{% endblock %}
</div>
{% block bountynotesouter %}
<div class="notes">
Note:
<ul>
{% block bountynotes %}
<li>{% trans -%}
To claim the bounty the author must not be paid by other organizations
or teams for this work (e.g. GSoC students are not valid).
{%- endtrans %}</li>
{% endblock %}
</ul>
</div>
{% endblock %}
<div class="donate">
<p><i>{% trans donate=site_url('get-involved/donate'), donatename=self.donatename() -%}
Bounty amounts may be increased by further donations. Do
you think these are important? <a href="{{ donate }}">Add in your donation</a>,
marking the amount for the {{ donatename }} bounty!
{%- endtrans %}</i></p>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,13 @@
{% extends "global/layout.html" %}
{% block title -%}
{% trans -%}
Not found
{%- endtrans %}
{%- endblock %}
{% block content %}
{% trans -%}
Yep... the resource, you were searching for, is named differently, doesn't exist or was removed.
{%- endtrans %}
{% endblock %}

View File

@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% trans %}Server error{% endtrans %} - I2P</title>
<link rel="stylesheet" type="text/css" href="/_static/styles/duck.css" title="duck" />
<link rel="shortcut icon" type="image/x-icon" href="/_static/favicon.ico" />
<meta name="robots" content="NOODP" />
</head>
<body>
<div id="branding">
<h1 id="logo"><a href="/"><img src="/_static/images/logo_medium.png" alt="I2P" /></a></h1>
<div class="title">{% trans %}500 Server error{% endtrans %}</div>
</div>
<div id="content">
<div class="inner">
{% trans %}Umm... the server encountered some sort of error.{% endtrans %}
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,32 @@
<div class='aside first'>
<h1>{{ _('Mirrors') }}</h1>
<ul>
<li><a rel="nofollow" href="http://i2pproject.net/">http://i2pproject.net</a></li>
<li><a rel="nofollow" href="http://i2p-projekt.de/">http://i2p-projekt.de</a></li>
</ul>
</div>
<div class='aside second'>
<h1>{{ _('Secure') }}</h1>
<ul>
<li><a rel="nofollow" href="https://geti2p.net/">https://geti2p.net</a></li>
<li><a rel="nofollow" href="https://www.i2p2.de/">https://www.i2p2.de</a></li>
</ul>
</div>
<div class='aside third'>
<h1>{{ _('Misc.') }}</h1>
<ul>
<li><a href="http://syndie.i2p2.de/">Syndie</a></li>
<li><a href="{{ site_url('links') }}">{{ _('Links') }}</a></li>
<li><a href="{{ site_url('impressum') }}">{{ _('Impressum') }}</a></li>
</ul>
</div>
<div class='aside fourth'>
<h1>{{ _('T-Shirts!') }}</h1>
<ul>
<li><a href="http://www.getdigital.de/products/I2P_Fanshirt/lng/en">{{ _('Europe') }}</a></li>
<li><a href="https://i2pshop.spreadshirt.com/">{{ _('USA') }}</a></li>
</ul>
</div>
<div class='aside fifth'>
<a class='button' href="{{ site_url('get-involved/donate') }}">{{ _('Donate') }}</a>
</div>

View File

@@ -0,0 +1,9 @@
<ul class="languages">
<li><a href="{{ change_lang('en') }}" rel="alternate" hreflang="en"><div class="menuitem"><img src="{{ get_flag('en') }}" alt="English" /></div></a></li>
<li><a href="{{ change_lang('es') }}" rel="alternate" hreflang="es"><div class="menuitem"><img src="{{ get_flag('es') }}" alt="Castellano" /></div></a></li>
<li><a href="{{ change_lang('zh_CN') }}" rel="alternate" hreflang="zh_CN"><div class="menuitem"><img src="{{ get_flag('zh_CN') }}" alt="Chinese" /></div></a></li>
<li><a href="{{ change_lang('de') }}" rel="alternate" hreflang="de"><div class="menuitem"><img src="{{ get_flag('de') }}" alt="Deutsch" /></div></a></li>
<li><a href="{{ change_lang('fr') }}" rel="alternate" hreflang="fr"><div class="menuitem"><img src="{{ get_flag('fr') }}" alt="Français" /></div></a></li>
<li><a href="{{ change_lang('pt') }}" rel="alternate" hreflang="pt"><div class="menuitem"><img src="{{ get_flag('pt') }}" alt="Portugese" /></div></a></li>
<li><a href="{{ change_lang('sv_SE') }}" rel="alternate" hreflang="sv_SE"><div class="menuitem"><img src="{{ get_flag('sv_SE') }}" alt="Svenska" /></div></a></li>
</ul>

View File

@@ -0,0 +1,14 @@
<ul class="languages">
<li><a href="{{ change_lang('en') }}" rel="alternate" hreflang="en"><div class="menuitem"><img src="{{ get_flag('en') }}" alt="English" /></div></a></li>
<li><a href="{{ change_lang('es') }}" rel="alternate" hreflang="es"><div class="menuitem"><img src="{{ get_flag('es') }}" alt="Castellano" /></div></a></li>
<li><a href="{{ change_lang('zh') }}" rel="alternate" hreflang="zh"><div class="menuitem"><img src="{{ get_flag('zh') }}" alt="Chinese" /></div></a></li>
<li><a href="{{ change_lang('de') }}" rel="alternate" hreflang="de"><div class="menuitem"><img src="{{ get_flag('de') }}" alt="Deutsch" /></div></a></li>
<li><a href="{{ change_lang('fr') }}" rel="alternate" hreflang="fr"><div class="menuitem"><img src="{{ get_flag('fr') }}" alt="Français" /></div></a></li>
<li><a href="{{ change_lang('it') }}" rel="alternate" hreflang="it"><div class="menuitem"><img src="{{ get_flag('it') }}" alt="Italiano" /></div></a></li>
<li><a href="{{ change_lang('nl') }}" rel="alternate" hreflang="nl"><div class="menuitem"><img src="{{ get_flag('nl') }}" alt="Nederlands" /></div></a></li>
<li><a href="{{ change_lang('ru') }}" rel="alternate" hreflang="ru"><div class="menuitem"><img src="{{ get_flag('ru') }}" alt="Russian" /></div></a></li>
<li><a href="{{ change_lang('sv') }}" rel="alternate" hreflang="sv"><div class="menuitem"><img src="{{ get_flag('sv') }}" alt="Svenska" /></div></a></li>
<li><a href="{{ change_lang('cs') }}" rel="alternate" hreflang="cs"><div class="menuitem"><img src="{{ get_flag('cs') }}" alt="Czech" /></div></a></li>
<li><a href="{{ change_lang('ar') }}" rel="alternate" hreflang="ar"><div class="menuitem"><img src="{{ get_flag('ar') }}" alt="Arabic" /></div></a></li>
<li><a href="{{ change_lang('el') }}" rel="alternate" hreflang="el"><div class="menuitem"><img src="{{ get_flag('el') }}" alt="Greek" /></div></a></li>
</ul>

View File

@@ -0,0 +1,79 @@
{%- from "global/macros" import change_lang with context -%}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title_outer %}{% block title %}{% endblock %} - I2P{% endblock %}</title>
{%- if self.metadesc() %}
<meta name="description" content="{% block metadesc %}{% endblock %}">
{%- endif %}
<link rel="canonical" href="{{ canonical() }}" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=2.0, user-scalable=yes" />
{% if g.exttheme %}<link rel="stylesheet" type="text/css" href="{{ g.exttheme }}" title="External theme" />{% else -%}
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles/' + g.theme + '/default.css') }}" media="screen, handheld, print, projection" />
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles/' + g.theme + '/mobile.css') }}" media="screen and (min-device-width:320px) and (max-width:767px)" />
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles/' + g.theme + '/desktop.css') }}" title="{{ g.theme }}" media="screen and (min-device-width:768px) and (min-width:768px), print, projection" />
<!--[if IEMobile]>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles/' + g.theme + '/mobile.css') }}" media="screen" />
<![endif]-->
<!--[if lt IE 9]>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles/' + g.theme + '/desktop.css') }}" title="{{ g.theme }}" media="all" />
<![endif]-->
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles/' + g.theme + '/syntax.css') }}" media="screen, handheld, print, projection" />
{%- endif %}
<link rel="shortcut icon" type="image/x-icon" href="{{ url_for('static', filename='favicon.ico') }}" />
<meta name="robots" content="NOODP" />
{%- block headextra %}{% endblock %}
</head>
<body>
<div class="hide"><a href="#content" title="Skip navigation" accesskey="2">{{ _('Skip navigation') }}</a></div>
<header>
<div id="topbar">
<a id="logo" href="{{ site_url() }}"><img src="{{ url_for('static', filename=logo_url()) }}" alt="{{ _('I2P Logo') }}" title="{{ _('The Invisible Internet Project') }} (I2P)" /></a>
<div class="title">
<h1>{{ self.title() }}</h1>
<div class="lang">
{% include "global/lang.html" %}
</div>
</div>
</div>
<nav class="navigation">
{% include "global/nav.html" %}
</nav>
</header>
<div class="container-fluid{% if not self.content() %} well{% endif %}">
<div id="content">
{% block content_outer %}
<article class="inner">
{% if self.lastupdated() or self.accuratefor() -%}
<div class="lastupdated">
<!--
{% block lastupdated %}{% endblock %}
{% block accuratefor %}{% endblock %}
-->
{% if self.lastupdated() and self.accuratefor() -%}
{% trans lastupdated=self.lastupdated(), accuratefor=self.accuratefor() -%}
This page was last updated in {{ lastupdated}} and is accurate for router version {{ accuratefor }}.
{%- endtrans %}
{%- else %}{% if self.lastupdated() -%}
{% trans lastupdated=self.lastupdated() -%}
This page was last updated in {{ lastupdated}}.
{%- endtrans %}
{%- else %}{% if self.accuratefor() -%}
{% trans accuratefor=self.accuratefor() -%}
This page is accurate for router version {{ accuratefor }}.
{%- endtrans %}
{%- endif %}{% endif %}{% endif %}
</div>
{%- endif %}
{% block content %}{% endblock %}
</article>
{% endblock %}
</div>
<footer id="global-footer">
{% include "global/footer.html" %}
</footer>
</div>
</body>
</html>

View File

@@ -0,0 +1,45 @@
{%- macro change_lang(lang) -%}
{%- if request.endpoint == 'site_show' -%}{{ url_for('site_show', lang=lang, page=page) }}
{%- elif request.endpoint == 'blog_index' -%}
{%- if category -%}{{ url_for('blog_index', lang=lang, category=category) }}
{%- else -%}{{ url_for('blog_index', lang=lang) }}
{%- endif -%}
{%- elif request.endpoint == 'blog_post' -%}{{ url_for('blog_post', lang=lang, slug=slug) }}
{%- elif request.endpoint == 'meetings_show' -%}{{ url_for('meetings_show', lang=lang, id=id) }}
{%- elif request.endpoint == 'downloads_debian' -%}{{ url_for('downloads_debian', lang=lang) }}
{%- elif request.endpoint == 'downloads_select' -%}{{ url_for('downloads_select', lang=lang, version=version, file=file) }}
{%- elif request.endpoint == 'downloads_redirect' -%}{{ url_for('site_show', lang=lang) }}
{%- elif request.endpoint -%}{{ url_for(request.endpoint, lang=lang) }}
{%- else -%}{{ url_for('site_show', lang=lang) }}
{%- endif -%}
{%- endmacro -%}
{%- macro render_pagination(pagination) %}
<div class="pagination">
{%- if pagination.has_prev %}
<a href="{{ url_for_other_page(pagination.page - 1)
}}">&laquo; {{ _('Previous') }}</a>
{%- endif %}
{%- for page in pagination.iter_pages() %}
{%- if page %}
{%- if page != pagination.page %}
<a href="{{ url_for_other_page(page) }}">{{ page }}</a>
{%- else %}
<strong>{{ page }}</strong>
{%- endif %}
{%- else %}
<span class="ellipsis">…</span>
{%- endif %}
{%- endfor %}
{%- if pagination.has_next %}
<a href="{{ url_for_other_page(pagination.page + 1)
}}">{{ _('Next') }} &raquo;</a>
{%- endif %}
</div>
{%- endmacro -%}
{%- macro render_categories(categories) -%}
{%- if categories and categories|length -%}
{{ _('Posted in') }} {% for category in categories %}<a href="{{ get_url('blog_index', category=category) }}">{{ category }}</a>{% if not loop.last %}, {% endif %}{% endfor %}
{%- endif %}
{%- endmacro %}

View File

@@ -0,0 +1,144 @@
<div id="cssmenu">
<ul>
<li><a href="{{ get_url('downloads_list') }}"><div class="menuitem"><span>{{ _('Download') }}</span></div></a></li>
<li class="has-sub"><div class="menuitem"><span>{{ _('About') }}</span></div>
<ul>
<li><a href="{{ site_url('about/intro') }}"><div class="menuitem"><span>{{ _('Introduction to I2P') }}</span></div></a></li>
<li class="has-sub"><div class="menuitem"><span>{{ _('Comparisons') }}</span></div>
<ul>
<li><a href="{{ site_url('comparison') }}"><div class="menuitem"><span>{{ _('Overview of comparisons') }}</span></div></a></li>
<li><a href="{{ site_url('comparison/tor') }}"><div class="menuitem"><span>Tor</span></div></a></li>
<li><a href="{{ site_url('comparison/freenet') }}"><div class="menuitem"><span>Freenet</span></div></a></li>
{#<li><a href="{{ site_url('comparison/gnunet') }}"><div class="menuitem"><span>GNUnet</span></div></a></li> #}
<li><a href="{{ site_url('comparison/other-networks') }}"><div class="menuitem"><span>{{ _('Other anonymous networks') }}</span></div></a></li>
</ul>
</li>
<li class="has-sub"><div class="menuitem"><span>{{ _('Documentation') }}</span></div>
<ul>
<li><a href="{{ site_url('docs') }}"><div class="menuitem"><span>{{ _('Documentation index') }}</span></div></a></li>
<li class="has-sub"><div class="menuitem"><span>{{ _('How does it work?') }}</span></div>
<ul>
<li><a href="{{ site_url('docs/how/intro') }}"><div class="menuitem"><span>{{ _('Gentle intro') }}</span></div></a></li>
<li><a href="{{ site_url('docs/how/tech-intro') }}"><div class="menuitem"><span>{{ _('Tech intro') }}</span></div></a></li>
<li><a href="{{ site_url('docs/how/threat-model') }}"><div class="menuitem"><span>{{ _('Threat model') }}</span></div></a></li>
<li><a href="{{ site_url('docs/how/garlic-routing') }}"><div class="menuitem"><span>{{ _('Garlic routing') }}</span></div></a></li>
<li><a href="{{ site_url('docs/how/network-database') }}"><div class="menuitem"><span>{{ _('Network database') }}</span></div></a></li>
<li><a href="{{ site_url('docs/how/tunnel-routing') }}"><div class="menuitem"><span>{{ _('Tunnel routing') }}</span></div></a></li>
<li><a href="{{ site_url('docs/how/peer-selection') }}"><div class="menuitem"><span>{{ _('Peer selection') }}</span></div></a></li>
<li><a href="{{ site_url('docs/how/cryptography') }}"><div class="menuitem"><span>{{ _('Cryptography') }}</span></div></a></li>
<li><a href="{{ site_url('docs/how/elgamal-aes') }}"><div class="menuitem"><span>{{ _('ElGamal/AES+SessionTags') }}</span></div></a></li>
</ul>
</li>
<li class="has-sub"><div class="menuitem"><span>{{ _('Applications') }}</span></div>
<ul>
<li><a href="{{ site_url('docs/applications/supported') }}"><div class="menuitem"><span>{{ _('Supported applications') }}</span></div></a></li>
<li><a href="{{ site_url('docs/applications/bittorrent') }}"><div class="menuitem"><span>{{ _('Bittorrent') }}</span></div></a></li>
</ul>
</li>
<li class="has-sub"><div class="menuitem"><span>{{ _('API') }}</span></div>
<ul>
<li><a href="{{ site_url('docs/api/i2ptunnel') }}"><div class="menuitem"><span>I2PTunnel</span></div></a></li>
<li><a href="{{ site_url('docs/api/socks') }}"><div class="menuitem"><span>SOCKS</span></div></a></li>
<li><a href="{{ site_url('docs/api/sam') }}"><div class="menuitem"><span>SAM v1</span></div></a></li>
<li><a href="{{ site_url('docs/api/samv2') }}"><div class="menuitem"><span>SAM v2</span></div></a></li>
<li><a href="{{ site_url('docs/api/samv3') }}"><div class="menuitem"><span>SAM v3</span></div></a></li>
<li><a href="{{ site_url('docs/api/bob') }}"><div class="menuitem"><span>BOB</span></div></a></li>
<li><a href="{{ site_url('docs/api/streaming') }}"><div class="menuitem"><span>{{ _('Streaming library') }}</span></div></a></li>
<li><a href="{{ site_url('docs/api/ministreaming') }}"><div class="menuitem"><span>{{ _('Ministreaming library') }}</span></div></a></li>
<li><a href="{{ site_url('docs/api/datagrams') }}"><div class="menuitem"><span>{{ _('Datagrams') }}</span></div></a></li>
<li><a href="{{ site_url('docs/api/i2pcontrol') }}"><div class="menuitem"><span>I2PControl</span></div></a></li>
</ul>
</li>
<li class="has-sub"><div class="menuitem"><span>{{ _('Protocols') }}</span></div>
<ul>
<li><a href="{{ site_url('docs/protocol') }}"><div class="menuitem"><span>{{ _('Protocol stack') }}</span></div></a></li>
<li><a href="{{ site_url('docs/protocol/i2cp') }}"><div class="menuitem"><span>I2CP</span></div></a></li>
<li><a href="{{ site_url('docs/protocol/i2np') }}"><div class="menuitem"><span>I2NP</span></div></a></li>
</ul>
</li>
<li class="has-sub"><div class="menuitem"><span>{{ _('Transports') }}</span></div>
<ul>
<li><a href="{{ site_url('docs/transport') }}"><div class="menuitem"><span>{{ _('Transport layer overview') }}</span></div></a></li>
<li><a href="{{ site_url('docs/transport/ntcp') }}"><div class="menuitem"><span>NTCP</span></div></a></li>
<li><a href="{{ site_url('docs/transport/ssu') }}"><div class="menuitem"><span>SSU</span></div></a></li>
</ul>
</li>
<li class="has-sub"><div class="menuitem"><span>{{ _('Specifications') }}</span></div>
<ul>
<li><a href="{{ site_url('docs/spec/blockfile') }}"><div class="menuitem"><span>{{ _('Blockfile') }}</span></div></a></li>
<li><a href="{{ site_url('docs/spec/common-structures') }}"><div class="menuitem"><span>{{ _('Common structures') }}</span></div></a></li>
<li><a href="{{ site_url('docs/spec/configuration') }}"><div class="menuitem"><span>{{ _('Configuration files') }}</span></div></a></li>
<li><a href="{{ site_url('docs/spec/datagrams') }}"><div class="menuitem"><span>{{ _('Datagrams') }}</span></div></a></li>
<li><a href="{{ site_url('docs/spec/geoip') }}"><div class="menuitem"><span>{{ _('GeoIP files') }}</span></div></a></li>
<li><a href="{{ site_url('docs/spec/i2cp') }}"><div class="menuitem"><span>I2CP</span></div></a></li>
<li><a href="{{ site_url('docs/spec/i2np') }}"><div class="menuitem"><span>I2NP</span></div></a></li>
<li><a href="{{ site_url('docs/spec/plugin') }}"><div class="menuitem"><span>{{ _('Plugins') }}</span></div></a></li>
<li><a href="{{ site_url('docs/spec/ssu') }}"><div class="menuitem"><span>SSU</span></div></a></li>
<li><a href="{{ site_url('docs/spec/streaming') }}"><div class="menuitem"><span>{{ _('Streaming library') }}</span></div></a></li>
<li><a href="{{ site_url('docs/spec/tunnel-creation') }}"><div class="menuitem"><span>{{ _('Tunnel creation') }}</span></div></a></li>
<li><a href="{{ site_url('docs/spec/tunnel-message') }}"><div class="menuitem"><span>{{ _('Tunnel messages') }}</span></div></a></li>
<li><a href="{{ site_url('docs/spec/updates') }}"><div class="menuitem"><span>{{ _('Software updates') }}</span></div></a></li>
</ul>
</li>
<li class="has-sub"><div class="menuitem"><span>{{ _('Tunnels') }}</span></div>
<ul>
<li><a href="{{ site_url('docs/tunnels/implementation') }}"><div class="menuitem"><span>{{ _('Tunnel implementation') }}</span></div></a></li>
<li><a href="{{ site_url('docs/tunnels/unidirectional') }}"><div class="menuitem"><span>{{ _('Unidirectional tunnels') }}</span></div></a></li>
<li><a href="{{ site_url('docs/tunnels/old-implementation') }}"><div class="menuitem"><span>{{ _('Old implementation') }}</span></div></a></li>
</ul>
</li>
<li><a href="{{ site_url('docs/naming') }}"><div class="menuitem"><span>{{ _('Naming and addressbook') }}</span></div></a></li>
<li><a href="{{ site_url('docs/plugins') }}"><div class="menuitem"><span>{{ _('Plugins') }}</span></div></a></li>
</ul>
</li>
<li><a href="{{ site_url('about/team') }}"><div class="menuitem"><span>{{ _('Team') }}</span></div></a></li>
<li><a href="{{ get_url('blog_index') }}"><div class="menuitem"><span>{{ _('Blog') }}</span></div></a></li>
<li><a href="{{ site_url('about/hall-of-fame') }}"><div class="menuitem"><span>{{ _('Hall of Fame') }}</span></div></a></li>
<li><a href="{{ get_url('papers_list') }}"><div class="menuitem"><span>{{ _('Academic papers and peer review') }}</span></div></a></li>
<li><a href="{{ site_url('about/media') }}"><div class="menuitem"><span>{{ _('Presentations, tutorials and articles') }}</span></div></a></li>
<li><a href="{{ site_url('contact') }}"><div class="menuitem"><span>{{ _('Contact us') }}</span></div></a></li>
</ul>
</li>
<li class="has-sub"><div class="menuitem"><span>{{ _('Help') }}</span></div>
<ul>
<li><a href="{{ site_url('faq') }}"><div class="menuitem"><span>{{ _('FAQ') }}</span></div></a></li>
<li><a href="{{ site_url('about/browser-config') }}"><div class="menuitem"><span>{{ _('How to browse I2P') }}</span></div></a></li>
<li><a href="{{ site_url('about/glossary') }}"><div class="menuitem"><span>{{ _('Glossary') }}</span></div></a></li>
<li><a href="{{ site_url('about/performance') }}"><div class="menuitem"><span>{{ _('Performance') }}</span></div></a></li>
<li><a href="http://{{ i2pconv('forum.i2p') }}/"><div class="menuitem"><span>{{ _('Forums') }}</span></div></a></li>
</ul>
</li>
<li class="has-sub"><div class="menuitem"><span>{{ _('Volunteer') }}</span></div>
<ul>
<li><a href="{{ site_url('get-involved') }}"><div class="menuitem"><span>{{ _('Get involved!') }}</span></div></a></li>
<li class="has-sub"><div class="menuitem"><span>{{ _('Develop') }}</span></div>
<ul>
<li><a href="{{ site_url('get-involved/develop/applications') }}"><div class="menuitem"><span>{{ _('Applications') }}</span></div></a></li>
<li><a href="{{ site_url('get-involved/develop/licenses') }}"><div class="menuitem"><span>{{ _('Licenses') }}</span></div></a></li>
<li><a href="{{ site_url('get-involved/develop/release-signing-key') }}"><div class="menuitem"><span>{{ _('Release signing keys') }}</span></div></a></li>
<li><a href="{{ site_url('get-involved/develop/signed-keys') }}"><div class="menuitem"><span>{{ _('Signed keys') }}</span></div></a></li>
<li><a href="{{ site_url('get-involved/develop/developers-keys') }}"><div class="menuitem"><span>{{ _('Developers keys') }}</span></div></a></li>
<li><a href="http://{{ i2pconv('trac.i2p2.i2p') }}/"><div class="menuitem"><span>{{ _('Bug tracker') }}</span></div></a></li>
</ul>
</li>
<li><a href="{{ site_url('research') }}"><div class="menuitem"><span>{{ _('Academic research') }}</span></div></a></li>
<li class="has-sub"><div class="menuitem"><span>{{ _('Guides') }}</span></div>
<ul>
<li><a href="{{ site_url('get-involved/guides/new-developers') }}"><div class="menuitem"><span>{{ _('New developers') }}</span></div></a></li>
<li><a href="{{ site_url('get-involved/guides/ides') }}"><div class="menuitem"><span>{{ _('Using an IDE with I2P') }}</span></div></a></li>
<li><a href="{{ site_url('get-involved/guides/dev-guidelines') }}"><div class="menuitem"><span>{{ _('Developer guidelines and coding style') }}</span></div></a></li>
<li><a href="{{ site_url('get-involved/guides/monotone') }}"><div class="menuitem"><span>{{ _('Monotone') }}</span></div></a></li>
<li><a href="{{ site_url('get-involved/guides/new-translators') }}"><div class="menuitem"><span>{{ _('New translators') }}</span></div></a></li>
</ul>
</li>
<li><a href="{{ site_url('get-involved/bounties') }}"><div class="menuitem"><span>{{ _('Bounties') }}</span></div></a></li>
<li><a href="{{ get_url('meetings_index') }}"><div class="menuitem"><span>{{ _('Meetings') }}</span></div></a></li>
<li><a href="{{ site_url('get-involved/roadmap') }}"><div class="menuitem"><span>{{ _('Roadmap') }}</span></div></a></li>
<li><a href="{{ site_url('get-involved/todo') }}"><div class="menuitem"><span>{{ _('Task list') }}</span></div></a></li>
</ul>
</li>
<li class="has-sub right"><div class="menuitem"><span><img src="{{ get_flag() }}" /> {{ _('Language') }}</span></div>
{% include "global/lang.html" %}
</li>
</ul>
</div>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
{%- for url in urls %}
<url>
<loc>{{ url_root }}{{ g.lang }}{{ url.path }}</loc>
{%- for altlang in langs %}
<xhtml:link
rel="alternate"
hreflang="{{ altlang }}"
href="{{ url_root }}{{ altlang }}{{ url.path }}"
/>
{%- endfor %}
</url>
{%- endfor %}
</urlset>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{%- for lang in langs %}
<sitemap>
<loc>{{ url_root }}{{ lang }}/sitemap.xml</loc>
</sitemap>
{%- endfor %}
</sitemapindex>

View File

@@ -0,0 +1,82 @@
<code>
<pre>
-- This implements a list of trusted signers.
-- It is used on checkout and update.
-- It is not used for repo sync/push/pull.
-- If you do not include this function in ~/.monotone/monotonerc, the
-- default is to trust everybody, which is probably a bad thing
-- in an anonymous network.
-- Update the list below to reflect the signers YOU trust.
--
-- ref: http://www.monotone.ca/docs/Trust-Evaluation-Hooks.html
-- Modified to use key identities instead of key names, since
-- monotone allows duplicate key names, so any key-name-based
-- trust system is insecure.
--
-- Modified from intersection() to use key identities instead of key names, since
-- monotone allows duplicate key names.
--
-- a: table of ID structures (see above)
-- b: table of hex IDs
--
function keyintersection(a,b)
local s={}
local t={}
for k,v in pairs(a) do s[v.id] = 1 end
for k,v in pairs(b) do if s[v] ~= nil then table.insert(t,v) end end
return t
end
--
-- from mtn source project.hh and lua_hooks.cc:
-- signers is a table of integers (starting with 1) to the following ID structure:
-- struct ID
-- {
-- id: (key_id in key_identity_info) hex of revision id hash;
-- given_name: (given_name in key_identity_info) // name given when creating the key
-- name: (official_name in key_identity_info) // name returned by hooks or (once implented) policy
-- };
-- id: hex of revision id hash;
-- name: cert_name
-- val: cert_value
--
function get_revision_cert_trust(signers, id, name, val)
local trusted_signers = {
"5bc185cfd680eb512fdb9626b9fb4298e136215e", -- BlubMail@mail.i2p
"f6706ac205e6b5d7a7e3ea4244ab0ef497f0a099", -- cervantes@mail.i2p
"690f278ff6c6157cbaf23b0d602b6d6dcf368313", -- complication@mail.i2p
"eb4ac08d5ddbb2bd73889f86c1211424025a6f07", -- dev@robertfoss.se
"aae785027c240ebbb0a883fd8ebcf8d6ecee4104", -- dev@welterde.de
"5f75b8f0769770edc3267c21ddc9a00ddae31394", -- digit@mail.i2p
"4ebaace9973913416af92ee8d0fb93d64753df4c", -- dream@mail.i2p
"7e498ae94c9c322404adfc61b16bed388095906b", -- duck@mail.i2p
"56c0064a8638fe180ed2f2726d6e2e404c788d3d", -- echelon@mail.i2p
"0e4e7ebebafbdf4cdacc45a47ba155b1215d8e8b", -- forget@mail.i2p
"f332b3d3b11b2efdae220cea75b9d5ba9ec3b52d", -- hamada@mail.i2p
"e246444b4fe69ba599e13403c4ab931066de902f", -- hiddenz@mail.i2p
"a61146ee69ddb9fcf3b82b19a62b8114b60d367e", -- HungryHobo@mail.i2p
"4844b1fd45f5a68744fa28d2f3e3b61a3cf83b95", -- kytv@mail.i2p
"c9b970f5e8917eada663d4c6b22096617021c95c", -- m1xxy@mail.i2p
"3be64909d6ab7c3d7afe16f20f24e672708b576b", -- magma@mail.i2p
"2977a6f4e11819a3f928783175caadc0071fc4de", -- mathiasdm@mail.i2p
"de9d196e8057e1629178edbfa1ed754c648d7340", -- meeh@mail.i2p
"2a0bba98558d7a9d7e4b1bd807789601252c0024", -- mkvore-commit@mail.i2p
"6ade4b7a9a6425194f482ab351950e4230dbbc85", -- neutron@mail.i2p
"bc74b49fd8a20513b2745a3d13414b7e9818dd18", -- Oldaris@mail.i2p
"3fb8d1ee1e82981a8076ddbcbf4d18f372b8bba7", -- privateer@mail.i2p
"e3815f0c985663182534fbd7d6a2bf93204a0bd0", -- russiansponsor@mail.i2p
"1092773c40f5813b9179d52a8ab7b499b9554da3", -- sponge@mail.i2p
"01265f0c817b24548478341fb75e672720a78b21", -- str4d@mail.i2p
"38fe2aa37e1eb9a300a2061ef153265c48031c6b", -- walking@mail.i2p
"a0eb78d437efad120dd9edcd776a327ec2c2adde", -- zab@mail.i2p
"2158706490e62a17c8140b6e9eabca965b681bc7", -- zab2@mail.i2p
"896e399990704373125f782ae2ee19b6611ac612" -- zzz@mail.i2p
}
local t = keyintersection(signers, trusted_signers)
if t == nil then return false end
if table.getn(t) >= 1 then return true end
return false
end
</pre>
</code>

View File

@@ -0,0 +1,28 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Meetings') }}{% endblock %}
{% block headextra %}
<link href="{{ get_url('meetings_atom') }}" type="application/atom+xml" rel="alternate" title="{{ _('I2P Meetings ATOM Feed') }}" />
{%- endblock %}
{% block content %}
<h1>{{ _('Logs of past I2P meetings') }}</h1>
<p>{% trans -%}
Meetings are currently on hold until a more suitable time can be chosen.
{%- endtrans %}</p>
<p>{% trans blogindex=get_url('blog_index') -%}
If you have something to discuss, please find the developers on IRC in #i2p-dev.
<a href="{{ blogindex }}">Status updates</a> from developers are also available.
{%- endtrans %}</p>
<div class="underline"></div>
<ul class="infolist">
{%- macro meeting_url(m_id) -%}{{ get_url('meetings_show', id=m_id) }}{%- endmacro %}
{% for meeting in meetings %}
<li><a href="{{ meeting_url(meeting['id']) }}">Meeting {{ meeting['id'] }}</a>{% if meeting['date'] %} - {{ meeting['date'].strftime("%B %d, %Y") }}{% endif %}</li>
{% endfor %}
</ul>
{%- from "global/macros" import render_pagination with context -%}
{{ render_pagination(pagination) | safe }}
{% endblock %}

View File

@@ -0,0 +1,15 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}I2P Development Meeting {{ id }}{% endtrans %}{% endblock %}
{% block content %}
{% autoescape false %}
{% if header %}
{{ header | restructuredtext }}
{% endif %}
{% endautoescape %}
<div class="irclog">
<h1>{{ _('Full IRC Log') }}</h1>
{% highlight lang='irc' %}
{{ log|escape }}
{% endhighlight %}
</div>
{% endblock %}

View File

@@ -0,0 +1,186 @@
%
%
% Magic fields:
%
% www_tags -- used to control which page groups the paper appears in.
% This is a space-separated list.
% www_section -- the topic used under 'topics.html'
% www_{ps|pdf|ps_gz|txt|html|abstract}_url -- link for text/abstract of
% an entry.
% www_important -- set for important entries
% www_remarks -- annotation for an entry
%% List of sections
@string{comm = "Anonymous communication"}
@string{traffic = "Traffic analysis"}
@string{pub = "Anonymous publication"}
@string{proofs = "Provable shuffles"}
@string{methods = "Formal methods"}
@string{nym = "Pseudonymity"}
@string{pir = "Private Information Retrieval"}
@string{economics = "Economics"}
@string{censorship = "Communications Censorship"}
@string{credentials = "E-Cash / Anonymous Credentials"}
@string{misc = "Misc"}
#
# Proposed new sections: application privacy, data anonymization, ...
#
@string{lncs = "Lecture Notes in Computer Science"}
@inproceedings{egger2013:practical-attacks,
title = {Practical Attacks Against the I2P Network},
author = {Christoph Egger and Johannes Schlumberger and Christopher Kruegel and Giovanni Vigna},
booktitle = {Proceedings of the 16th International Symposium on Research in Attacks, Intrusions and Defenses (RAID 2013)},
year = {2013},
month = {October},
www_pdf_url = {http://wwwcip.informatik.uni-erlangen.de/~spjsschl/i2p.pdf},
www_section = traffic,
}
%% hal-00744922, version 1
%% http://hal.inria.fr/hal-00744922
@inproceedings{timpanaro:hal-00744922,
hal_id = {hal-00744922},
url = {http://hal.inria.fr/hal-00744922},
title = {{Improving Content Availability in the I2P Anonymous File-Sharing Environment}},
author = {Timpanaro, Juan Pablo and Chrisment, Isabelle and Festor, Olivier},
abstract = {{Anonymous communication has gained more and more interest from Internet users as privacy and anonymity problems have emerged. Dedicated anonymous networks such as Freenet and I2P allow anonymous file-sharing among users. However, one major problem with anonymous file-sharing networks is that the available content is highly reduced, mostly with outdated files, and non-anonymous networks, such as the BitTorrent network, are still the major source of content: we show that in a 30-days period, 21648 new torrents were introduced in the BitTorrent community, whilst only 236 were introduced in the anonymous I2P network, for four different categories of content. Therefore, how can a user of these anonymous networks access this varied and non-anonymous content without compromising its anonymity? In this paper, we improve content availability in an anonymous environment by proposing the first internetwork model allowing anonymous users to access and share content in large public communities while remaining anonymous. We show that our approach can efficiently interconnect I2P users and public BitTorrent swarms without affecting their anonymity nor their performance. Our model is fully implemented and freely usable.}},
language = {English},
affiliation = {MADYNES - INRIA Nancy - Grand Est / LORIA},
booktitle = {{Proceedings of the 4th International Symposium on Cyberspace Safety and Security}},
publisher = {Springer},
pages = {77--92},
address = {Melbourne, Australia},
volume = {4},
audience = {international },
doi = {10.1007/978-3-642-35362-8 },
year = {2012},
month = Dec,
www_pdf_url = {http://hal.inria.fr/hal-00744922/PDF/Improving\_Content\_Availability\_in\_the\_I2P\_0AAnonymous\_File-Sharing\_Environment\_0A.pdf},
www_section = comm,
}
%% hal-00744919, version 1
%% http://hal.inria.fr/hal-00744919
@inproceedings{timpanaro:hal-00744919,
hal_id = {hal-00744919},
url = {http://hal.inria.fr/hal-00744919},
title = {{A Bird's Eye View on the I2P Anonymous File-sharing Environment}},
author = {Timpanaro, Juan Pablo and Chrisment, Isabelle and Festor, Olivier},
abstract = {{Anonymous communications have been gaining more and more interest from Internet users as privacy and anonymity problems have emerged. Among anonymous enabled services, anonymous file-sharing is one of the most active one and is increasingly growing. Large scale monitoring on these systems allows us to grasp how they behave, which type of data is shared among users, the overall behaviour in the system. But does large scale monitoring jeopardize the system anonymity? In this work we present the first large scale monitoring architecture and experiments on the I2P network, a low-latency message-oriented anonymous network. We characterize the file-sharing environment within I2P, and evaluate if this monitoring affects the anonymity provided by the network. We show that most activities within the network are file-sharing oriented, along with anonymous web-hosting. We assess the wide geographical location of nodes and network popularity. We also demonstrate that group-based profiling is feasible on this particular network.}},
keywords = {Large scale monitoring, I2P, Security risks, Anonymous file-sharing},
language = {English},
affiliation = {MADYNES - INRIA Nancy - Grand Est / LORIA},
booktitle = {{Proceedings of the 6th International Conference on Network and System Security}},
address = {Wu Yi Shan, China},
audience = {international },
year = {2012},
month = Nov,
www_pdf_url = {http://hal.inria.fr/hal-00744919/PDF/A\_Birda\_s\_Eye\_View\_on\_the\_I2P\_Anonymous\_0AFile-sharing\_Environment\_0A.pdf},
www_section = traffic,
}
@misc{ehlert2011:usability-comparison-i2p-tor,
title = {I2P Usability vs. Tor Usability A Bandwidth and Latency Comparison},
author = {Mathias Ehlert},
howpublished = {Seminar, Humboldt University of Berlin},
year = {2011},
month = {November},
www_pdf_url = {http://userpage.fu-berlin.de/~semu/docs/2011_seminar_ehlert_i2p.pdf},
www_section = comm,
}
%% inria-00632259, version 1
%% http://hal.inria.fr/inria-00632259
@misc{timpanaro:inria-00632259,
hal_id = {inria-00632259},
url = {http://hal.inria.fr/inria-00632259},
title = {{Monitoring the I2P network}},
author = {Timpanaro, Juan Pablo and Chrisment, Isabelle and Festor, Olivier},
howpublished = {Preprint},
abstract = {{We present the first monitoring study aiming to characterize the usage of the I2P network, a low-latency anonymous network based on garlic routing. We design a distributed monitoring architecture for the I2P network and we show through a one week long experiment that we are able to identify 32\% of all running applications, among web servers and file- sharing clients. Additionally, we identify 37\% of published I2P applications, which turn out to be unreachable after its publication on the I2P distributed database.}},
language = {English},
affiliation = {MADYNES - INRIA Lorraine - LORIA},
year = {2011},
month = Oct,
www_pdf_url = {http://hal.inria.fr/inria-00632259/PDF/TMA2012-LNCS.pdf},
www_section = traffic,
}
@inproceedings{pets2011-i2p,
title = {Privacy Implications of Performance-Based Peer Selection by Onion Routers: A Real-World Case Study using I2P},
author = {Michael Herrmann and Christian Grothoff},
booktitle = {Proceedings of the 11th Privacy Enhancing Technologies Symposium (PETS 2011)},
year = {2011},
month = {July},
location = {Waterloo, Canada},
www_tags = {selected},
www_pdf_url = {http://freehaven.net/anonbib/papers/pets2011/p9-herrmann.pdf},
www_section = traffic,
}
@mastersthesis{hermann2011-mthesis,
title = {Privacy-Implications of Performance-Based Peer Selection by Onion-Routers: A Real-World Case Study using I2P},
author = {Michael Hermann},
school = {TU-Munich},
year = {2011},
month = {March},
www_section = traffic,
}
@inproceedings{BlackHat2011-crenshaw,
url = {http://www.irongeek.com/i.php?page=security/darknets-i2p-identifying-hidden-servers},
title = {Darknets - I2P Identifying Hidden Servers},
author = {Adrian Crenshaw},
booktitle = {Proceedings of Black Hat},
year = {2011},
month = {January},
location = {DC},
www_pdf_url = {http://www.irongeek.com/downloads/Identifying%20the%20true%20IP%20of%20I2P%20service%20hosts.pdf},
www_section = traffic,
}
@mastersthesis{delmer-mthesis,
title = {L'{\'e}mergence au sein d'internet de communaut{\'e}s virtuelles et anonymes, Freenet et i2p},
author = {Laurie Delmer},
school = {Universit{\'e} catholique de Louvain - D{\'e}partement des sciences politiques et sociales},
year = {2009},
note = {Title : The rise in internet virtual and anonymous communities, Freenet and I2P. School: Catholic University of Leuven - Department of Political and Social Science},
www_section = comm,
}
@inproceedings{petcon2009-schomburg,
title = {Anonymity Techniques - Usability Tests of Major Anonymity Networks},
author = {Jens Schomburg},
booktitle = {Proceedings of PET-CON 2009.1},
location = {Dresden, Germany},
year = {2009},
month = {March},
pages = {49--58},
www_pdf_url = {https://people.torproject.org/~karsten/petcon-proceedings-2009.1.pdf},
www_section = comm,
}
@inproceedings{petcon2009-zzz,
title = {Peer Profiling and Selection in the I2P Anonymous Network},
author = {zzz (Pseudonym) and Lars Schimmer},
booktitle = {Proceedings of PET-CON 2009.1},
location = {Dresden, Germany},
year = {2009},
month = {March},
pages = {59--70},
www_pdf_url = {/_static/pdf/I2P-PET-CON-2009.1.pdf},
www_section = comm,
}
@misc{jrandom2003,
title = {Invisible Internet Project (I2P) Project Overview},
author = {jrandom (Pseudonym)},
howpublished = {Design document},
year = {2003},
month = Aug,
www_pdf_url = {/_static/pdf/i2p_philosophy.pdf},
www_section = comm,
}

View File

@@ -0,0 +1,163 @@
# Copyright 2003-2008, Nick Mathewson. See LICENSE for licensing info.
# Our input filename.
MASTER_BIB = "./anonbib.bib"
# Where do we put generated HTML?
OUTPUT_DIR = "."
# Where do we put cached papers (relative to OUTPUT_DIR)
CACHE_DIR = "cache"
# Where do we cache citations papers (relative to OUTPUT_DIR)
CITE_CACHE_DIR = "cite_cache"
# Are there subsections for cached papers? This is useful for putting
# different Apache permission on different directories.
CACHE_SECTIONS = [ ]
# Only include entries that have this key. This is one way to
# generate multiple bibliographies from the same source. Currently
# deprecated in favor of tags.
#
#example: REQUIRE_KEY = "www_selected"
#
REQUIRE_KEY = None
# Timeout when downloading from a server while caching, in seconds.
DOWNLOAD_CONNECT_TIMEOUT = 15
# Template files.
TEMPLATE_FILE = "./_template_.html"
BIBTEX_TEMPLATE_FILE = "./_template_bibtex.html"
# Map from author name regex to author homepage.
AUTHOR_URLS = {
'Ross.*Anderson' : 'http://www.cl.cam.ac.uk/users/rja14/',
'Alessandro.*Acquisti' : 'http://www.heinz.cmu.edu/~acquisti/index.html',
'Agrawal' : 'http://www.research.ibm.com/people/a/agrawal/',
'Adam.*Back' : 'http://www.cypherspace.org/~adam/',
'Berthold' : 'http://page.inf.fu-berlin.de/~berthold/',
'Borisov' : 'http://hatswitch.org/~nikita/',
'Bettati' : 'http://faculty.cs.tamu.edu/bettati/',
'Miguel.*Castro' : 'http://research.microsoft.com/users/mcastro/',
'Chaum' : 'http://www.chaum.com/',
'J.*Claessens' : 'http://www.esat.kuleuven.be/~joclaess/',
'R.*Clayton' : 'http://www.cl.cam.ac.uk/~rnc1/',
'Wei Dai' : 'http://www.eskimo.com/~weidai/',
'Danezis' : 'http://homes.esat.kuleuven.be/~gdanezis/',
'Claudia.*az' : 'http://www.esat.kuleuven.be/~cdiaz/',
'Dingledine' : 'http://www.freehaven.net/~arma/cv.html',
'Desmedt' : 'http://www.cs.fsu.edu/~desmedt/',
'Douceur' : 'http://research.microsoft.com/~johndo/',
'N.*Hopper' : 'http://www-users.cs.umn.edu/~hopper/',
'Michael.*Freedman' : 'http://www.scs.cs.nyu.edu/~mfreed/',
'Gergely' : 'http://www.planeforge.com/home/tgm',
'Ian.*Goldberg' : 'http://www.cs.uwaterloo.ca/~iang/',
'Christian.*Grothoff' : 'http://grothoff.org/christian/',
'D.*Hopwood' : 'http://www.users.zetnet.co.uk/hopwood/',
'Jakobsson' : 'http://www2.parc.com/csl/members/mjakobss/markus-jakobsson.htm',
'Juels' : 'http://www.rsasecurity.com/rsalabs/staff/bios/ajuels/',
'Kaashoek' : 'http://pdos.csail.mit.edu/~kaashoek/',
'K.*Kurosawa' : 'http://kuro.cis.ibaraki.ac.jp/~kurosawa/',
'H.*Langos' : 'http://www.wh9.tu-dresden.de/~heinrich/',
'B.*Liskov' : 'http://www.pmg.lcs.mit.edu/barbara_liskov.html',
'Mathewson' : 'http://www.wangafu.net/~nickm/',
'Mazi&egrave;res' : 'http://www.scs.cs.nyu.edu/~dm/',
'B.*M&ouml;ller' : ('http://www.informatik.tu-darmstadt.de/TI/'
'Mitarbeiter/moeller.html'),
'U.*M&ouml;ller' : 'http://www.ulfm.de/',
'D.*Molnar' : 'http://www.cs.berkeley.edu/~dmolnar/',
'R.*Morris' : 'http://www.pdos.lcs.mit.edu/~rtm/',
'S.*Murdoch' : 'http://www.cl.cam.ac.uk/users/sjm217/',
'A.*Pashalidis' : 'http://www.xrtc.com/',
'A.*Pfitzmann' : 'http://dud.inf.tu-dresden.de/~pfitza/',
'B.*Pfitzmann' : 'http://www.zurich.ibm.com/~bpf/',
'B.*Preneel' : 'http://www.esat.kuleuven.be/~preneel/',
'Daniel.*Simon' : 'http://research.microsoft.com/crypto/dansimon/me.htm',
'Rackoff' : 'http://www.cs.toronto.edu/DCS/People/Faculty/rackoff.html',
'Jean F' : 'http://www.geocities.com/j_f_raymond/',
'M.*Rennhard' : 'http://www.tik.ee.ethz.ch/~rennhard/',
'M.*Reiter' : 'http://www.ece.cmu.edu/~reiter/',
'Rivest' : 'http://theory.lcs.mit.edu/~rivest/',
'Avi.*Rubin' : 'http://avirubin.com/',
'Sassaman' : 'http://homes.esat.kuleuven.be/~lsassama/',
'Serjantov' : 'http://home.arachsys.com/~aas/',
'S.*Seys' : 'http://www.esat.kuleuven.be/~sseys/',
'Shoup' : 'http://www.shoup.net/',
'Syverson' : 'http://www.syverson.org/',
'Tsudik' : 'http://www.ics.uci.edu/~gts/c.html',
'M.*Waidner' : 'http://www.zurich.ibm.com/~wmi/',
'David.*Wagner' : 'http://www.cs.berkeley.edu/~daw/',
'M.*Waldman' : 'http://cs1.cs.nyu.edu/~waldman/',
'B.*Waters' : 'http://www.cs.utexas.edu/~bwaters/',
'Chenxi.*Wang' : 'http://www.ece.cmu.edu/~chenxi/',
'M.*Wright' : 'http://ranger.uta.edu/~mwright/',
'B.*Levine' : 'http://prisms.cs.umass.edu/brian/',
'T.*Benjamin' : 'http://www.cs.umass.edu/~tshb/',
'B.*Defend' : 'http://www.cs.umass.edu/~defend/',
'K.*Fu' : 'http://www.cs.umass.edu/~kevinfu/',
'J.*Camenisch' : 'http://www.zurich.ibm.com/~jca/',
'S.*Hohenberger' : 'http://www.cs.jhu.edu/~susan/',
'M.*Kohlweiss' : 'http://homes.esat.kuleuven.be/~mkohlwei/',
'A.*Lysyanskaya' : 'http://www.cs.brown.edu/~anna/',
'M.*Meyerovich' : 'http://www.cs.brown.edu/~mira/',
'P.*Zieli.*ski' : 'http://www.cl.cam.ac.uk/~pz215/',
'S.*Zander' : 'http://caia.swin.edu.au/cv/szander/'
}
# List of paterns for author names _not_ to do an initial-tolerant
# match on when building section list. E.g., if "J\\. Smith" is in
# this list, he won't be folded into "John Smith".
NO_COLLAPSE_AUTHORS = [
]
# Map from LaTeX-style name of author to collapse to canonical name.
COLLAPSE_AUTHORS = {
"Nicholas Mathewson": "Nick Mathewson",
}
# Map from author pattern to collation key.
# This keeps 'Zero Knowledge Systems' from getting alphabetized as "Systems,
# Zero Knowledge."
ALPHABETIZE_AUTHOR_AS = {
"Zero.*Knowledge.*Systems": "Zero Knowledge Systems",
"Carlos.*Aguilar.*Melchor": "Aguilar Melchor Carlos",
}
# Map of strings to initialize BibTeX parsing with.
INITIAL_STRINGS = {
# SECTIONS
'sec_mix' : "Mix Networks: Design",
'sec_mixattacks' : "Mix Networks: Attacks",
'sec_stream' : "Stream-based anonymity",
'sec_traffic' : "Traffic analysis",
'sec_pub' : "Anonymous publication",
'sec_pir' : "Private Information Retrieval",
'sec_nym' : "Pseudonymity"
}
# Don't put in any entries of this type.
OMIT_ENTRIES = ("proceedings", "journal")
# List of all recognized values for www_tags.
ALL_TAGS = ("selected", )
# Titles of page, by tag.
TAG_TITLES = { "": "I2P Bibliography",
"selected": "Selected I2P Papers"
}
# As TAG_TITLES, but shorter.
TAG_SHORT_TITLES = { "": "I2P Bibliography",
"selected": "Selected I2P Papers",
}
# Directories where tag pages get generated.
TAG_DIRECTORIES = { '': "full",
"selected": "" }
# Make cached stuff group-writable. Make sure that your cache directories
# are sticky!
CACHE_UMASK = 002

View File

@@ -0,0 +1,17 @@
{% extends "global/layout.html" %}
{% block title %}{{ bib.title }}: BibTeX{% endblock %}
{% block headextra %}
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles/pubs.css') }}" />
{% endblock %}
{% block content %}
<table cellspacing="15" border="0" align="center" width="100%%">
{% for entry in bib.entries %}
<tr><td class='bibtex'>
<a name='{{ entry.key }}'>{{ entry.key }}</a>
<pre class='bibtex'>
{{ entry.format(90,8,1) }}
</pre>
</td></tr>
{% endfor %}
</table>
{% endblock %}

View File

@@ -0,0 +1,93 @@
{% extends "global/layout.html" %}
{% block title %}{{ bib.tag_short_titles[bib.tag] }}{% endblock %}
{% block headextra %}
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles/pubs.css') }}" />
{% endblock %}
{% block content %}
<h1 align="center">{{ bib.tag_titles[bib.tag] }}</h1>
<p align="center">
{%- if bib.tag|length %}<a href='{% if bib.field != 'date' -%}
{{ get_url('papers_list', choice=bib.field) }}
{%- else %}{{ get_url('papers_list') }}{% endif %}'>
{%- endif %}{{ bib.tag_titles[''] }}
{%- if bib.tag|length %}</a>{% endif %}
{%- for tag in bib.tags %}&nbsp;|&nbsp;
{%- if tag != bib.tag %}<a href='{% if bib.field != 'date' -%}
{{ get_url('papers_list', tag=tag, choice=bib.field) }}
{%- else %}{{ get_url('papers_list', tag=tag) }}{% endif %}'>
{%- endif %}{{ bib.tag_titles[tag] }}
{%- if tag != bib.tag %}</a>{% endif %}
{%- endfor -%}
</p>
<p align="center">
{%- if bib.field != 'topic' %}{% if bib.tag -%}
<a href='{{ get_url('papers_list', tag=bib.tag, choice='topic') }}'>
{%- else -%}
<a href='{{ get_url('papers_list', choice='topic') }}'>{% endif %}
{%- endif %}{{ _('By topic') }}{%- if bib.field != 'topic' -%}</a>{% endif -%}
&nbsp;|&nbsp;
{%- if bib.field != 'date' -%}{% if bib.tag -%}
<a href='{{ get_url('papers_list', tag=bib.tag) }}'>
{%- else -%}
<a href='{{ get_url('papers_list') }}'>{% endif %}
{%- endif %}{{ _('By date') }}{%- if bib.field != 'date' -%}</a>{% endif -%}
&nbsp;|&nbsp;
{%- if bib.field != 'author' -%}{% if bib.tag -%}
<a href='{{ get_url('papers_list', tag=bib.tag, choice='author') }}'>
{%- else -%}
<a href='{{ get_url('papers_list', choice='author') }}'>{% endif %}
{%- endif %}{{ _('By author') }}{%- if bib.field != 'author' -%}</a>{% endif -%}
</p>
<!-- Table 1: contains the sidebar and the body. -->
<table cellspacing="3" cellpadding="0" border="0" align="center" width="100%%">
<tr valign="top">
<td>
<!-- Table 2: The sidebar-->
<table align="right" cellspacing="0" cellpadding="5" width="100"
class="sidebar">
<tr valign="top"><td><p class="l1"><strong>{{ bib.sectiontypes }}:</strong><br /></p>
{% for section in bib.sections %}
<p class="l2"><a href="#{{ section.slug }}">{{ section.name }}</a></p>
{% endfor %}
</td>
</tr>
</table><!-- End of table 2 -->
</td>
<td width="85%%">
<h2>Publications by {{ bib.field }}</h2>
<ul class="sections">
{% for section in bib.sections %}
<li><h3><a name="{{ section.slug }}">{{ section.name }}</a></h3>
<ul class="expand">
{% for entry in section.entries %}
{{ entry.to_html()|safe }}
{% endfor %}
</ul></li>
{% endfor %}
</ul>
</td>
<td width="5%%"><br /></td>
</tr>
</table><!-- End of table 1 -->
<p class="contact">{% trans email="press&#64;i2<!-- -->p2.de"|safe,
bibtex = get_url('papers_bibtex', tag=bib.tag) if bib.tag else get_url('papers_bibtex'),
citeseer = 'http://citeseer.ist.psu.edu/online-nature01/' -%}
Please send new or corrected entries to
<a name="contact"><span class="email">{{ email }}</span></a>.<br />
If you can, please format them as BibTeX; see our
<a href="{{ bibtex }}">BibTeX source page</a> for examples.<br />
Remember to include URLs if possible:
<a href="{{ citeseer }}">offline papers are less useful</a>.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,105 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Web Browser Configuration') }}{% endblock %}
{% block content %}
<p>{% trans -%}
Your web browser will need to be configured in order to browse eepsites and to
utilize the outproxies available within I2P. Below are walkthroughs for some of
the most popular browsers.
{%- endtrans %}</p>
<h2>{{ _('How to configure your browser') }}</h2>
<ul>
<li><a href="#ie8">Internet Explorer 8</a></li>
<li><a href="#firefox">Firefox</a></li>
<li><a href="#konqueror">Konqueror</a></li>
<li><a href="#TOS">{{ _('Outproxy Terms Of Service') }}</a></li>
</ul>
<a name="ie8"></a>
<h3>{{ _('Internet Explorer 8 or Chrome') }}</h3>
<p>{% trans -%}
In the tools menu select the "Internet Options" line to open the settings. In the
settings window choose the connections tab and click on LAN settings for the
proxy port configuration.
{%- endtrans %}</p>
<img src="{{ url_for('static', filename='images/ie.options.jpg') }}" alt="{{ _('IE Internet Options') }}" title="{{ _('IE Internet Options') }}">
<p>{% trans -%}
Now set the checkmark at "use a proxy server for your LAN" and at the "Bypass
proxy server for local addresses". With a click on Advanced-button you open the
window to open the ports. Enter the values like on the picture, IP 127.0.0.1
and port 4444 for HTTP, port 4445 for HTTPS. With clicks on OK you save the
settings and your browser is set to use the I2P proxy.
{%- endtrans %}</p>
<img src="{{ url_for('static', filename='images/ie.proxyports.jpg') }}" alt="{{ _('IE Proxy Settings') }}" title="{{ _('IE Proxy Settings') }}">
<a name="firefox"></a>
<h3>Firefox</h3>
<p>{% trans -%}
From the Tools menu, select Options to bring up the Firefox settings panel.
Click the icon labelled <em>Advanced</em>, then click on the <em>Network</em>
tab. In the <em>Connections</em> section, click on the Settings button. You'll
see a Window like the following:
{%- endtrans %}</p>
<img src="{{ url_for('static', filename='images/firefox.options.jpg') }}" alt="{{ _('Firefox Network Options') }}" title="{{ _('Firefox Network Options') }}">
<p>{% trans -%}
In the <em>Connection Settings</em> window, click the circle next to <em>Manual
proxy configuration</em>, then enter 127.0.0.1, port 4444 in the HTTP Proxy
field. Enter 127.0.0.1, port 4445 in the SSL Proxy field.
Be sure to enter localhost and 127.0.0.1 into the "No Proxy for" box.
{%- endtrans %}</p>
<img src="{{ url_for('static', filename='images/firefox.proxyports.jpg') }}" alt="{{ _('Firefox Proxy Settings') }}" title="{{ _('Firefox Proxy Settings') }}">
<a name="konqueror"></a>
<h3>Konqueror</h3>
<p>{% trans -%}
From the <em>Settings</em> menu, select <em>Configure Konqueror</em>. In the
Web Browsing group on the left side, select Proxy Services.
In this new window, select the option "Manually specify the proxy settings" and
click the <em>Setup</em> box.
{%- endtrans %}</p>
<img src="{{ url_for('static', filename='images/konqueror.options.jpg') }}" alt="{{ _('Konqueror Proxy Options') }}" title="{{ _('Konqueror Proxy Options') }}">
<p>{% trans -%}
Enter 127.0.0.1 and port 4444 into the HTTP box. Enter 127.0.0.1 and port 4445 into
HTTPS box. Click the <em>New</em> button in the Exceptions section. Enter
localhost and click OK. Click the <em>New</em> button once more and enter
127.0.0.1 and OK. Hit OK once more to close the configuration window.
{%- endtrans %}</p>
<img src="{{ url_for('static', filename='images/konqueror.proxyports.jpg') }}" alt="{{ _('Konqueror Proxy Ports') }}" title="{{ _('Konqueror Proxy Ports') }}">
<a name="TOS"></a>
<h3>{{ _('Outproxy Terms Of Service') }}</h3>
<p>{% trans -%}
Remember: I2P was not designed for creating proxies to the outer Internet.
Instead, it is meant to be used as an internal network.
{%- endtrans %}</p>
<p>{% trans -%}
<b>The I2P project itself does not run any proxies to the Internet. Any such proxy
services are run by by private volunteers and could be shut down or
unreachable at anytime.</b>
{%- endtrans %}</p>
<p>{% trans http='false.i2p', https='outproxy-tor.meeh.i2p' -%}
By default, I2P comes with two outproxies configured: <code>{{ http }}</code>
(an HTTP-only proxy) and <code>{{ https }}</code> (an HTTPS proxy
routed through Tor.
{%- endtrans %}</p>
<p>{% trans -%}
Both of these outproxies are configured with connection limits. This means
that only set amount of accesses are allowed per client. Once the limit is
reached, the client is blocked out for a timeframe of 1min/1h/1 day. Be
respectful and do not overload these services with too many requests!
{%- endtrans %}</p>
<p>{% trans -%}
Filtering is active on these outproxies (for example, mibbit and torrent
tracker access is blocked). Eepsites
that are accessible via .i2p addresses are also not allowed via the outproxies.
As a convenience, <code>false.i2p</code> blocks ad servers.
{%- endtrans %}</p>
<p>{% trans -%}
<a href="https://www.torproject.org">Tor</a> is good application to use as an
outproxy to the Internet.
{%- endtrans %}</p>
<!-- vim: set noai ff=unix nosi ft=html tw=79 et sw=4 ts=4 spell spelllang=en: -->
{% endblock %}

View File

@@ -0,0 +1,33 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Glossary') }}{% endblock %}
{% block content %}
{% trans -%}
This page lists often-used terminology when discussing I2P and cryptography.
{%- endtrans %}
<table>
<tr>
<td>I2P</td>
<td>Invisible Internet Project: a project meant to provide an anonymity layer, so user can communicate anonymously using a range of applications.</td>
</tr>
<tr>
<td>Router</td>
<td>The core I2P software, which routes encrypted packets on the I2P network. All routers by default participate in the network, which both helps the network and provides cover traffic for any clients or servers connecting to the I2P network through the router.</td>
</tr>
<tr>
<td>RouterIdentity</td>
<td>A collection of information required to communicate directly with a router, such as its IP address and listening port, public signing and encryption keys etc.</td>
</tr>
<tr>
<td>Tunnel</td>
<td>An anonymous communication pathway between a client or server and the I2P network. Tunnels are unidirectional, so any one client or server must have at least two Tunnels - one for inbound traffic and one for outbound traffic.</td>
</tr>
<tr>
<td>Destination</td>
<td>The cryptographic identity of a tunnel. These are the identities of clients and servers within the I2P network, and are analogous to the IP:port of a computer on the normal internet.</td>
</tr>
<tr>
<td>LeaseSet</td>
<td>A collection of information required to communicate with a client or server at a particular Destination, such as the gateways of the inbound Tunnels for that Destination.</td>
</tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,557 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Hall Of Fame') }}{% endblock %}
{% block content %}
<!-- file version 2013.08.25.01 -->
<h1>{% trans %}I2P'<small>s</small> Hall of Fame{% endtrans %}</h1>
<b>{% trans date='2013-08-25' -%}
Current balance: as of {{ date }}
{%- endtrans %}</b><br />
<b>{{ _('General fund') }}:
{% trans euroval='28829,12', btcval='607,49839100' %}{{ euroval }} &euro; and {{ btcval }} BTC{% endtrans %}</b><br />
<b><a href="{{ site_url('get-involved/bounties/datastore') }}">{{ _('Datastorage bounty') }}</a>:
{% trans euroval='145.0', btcval='2' %}{{ euroval }} &euro; and {{ btcval }} BTC{% endtrans %}</b><br />
<b><a href="{{ site_url('get-involved/bounties/ipv6') }}">{{ _('Native IPv6 I2P') }}</a>:
{% trans euroval='100.0', btcval='50' %}{{ euroval }} &euro; and {{ btcval }} BTC{% endtrans %}</b><br />
<b><a href="{{ site_url('get-involved/bounties/i2phex') }}">{{ _('I2PHex bounty') }}</a>:
{% trans euroval='100.0' %}{{ euroval }} &euro;{% endtrans %}</b><br />
<b><a href="{{ site_url('get-involved/bounties/deb-pack') }}">{{ _('I2P in debian mirrors') }}</a>:
{% trans euroval='148.0' %}{{ euroval }} &euro;{% endtrans %}</b><br />
<b><a href="{{ site_url('get-involved/bounties/btc-client') }}">{{ _('Bitcoin client for I2P') }}</a>:
{% trans euroval='10', btcval='50.34' %}{{ euroval }} &euro; and {{ btcval }} BTC{% endtrans %}</b><br />
<b><a href="{{ site_url('get-involved/bounties/unit-tests') }}">{{ _('Unit Tests for I2P router') }}</a>:
{% trans euroval='2305' %}{{ euroval }} &euro;{% endtrans %}</b><br />
<b>{{ _('Bounty Robert') }}: 20</b><br />
<b>{{ _('Bounty Syndie') }}: 18 BTC</b><br />
<b>{{ _('Bounty I2P for CCR Microtic Board') }}: 10 &euro;</b><br />
<br />
<b>{{ _('Current monthly running costs:') }}</b><br />
<table border="1">
<tr>
<td>Welterde</td>
<td>8 &euro;/mo, since January, 2008 - i2p2.de</td>
</tr>
<tr>
<td>eche|on</td>
<td>40 &euro;/mo since January, 2008 - i2p-projekt.de and domains</td>
</tr>
</table>
<p>{% trans %}Big thanks go to the following people who have donated to I2P!{% endtrans %}</p>
<p>{% trans echelon='echelon@'+i2pconv('mail.i2p') -%}
If you have made a donation, please send an email to <a href="mailto:{{ echelon }}">echelon</a>
with your name or nick (and optionally homepage) so we can list you here.
{%- endtrans %}</p>
<b>{{ _('Current monthly subscriptions:') }}</b><br />
<table border="1">
<tr><td>01/2012-01/2013</td><td>anonymous</td><td>30 &euro;</td><td>{{ _('General fund') }}</td></tr>
</table>
<br />
<b>{{ _('2013 donations and costs:') }}</b><br />
<table border="1">
<tr><td>date</td><td>who</td><td>income</td><td>outgoing</td><td>account</td></tr>
<tr><td>Jan, 2013</td><td>anonymous</td><td>10 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Jan, 2013</td><td>PayPal fees 2012,2nd</td><td></td><td>30,27 &euro;</td><td>General fund</td></tr>
<tr><td>Jan, 2013</td><td>29C3 costs</td><td></td><td>320 &euro;</td><td>General fund</td></tr>
<tr><td>Jan, 2013</td><td>Hottuna</td><td>80 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Jan, 2013</td><td>Cacapo</td><td>80 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Jan, 2013</td><td>I2P services echelon</td><td></td><td>100 &euro;</td><td>General fund</td></tr>
<tr><td>Jan, 2013</td><td>I2P services welterde</td><td></td><td>100 &euro;</td><td>General fund</td></tr>
<tr><td>Jan, 2013</td><td>I2P services sponge</td><td></td><td>100 &euro;</td><td>General fund</td></tr>
<tr><td>Jan, 2013</td><td>Kytv service</td><td></td><td>9.50 BTC</td><td>General fund</td></tr>
<tr><td>Jan, 2013</td><td>anonymous</td><td>10 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Jan, 2013</td><td>anonymous</td><td>18 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Jan, 2013</td><td>anonymous</td><td>20 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Jan, 2013</td><td>anonymous</td><td>30 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Jan, 2013</td><td>sell BTC</td><td>2434 &euro;</td><td>200 BTC</td><td>General fund</td></tr>
<tr><td>Jan, 2013</td><td>anonymous</td><td>5 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Jan, 2013</td><td>anonymous</td><td>0.80 BTC</td><td></td><td>General fund</td></tr>
<tr><td>Jan, 2013</td><td>anonymous</td><td>10 &euro;</td><td></td><td>Bounty .deb package</td></tr>
<tr><td>Jan, 2013</td><td>anonymous</td><td>5 &euro;</td><td></td><td>Bounty Unit Tests</td></tr>
<tr><td>Jan, 2013</td><td>anonymous</td><td>30 &euro;</td><td></td><td>Bounty Eepsites in Tahoe-Lafs</td></tr>
<tr><td>Jan, 2013</td><td>Paid Bounty Unittests</td><td></td><td>400 &euro;</td><td>Bounty Unittests</td></tr>
<tr><td>Feb, 2013</td><td>bikenstrings</td><td>5 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Feb, 2013</td><td>i2p-projekt.de domain</td><td></td><td>11,90 &euro;</td><td>General fund</td></tr>
<tr><td>Feb, 2013</td><td>anonymous</td><td>10 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Feb, 2013</td><td>anonymous</td><td>20 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Feb, 2013</td><td>anonymous</td><td>30 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Feb, 2013</td><td>tabby.cat</td><td>1 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Feb, 2013</td><td>anonymous</td><td>30 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Feb, 2013</td><td>syndie,i2pprojekt.net domains</td><td></td><td>59,90 &euro;</td><td>General fund</td></tr>
<tr><td>Feb, 2013</td><td>anonymous</td><td>0.01234567 BTC</td><td></td><td>General fund</td></tr>
<tr><td>Feb, 2013</td><td>anonymous</td><td>0.499 BTC</td><td></td><td>General fund</td></tr>
<tr><td>Feb, 2013</td><td>anonymous</td><td>0.01234567 BTC</td><td></td><td>General fund</td></tr>
<tr><td>Feb, 2013</td><td>anonymous</td><td>0.29 BTC</td><td></td><td>General fund</td></tr>
<tr><td>Feb, 2013</td><td>anonymous</td><td>0.01234567 BTC</td><td></td><td>General fund</td></tr>
<tr><td>Feb, 2013</td><td>Change Syndie/IPv6 bounty</td><td>50 BTC</td><td>50 BTC</td><td>Bounty Syndie,IPv6</td></tr>
<tr><td>Mar, 2013</td><td>Sell BTC</td><td>2598 &euro;</td><td>100 BTC</td><td>General fund</td></tr>
<tr><td>Mar, 2013</td><td>I2P Laptop</td><td></td><td>846,05 &euro;</td><td>General fund</td></tr>
<tr><td>Mar, 2013</td><td>Sell BTC</td><td>4123 &euro;</td><td>100 BTC</td><td>General fund</td></tr>
<tr><td>Mar, 2013</td><td>David Julian</td><td>30 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Mar, 2013</td><td>I2P Laptop</td><td></td><td>117,46 &euro;</td><td>General fund</td></tr>
<tr><td>Mar, 2013</td><td>anonymous</td><td>20 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Mar, 2013</td><td>anonymous</td><td>30 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Mar, 2013</td><td>Sell BTC</td><td>4998 &euro;</td><td>100 BTC</td><td>General fund</td></tr>
<tr><td>Mar, 2013</td><td>Sell BTC</td><td>5923 &euro;</td><td>100 BTC</td><td>General fund</td></tr>
<tr><td>Mar, 2013</td><td>i2p-projekt.net domain</td><td></td><td>11,90 &euro;</td><td>General fund</td></tr>
<tr><td>Mar, 2013</td><td>Sell BTC</td><td>7889 &euro;</td><td>100 BTC</td><td>General fund</td></tr>
<tr><td>Mar, 2013</td><td>anonymous</td><td>25 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Mar, 2013</td><td>anonymous</td><td>0.01234567 BTC</td><td></td><td>General fund</td></tr>
<tr><td>Mar, 2013</td><td>echelon</td><td>10 BTC</td><td></td><td>General fund</td></tr>
<tr><td>Mar, 2013</td><td>Recalc Syndie Bountie</td><td>32 BTC</td><td>32 BTC</td><td>General fund, Syndie bounty</td></tr>
<tr><td>Apr, 2013</td><td>SSL cert syndie.de</td><td></td><td>389,70 &euro;</td><td>General fund</td></tr>
<tr><td>Apr, 2013</td><td>SSL cert geti2p.net</td><td></td><td>389,70 &euro;</td><td>General fund</td></tr>
<tr><td>Apr, 2013</td><td>anonymous</td><td>5 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Apr, 2013</td><td>giv</td><td>30 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Apr, 2013</td><td>anonymous</td><td>20 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Apr, 2013</td><td>anonymous</td><td>30 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Apr, 2013</td><td>Flattr</td><td>107,80 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Apr, 2013</td><td>SSL cert i2p2.de</td><td></td><td>2009,70 &euro;</td><td>General fund</td></tr>
<tr><td>Apr, 2013</td><td>anonymous</td><td>4 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Apr, 2013</td><td>anonymous</td><td>10 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Apr, 2013</td><td>anonymous</td><td>10 &euro;</td><td></td><td>I2PBTC native client</td></tr>
<tr><td>Apr, 2013</td><td>anonymous</td><td>1 BTC</td><td></td><td>General fund</td></tr>
<tr><td>Apr, 2013</td><td>29C3 contest</td><td></td><td>25 BTC</td><td>General fund</td></tr>
<tr><td>Apr, 2013</td><td>29C3 contest</td><td></td><td>5 BTC</td><td>General fund</td></tr>
<tr><td>Apr, 2013</td><td>29C3 contest</td><td></td><td>10,3 BTC</td><td>General fund</td></tr>
<tr><td>Apr, 2013</td><td>anonymous</td><td>0.15 BTC</td><td></td><td>General fund</td></tr>
<tr><td>Apr, 2013</td><td>anonymous</td><td>0.000024 BTC</td><td></td><td>General fund</td></tr>
<tr><td>Apr, 2013</td><td>anonymous</td><td>0.0000496 BTC</td><td></td><td>General fund</td></tr>
<tr><td>Apr, 2013</td><td>anonymous</td><td>0.01 BTC</td><td></td><td>General fund</td></tr>
<tr><td>Apr, 2013</td><td>Bounty native I2P BTC client paid to giv</td><td></td><td>30 &euro;</td><td>Bounty BTC client</td></tr>
<tr><td>Apr, 2013</td><td>Bounty native I2P BTC client paid to giv</td><td></td><td>68 BTC</td><td>Bounty BTC client</td></tr>
<tr><td>May, 2013</td><td>anonymous</td><td>50 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>May, 2013</td><td>anonymous</td><td>0.3 BTC</td><td></td><td>General fund</td></tr>
<tr><td>May, 2013</td><td>anonymous</td><td>10 &euro;</td><td></td><td>Bounty CCR Microtic Board</td></tr>
<tr><td>May, 2013</td><td>anonymous</td><td>20 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>May, 2013</td><td>anonymous</td><td>30 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>May, 2013</td><td>anonymous</td><td>3.50 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>May, 2013</td><td>anonymous</td><td>0.0008 BTC</td><td></td><td>General fund</td></tr>
<tr><td>May, 2013</td><td>anonymous</td><td>0.0991 BTC</td><td></td><td>General fund</td></tr>
<tr><td>June, 2013</td><td>anonymous</td><td>10 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>June, 2013</td><td>anonymous</td><td>20 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>June, 2013</td><td>anonymous</td><td>30 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>June, 2013</td><td>DHT bounty</td><td></td><td>325 &euro;</td><td>DHT bounty</td></tr>
<tr><td>June, 2013</td><td>anonymous</td><td>1 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>June, 2013</td><td>anonymous</td><td>0.0000067 BTC</td><td></td><td>General fund</td></tr>
<tr><td>June, 2013</td><td>anonymous</td><td>0.01 BTC</td><td></td><td>General fund</td></tr>
<tr><td>June, 2013</td><td>anonymous</td><td>0.031 BTC</td><td></td><td>General fund</td></tr>
<tr><td>June, 2013</td><td>anonymous</td><td>0.25 BTC</td><td></td><td>General fund</td></tr>
<tr><td>July, 2013</td><td>first-leon</td><td>1 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>July, 2013</td><td>anonymous</td><td>5 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>July, 2013</td><td>anonymous</td><td>2 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>July, 2013</td><td>anonymous</td><td>20 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>July, 2013</td><td>anonymous</td><td>0.05 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>July, 2013</td><td>anonymous</td><td>30 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>July, 2013</td><td>JULLIAN David</td><td>15 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>July, 2013</td><td>anonymous</td><td>0.00567899 BTC</td><td></td><td>General fund</td></tr>
<tr><td>July, 2013</td><td>anonymous</td><td>0.00942744 BTC</td><td></td><td>General fund</td></tr>
<tr><td>July, 2013</td><td>anonymous</td><td>0.01807730 BTC</td><td></td><td>General fund</td></tr>
<tr><td>July, 2013</td><td>fraud loss</td><td></td><td>9 BTC</td><td>General fund</td></tr>
<tr><td>Aug, 2013</td><td>anonymous</td><td>18 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Aug, 2013</td><td>anonymous</td><td>30 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Aug, 2013</td><td>sell BTC</td><td>820 &euro;</td><td>10 BTC</td><td>General fund</td></tr>
<tr><td>Aug, 2013</td><td>anonymous</td><td>20 &euro;</td><td></td><td>General fund</td></tr>
<tr><td>Aug, 2013</td><td>anonymous</td><td>25 &euro;</td><td></td><td>Bounty deb package</td></tr>
<tr><td>Aug, 2013</td><td>anonymous</td><td>0.0279 BTC</td><td></td><td>General fund</td></tr>
</table>
<br />
<br />
<b>{{ _('2012 donations and costs:') }}</b><br />
<table border="1">
<tr><td>date</td><td>who</td><td>income</td><td>outgoing</td><td>account</td></tr>
<tr><td>Jan, 2012</td><td>www.i2p2.de server rent</td><td></td><td>-100 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2012</td><td>www.i2p-projekt.de/echelon.i2p server rent</td><td></td><td>-200 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2012</td><td>I2P services sponge</td><td></td><td>-100 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2012</td><td>anonymous</td><td>500 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2012</td><td>anonymous</td><td>1500 &euro;</td><td></td><td>Bounty Unit Tests</td></tr>
<tr><td>Jan, 2012</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2012</td><td>anonymous</td><td>10 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2012</td><td>anonymous</td><td>0.01 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2012</td><td>anonymous</td><td>100 BTC</td><td></td><td>Bounty I2P bitcoin client</td></tr>
<tr><td>Jan, 2012</td><td>anonymous</td><td>20 &euro;</td><td></td><td>Bounty .deb package</td></tr>
<tr><td>Jan, 2012</td><td>anonymous</td><td>25 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2012</td><td>alu-anon</td><td>20 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2012</td><td>maxkoda</td><td>1.00 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2012</td><td>maxkoda</td><td>2.00 BTC</td><td></td><td>Bounty I2P BTC client</td></tr>
<tr><td>Feb, 2012</td><td>DJ Eugene</td><td>10 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2012</td><td>ZZZ new dev workstation</td><td></td><td>522,02 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2012</td><td>anonymous</td><td>15 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2012</td><td>anonymous</td><td>91 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2012</td><td>Sponge dev machine</td><td></td><td>52,3 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2012</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2012</td><td>anonymous</td><td>22 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2012</td><td>domain cost</td><td></td><td>11,9 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2012</td><td>domain cost</td><td></td><td>11,9 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2012</td><td>anonymous</td><td>1.4328 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2012</td><td>anonymous</td><td>1000.00 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2012</td><td>anonymous</td><td>2.20 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2012</td><td>maxkoda</td><td>1.00 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2012</td><td>maxkoda</td><td>2.00 BTC</td><td></td><td>Bounty I2P BTC client</td></tr>
<tr><td>Mar, 2012</td><td>Lautrec</td><td>10 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Mar, 2012</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Mar, 2012</td><td>PayPal fees recalculated</td><td></td><td>188,13 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Mar, 2012</td><td>anonymous</td><td>0.25 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Mar, 2012</td><td>anonymous</td><td>2.00 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Mar, 2012</td><td>anonymous</td><td>0.0000491 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Mar, 2012</td><td>anonymous</td><td>1500 &euro;</td><td></td><td>Bounty Unit Tests</td></tr>
<tr><td>Mar, 2012</td><td>domain cost</td><td></td><td>11,9 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Mar, 2012</td><td>maxkoda</td><td>1.01 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Mar, 2012</td><td>maxkoda</td><td>2.10 BTC</td><td></td><td>Bounty I2P BTC client</td></tr>
<tr><td>Apr, 2012</td><td>anonymous</td><td>100 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2012</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2012</td><td>anonymous</td><td>0,50 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2012</td><td>anonymous</td><td>0.10 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2012</td><td>anonymous</td><td>0.723 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2012</td><td>anonymous</td><td>0.01 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2012</td><td>anonymous</td><td>2.00 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2012</td><td>anonymous</td><td>1.50 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2012</td><td>anonymous</td><td>150 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2012</td><td>anonymous</td><td>5 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2012</td><td>PayPal fees april</td><td></td><td>11,94 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2012</td><td>anonymous</td><td>10 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2012</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2012</td><td>anonymous</td><td>0.25 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2012</td><td>anonymous</td><td>0,69307046 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2012</td><td>sell 100 BTC</td><td>513.38 &euro;</td><td>100 BTC</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2012</td><td>anonymous</td><td>10 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2012</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2012</td><td>anonymous</td><td>10 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2012</td><td>MaxKoda</td><td>1 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2012</td><td>maxkoda</td><td>1 BTC</td><td></td><td>Bounty I2P BTC client</td></tr>
<tr><td>Jul, 2012</td><td>anonymous</td><td>10 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jul, 2012</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jul, 2012</td><td>anonymous</td><td>1 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jul, 2012</td><td>anonymous</td><td>4 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Aug, 2012</td><td>anonymous</td><td>10 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Aug, 2012</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Aug, 2012</td><td>anonymous</td><td>96.04 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Sep, 2012</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Sep, 2012</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Sep, 2012</td><td>Evgeny Ilin</td><td>5 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Sep, 2012</td><td>anonymous</td><td>0.0001 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2012</td><td>dJavid84fr</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2012</td><td>anonymous</td><td>1.11 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2012</td><td>anonymous</td><td>20 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2012</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2012</td><td>anonymous</td><td>1 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2012</td><td>anonymous</td><td>20 &euro;</td><td></td><td>Bounty Deb package</td></tr>
<tr><td>Oct, 2012</td><td>anonymous</td><td>5 &euro;</td><td></td><td>Bounty Robert</td></tr>
<tr><td>Oct, 2012</td><td>anonymous</td><td>20 &euro;</td><td></td><td>Bounty Robert</td></tr>
<tr><td>Oct, 2012</td><td>anonymous</td><td>10 BTC</td><td></td><td>Bounty Robert</td></tr>
<tr><td>Oct, 2012</td><td>anonymous</td><td>1 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2012</td><td>anonymous</td><td>20 &euro;</td><td></td><td>Bounty Robert</td></tr>
<tr><td>Nov, 2012</td><td>anonymous</td><td>20 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Nov, 2012</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Nov, 2012</td><td>anonymous</td><td>0.000666 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Nov, 2012</td><td>anonymous</td><td>0.05025998 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Nov, 2012</td><td>anonymous</td><td>1 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Nov, 2012</td><td>maxkoda</td><td>1 BTC</td><td></td><td>Bounty native I2P BTC client</td></tr>
<tr><td>Nov, 2012</td><td>anonymous</td><td>0.00064184 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Mov, 2012</td><td>anonymous</td><td>0.01697271 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Nov, 2012</td><td>anonymous</td><td>0.0005 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Nov, 2012</td><td>anonymous</td><td>16 &euro;</td><td></td><td>Robert Bounty</td></tr>
<tr><td>Nov, 2012</td><td>anonymous</td><td>40 &euro;</td><td></td><td>Robert Bounty</td></tr>
<tr><td>Nov, 2012</td><td>I2P</td><td></td><td>101 &euro; & 10BTC</td><td>Robert Bounty payout</td></tr>
<tr><td>Dec, 2012</td><td>anonymous</td><td>10 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2012</td><td>anonymous</td><td>3 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2012</td><td>anonymous</td><td>20 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2012</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2012</td><td>anonymous</td><td>10 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2012</td><td>anonymous</td><td>0.7 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2012</td><td>anonymous</td><td>0.5 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2012</td><td>anonymous</td><td>0.0010 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2012</td><td>anonymous</td><td>0.5 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2012</td><td>I2P</td><td></td><td>100 BTC</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2012</td><td>I2P</td><td>100 BTC</td><td></td><td>Syndie Bounty</td></tr>
<tr><td>Dec, 2012</td><td>anonymous</td><td>0.01234567 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2012</td><td>anonymous</td><td>0.01234567 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
</table>
<br />
<br />
<b>{{ _('2011 donations and costs:') }}</b><br />
<table border="1">
<tr><td>date</td><td>who</td><td>income</td><td>outgoing</td><td>account</td></tr>
<tr><td>Jan, 2011</td><td>www.i2p2.de server rent</td><td></td><td>-100 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2011</td><td>www.i2p-projekt.de/echelon.i2p server rent</td><td></td><td>-200 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2011</td><td>PayPal fees 2010</td><td></td><td>-40 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2011</td><td>refund of netstorage bounty,duck,smeghead</td><td>700 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2011</td><td>woodchips</td><td>50 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2011</td><td>anonymous</td><td>13 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2011</td><td>anonymous</td><td>20 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2011</td><td>anonymous</td><td>400 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2011</td><td>Amiga4000</td><td>1000 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2011</td><td>anonymous</td><td>30 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2011</td><td>Mozartito</td><td>8 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2011</td><td>anonymous</td><td>20 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2011</td><td>Flattr</td><td>69,15 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2011</td><td>bv-falcon</td><td>15 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2011</td><td>anonymous</td><td>6,66 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2011</td><td>anonymous</td><td>100 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2011</td><td>anonymous</td><td>20 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2011</td><td>anonymous</td><td>25 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2011</td><td>3 domains 2011</td><td></td><td>-36 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2011</td><td>anonymous</td><td>33.41 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Mar, 2011</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Mar, 2011</td><td>h2ik</td><td>23 &euro;</td><td></td><td>I2P deb in debian mirrors</td></tr>
<tr><td>Mar, 2011</td><td>h2ik</td><td>50 &euro;</td><td></td><td>IPv6 Bounty</td></tr>
<tr><td>Mar, 2011</td><td>hamada</td><td></td><td>-80 BTC</td><td>Arabic routerconsole</td></tr>
<tr><td>Mar, 2011</td><td>anonymous</td><td>63.01 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2011</td><td>I2P</td><td>745.84 &euro;</td><td>-1000 BTC</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2011</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2011</td><td>anonymous</td><td>10 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2011</td><td>magma</td><td>100 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2011</td><td>I2P services sponge</td><td></td><td>-100 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2011</td><td>anonymous</td><td>20 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2011</td><td>anonymous</td><td>50 &euro;</td><td></td><td>I2P debian package bounty</td></tr>
<tr><td>Apr, 2011</td><td>anonymous</td><td>10 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2011</td><td>anonymous</td><td>10 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2011</td><td>anonymous</td><td>0.06 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2011</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2011</td><td>anonymous</td><td>5 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2011</td><td>anonymous</td><td>20 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2011</td><td>anonymous</td><td>10 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2011</td><td>Max Koda</td><td>10 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2011</td><td>anonymous</td><td>1.180001 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2011</td><td>ZZZ</td><td></td><td>250.06 &euro;</td><td>trimslice dev device for ZZZ</td></tr>
<tr><td>Jun, 2011</td><td>An anonymous secret society society@mail.i2p</td><td>200 &euro;</td><td></td><td>SILC bounty</td></tr>
<tr><td>Jun, 2011</td><td>Flattr</td><td>104 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2011</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2011</td><td>anonymous</td><td>3 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2011</td><td>anonymous</td><td></td><td>-13.6 BTC</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2011</td><td>anonymous</td><td>22.5 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jul, 2011</td><td>hamada</td><td></td><td>-20 BTC</td><td>arabic bounty</td></tr>
<tr><td>Jul, 2011</td><td>anonymous</td><td>0.2 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jul, 2011</td><td>psychonaut</td><td>30 &euro;</td><td></td><td>Bitcoin client bounty</td></tr>
<tr><td>Jul, 2011</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jul, 2011</td><td>anonymous</td><td>5 GBP</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jul, 2011</td><td>anonymous</td><td>10 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jul, 2011</td><td>anonymous</td><td>10 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Aug, 2011</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Aug, 2011</td><td>An anonymous secret society society@mail.i2p</td><td>20 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Aug, 2011</td><td>anonymous</td><td>15 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Aug, 2011</td><td>ZZZ</td><td></td><td>$150 US</td><td>travel expenses for ZZZ</td></tr>
<tr><td>Sep, 2011</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Sep, 2011</td><td>anonymous</td><td>5 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Sep, 2011</td><td>maxkoda.i2p</td><td>1.303 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Sep, 2011</td><td>anonymous</td><td>1.2 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2011</td><td>anonymous</td><td>12.1347 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2011</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2011</td><td>anonymous</td><td>20 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2011</td><td>anonymous</td><td>5 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2011</td><td>anonymous</td><td>10 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2011</td><td>anonymous</td><td>5 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2011</td><td>uglic</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2011</td><td>anonymous</td><td>10 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2011</td><td>vention</td><td>73 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2011</td><td>anonymous</td><td>20 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2011</td><td>4get</td><td></td><td>163 &euro;</td><td>RU translation delayed payment</td></tr>
<tr><td>Nov, 2011</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Nov, 2011</td><td>anonymous</td><td>10 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Nov, 2011</td><td>Daniel Liabeuf</td><td>20 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Nov, 2011</td><td>anonymous</td><td>15 &euro;</td><td></td><td>Bounty eepsites in datastorage</td></tr>
<tr><td>Nov, 2011</td><td>maxkoda</td><td>5.23 BTC</td><td></td><td>bounty BTC client in I2P</td></tr>
<tr><td>Nov, 2011</td><td>anonymous</td><td>0.512 BTC</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2011</td><td>anonymous</td><td>30 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2011</td><td>silc bounty</td><td>100 &euro;</td><td></td><td>ReturningNovice</td></tr>
<tr><td>Dec, 2011</td><td>silc bounty</td><td>100 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2011</td><td>ReturningNovice</td><td>50 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2011</td><td>ReturningNovice</td><td>50 &euro;</td><td></td><td>Sponge</td></tr>
<tr><td>Dec, 2011</td><td>anonymous</td><td>5 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2011</td><td>anonymous</td><td>5 &euro;</td><td></td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2011</td><td>maxkoda</td><td>5.01 BTC</td><td></td><td>bounty BTC client in I2P</td></tr>
<tr><td>Dec, 2011</td><td>anonymous</td><td>0.4825475 BTC</td><td></td><td>Sponge</td></tr>
<tr><td>Dec, 2011</td><td>anonymous</td><td>5,54436182 BTC</td><td></td><td>general fund</td></tr>
<tr><td>Dec, 2011</td><td>PayPal</td><td></td><td>100 &euro;</td><td>PayPal fees 2011</td></tr>
</table>
<br />
<br />
<b>{{ _('Previous to 2011 donations:') }}</b><br />
<table border="1">
<tr><td>Dec, 2010</td><td>anonymous</td><td>20 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2010</td><td>anonymous</td><td>30 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2010</td><td>anonymous</td><td>$20 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2010</td><td>anonymous</td><td>$10 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2010</td><td>anonymous</td><td>20 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2010</td><td>anonymous</td><td>1.50 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2010</td><td>anonymous</td><td>10 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Nov, 2010</td><td>anonymous</td><td>20 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2010</td><td>anonymous</td><td>20 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2010</td><td>anonymous</td><td>15 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2010</td><td>ru bounty payback</td><td>$230 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2010</td><td>R.Schwabe</td><td>10 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2010</td><td>Flattr</td><td>29,40 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Sep, 2010</td><td>anonymous</td><td>10 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Sep, 2010</td><td>anonymous</td><td>11 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Sep, 2010</td><td>anonymous</td><td>10 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Sep, 2010</td><td>anonymous</td><td>20 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Sep, 2010</td><td>R.Schwabe</td><td>10 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Sep, 2010</td><td>anonymous</td><td>15 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Aug, 2010</td><td>anonymous</td><td>20 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Aug, 2010</td><td>anonymous</td><td>10 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jul, 2010</td><td>anonymous</td><td>6,50 PLN</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jul, 2010</td><td>anonymous</td><td>10 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jul, 2010</td><td>anonymous</td><td>5 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jul, 2010</td><td>anonymous</td><td>20 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jul, 2010</td><td>anonymous</td><td>30 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2010</td><td>anonymous</td><td>5 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2010</td><td>anonymous</td><td>20 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2010</td><td>anonymous</td><td>8 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2010</td><td>anonymous</td><td>10 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2010</td><td>anonymous</td><td>$ 20 CAD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2010</td><td>anonymous</td><td>10 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2010</td><td>anonymous</td><td>7 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2010</td><td>anonymous</td><td>&pound; 60 SCO</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2010</td><td>anonymous</td><td>10 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2010</td><td>anonymous</td><td>200 &euro;</td><td>Datastorage bounty</td></tr>
<tr><td>Apr, 2010</td><td>anonymous</td><td>10 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2010</td><td>Mozartito</td><td>5 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Mar, 2010</td><td>anonymous</td><td>140 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Mar, 2010</td><td>anonymous</td><td>10 &euro;</td><td>Abo {{ _('General fund') }}</td></tr>
<tr><td>Mar, 2010</td><td>anonymous</td><td>10 &euro;</td><td>Abo {{ _('General fund') }}</td></tr>
<tr><td>Feb, 2010</td><td>anonymous</td><td>10 &euro;</td><td>Abo {{ _('General fund') }}</td></tr>
<tr><td>Feb, 2010</td><td>anonymous</td><td>5 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2010</td><td>anonymous</td><td>10 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2010</td><td>anonymous</td><td>500 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2010</td><td>bernerbaer</td><td>50 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2010</td><td>anonymous</td><td>15 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2009-Jan, 2010</td><td>neutron</td><td>20 &euro;/month</td><td>outproxy fund</td></tr>
<tr><td>Jan, 2010</td><td>anonymous</td><td>$20 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2010</td><td>anonymous</td><td>6.80 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2010</td><td>anonymous</td><td>10 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2009</td><td>anonymous</td><td>5 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Dec, 2009</td><td>anonymous</td><td>35 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Nov, 2009</td><td>russian donor</td><td>230 $</td><td>Russian translation bounty</td></tr>
<tr><td>Nov, 2009</td><td>anonymous</td><td>10 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2009</td><td>echelon</td><td>10 &euro;</td><td>i2phex bounty</td></tr>
<tr><td>Oct, 2009</td><td>arne bab</td><td>10 &euro;</td><td>i2phex bounty</td></tr>
<tr><td>Oct, 2009</td><td>anonymous</td><td>10 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Aug, 2009</td><td>anonymous</td><td>400 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Aug, 2009</td><td>anonymous</td><td>10 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Aug, 2009</td><td>anonymous</td><td>100 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jul, 2009</td><td>G.Klaus</td><td>15 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jul, 2009</td><td>R.Schwabe</td><td>$20 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2009</td><td>anonymous</td><td>10 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2009</td><td>Cendre</td><td>20 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2009</td><td>M.Hilbig</td><td>10 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2009</td><td>anonymous</td><td>20 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2009</td><td>EoL</td><td>10 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2009</td><td>anonymous</td><td>10 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2009</td><td>anonymous</td><td>60 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2009</td><td>Gilgongo</td><td>15 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2009</td><td>Amiga4000</td><td>50 &euro;</td><td>I2P vuze plugin bounty</td></tr>
<tr><td>Mar, 2009</td><td>[anonymous]</td><td>50 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2009</td><td>[anonymous]</td><td>30 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2009</td><td>DVT</td><td>20 &euro;</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2008</td><td>eche|on</td><td>500.0 &euro;</td><td>Datastorage bounty</td></tr>
<tr><td>Mar, 2007</td><td>zzz</td><td>$200 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Nov, 2006-Dec, 2007</td><td>[anonymous]</td><td>$10 USD/month</td><td>general fund</td></tr>
<tr><td>Dec, 2006</td><td>bar</td><td colspan="2">New mac testing machine</td></tr>
<tr><td>Dec, 2006</td><td>[anonymous]</td><td>$200 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2006</td><td>[anonymous]</td><td>$150 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2006</td><td>[anonymous]</td><td>$100 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2005-Oct, 2006</td><td>Eol</td><td>$10 USD/month</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Oct, 2006</td><td>Peter</td><td>$750 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2006</td><td>[anonymous]</td><td>$450 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2006</td><td>[anonymous]</td><td>$10 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jun, 2006</td><td>[anonymous]</td><td>$10 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>May, 2006</td><td>athena</td><td>$135 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2006</td><td>postman</td><td>$300 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2006</td><td>[anonymous]</td><td>$300 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2006</td><td>[anonymous]</td><td>$500 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2006</td><td>[anonymous]</td><td>$100 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2006</td><td>[anonymous]</td><td>$10 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2006</td><td>[anonymous]</td><td>$50 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2006</td><td>[anonymous]</td><td>$15 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Apr, 2006</td><td>[anonymous]</td><td>$12 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Mar, 2006</td><td>[anonymous]</td><td>$30 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Mar, 2006</td><td>[anonymous]</td><td>$800 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Mar, 2006</td><td>bar</td><td colspan="2">New development machine</td></tr>
<tr><td>Mar, 2006</td><td>postman</td><td>$300 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Mar, 2006</td><td>[anonymous]</td><td>$5 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Feb, 2006</td><td>[anonymous]</td><td>$50 USD</td><td>{{ _('General fund') }}</td></tr>
<tr><td>Jan, 2006</td><td>[anonymous]</td><td>$500 USD</td><td>Unit test bounty</td></tr>
<tr><td>Jan, 2006</td><td>[anonymous]</td><td>$25 USD</td><td>I2P general fund</td></tr>
<tr><td>Jan, 2006</td><td>[anonymous]</td><td>$10 USD</td><td>I2P general fund</td></tr>
<tr><td>Jan, 2006</td><td>[anonymous]</td><td>$40 USD</td><td>I2P general fund</td></tr>
<tr><td>Jan, 2006</td><td>[anonymous]</td><td>$50 USD</td><td>I2P general fund</td></tr>
<tr><td>Jan, 2006</td><td>[anonymous]</td><td>$20 USD</td><td>I2P general fund</td></tr>
<tr><td>Dec, 2005</td><td>[anonymous]</td><td>$10 USD</td><td>I2P general fund</td></tr>
<tr><td>Dec, 2005</td><td>[anonymous]</td><td>$10 USD</td><td>I2P general fund</td></tr>
<tr><td>Nov, 2005-Dec, 2007</td><td>[anonymous]</td><td>$10 USD/month</td><td>general fund</td></tr>
<tr><td>Nov, 2005-Dec, 2007</td><td>[anonymous]</td><td>$50 USD/month</td><td>general fund</td></tr>
<tr><td>Nov, 2005</td><td>aum</td><td>$10 USD</td><td>I2P general fund</td></tr>
<tr><td>Nov, 2005</td><td>aum</td><td>$10 USD</td><td>I2P general fund</td></tr>
<tr><td>Nov, 2005</td><td>[anonymous]</td><td>$50 USD</td><td>I2P general fund</td></tr>
<tr><td>Nov, 2005</td><td>[anonymous]</td><td>$100 USD</td><td>I2P general fund</td></tr>
<tr><td>Nov, 2005</td><td>Aurimas Fiseras</td><td>$20 USD</td><td>I2P general fund</td></tr>
<tr><td>Nov, 2005</td><td>[anonymous]</td><td>$500 USD</td><td>I2P general fund</td></tr>
<tr><td>Oct, 2005-Dec, 2007</td><td>[anonymous]</td><td>$200 USD/month</td><td>general fund</td></tr>
<tr><td>Oct, 2005</td><td>Doubtful salmon</td><td>$120 USD</td><td>Bundling bounties</td></tr>
<tr><td>Oct, 2005</td><td>[anonymous]</td><td>$1000 USD</td><td>I2P general fund</td></tr>
<tr><td>Sep, 2005</td><td>[anonymous]</td><td>$25 USD</td><td>GCJ bounty</td></tr>
<tr><td>Sep, 2005</td><td>[anonymous]</td><td>$25 USD</td><td>I2P general fund</td></tr>
<tr><td>Jul, 2005</td><td>Anthony Skipper</td><td>$50 USD</td><td>I2P general fund</td></tr>
<tr><td>Jul, 2005</td><td>Chris Wong</td><td>$50 USD</td><td>I2P general fund</td></tr>
<tr><td>Jun-Nov, 2005</td><td>[anonymous]</td><td>$60 USD</td><td>I2P general fund</td></tr>
<tr><td>Jun, 2005</td><td>[anonymous]</td><td>$3 USD</td><td>I2P general fund</td></tr>
<tr><td>May, 2005</td><td>Timothy Wesson</td><td>$60 USD</td><td>I2P general fund</td></tr>
<tr><td>Apr, 2005</td><td>Zlatin Balevsky</td><td>$500 USD</td><td>Unit test bounty</td></tr>
<tr><td>Apr, 2005</td><td>Dale Jefferson</td><td>$10 USD</td><td>I2P general fund</td></tr>
<tr><td>Mar, 2005</td><td>Synonymous</td><td>$3.45 USD</td><td>I2P general fund</td></tr>
<tr><td>Mar, 2005-Sep, 2005</td><td>David Hjelm</td><td>$10 USD</td><td>I2P general fund</td></tr>
<tr><td>Feb, 2005</td><td>Marcus Felker</td><td>$20 USD</td><td>I2P general fund</td></tr>
<tr><td>Feb-Dec, 2005</td><td>Sebastian Spaeth</td><td>$200 USD</td><td>I2P general fund</td></tr>
<tr><td>Jan, 2005-Dec, 2007</td><td>[anonymous]</td><td>$10 USD/month</td><td>general fund</td></tr>
<tr><td>Jan, 2005-Jun, 2005</td><td>Martin Stares</td><td>$60 USD</td><td>I2P general fund</td></tr>
<tr><td>Jan, 2005</td><td>Nico Zimmerman</td><td>$2 USD</td><td>I2P general fund</td></tr>
<tr><td>Nov, 2004-Dec, 2007</td><td>jnymo</td><td>$10 USD/month</td><td>general fund</td></tr>
<tr><td>Dec, 2004, May, 2005</td><td>Elliot Turner</td><td>$350 USD</td><td>I2P general fund</td></tr>
<tr><td>Dec, 2004</td><td>[anonymous]</td><td>$5 USD</td><td>I2P general fund</td></tr>
<tr><td>Nov, 2004</td><td>modulus</td><td>$40 USD</td><td>I2P general fund</td></tr>
<tr><td>Nov, 2004</td><td>Salvador Petit</td><td>$10 USD</td><td>I2P general fund</td></tr>
<tr><td>Nov, 2004</td><td>Philip Bock</td><td>$100 USD</td><td>I2P general fund</td></tr>
<tr><td>Nov, 2004</td><td>cervantes</td><td>$154 USD</td><td>I2P general fund</td></tr>
<tr><td>Sep, 2004</td><td>[anonymous]</td><td>$20 USD</td><td>I2P general fund</td></tr>
<tr><td>Sep, 2004</td><td>[anonymous]</td><td>$400 USD</td><td>I2P general fund</td></tr>
<tr><td>Aug, 2004-Apr, 2005</td><td>nickster</td><td>$90 USD</td><td>I2P general fund</td></tr>
<tr><td>May, 2004</td><td>protokol</td><td>$2.24 USD</td><td>I2P general fund</td></tr>
<tr><td>May, 2004-Sep, 2005</td><td>Jeff Teitel</td><td>$135 USD</td><td>I2P general fund</td></tr>
<tr><td>Apr, 2004-Dec, 2004</td><td>eco</td><td>$150 USD</td><td>I2P general fund, GCJ bounty</td></tr>
<tr><td>Apr, 2004</td><td>wilde</td><td>$60 USD</td><td>MyI2P bounty</td></tr>
<tr><td>Mar, 2004</td><td>bla</td><td>$15 USD</td><td>I2P general fund</td></tr>
<tr><td>Mar, 2004-Apr, 2005</td><td>duck</td><td>$720 USD</td><td>Unit test and other bounties</td></tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,104 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Intro') }}{% endblock %}
{% block content %}
<h1>{{ _('The Invisible Internet Project') }} (I2P)</h1>
<p>{% trans -%}
I2P is an anonymous network, exposing a simple layer that applications can
use to anonymously and securely send messages to each other. The network itself is
strictly message based (a la
<a href="http://en.wikipedia.org/wiki/Internet_Protocol">IP</a>), but there is a
library available to allow reliable streaming communication on top of it (a la
<a href="http://en.wikipedia.org/wiki/Transmission_Control_Protocol">TCP</a>).
All communication is end to end encrypted (in total there are four layers of
encryption used when sending a message), and even the end points ("destinations")
are cryptographic identifiers (essentially a pair of <a href="http://en.wikipedia.org/wiki/Public_key_encryption">public keys</a>).
{%- endtrans %}</p>
<h2>{{ _('How does it work?') }}</h2>
<p>{% trans tunnelrouting=site_url('docs/how/tunnel-routing') -%}
To anonymize the messages sent, each client application has their I2P "router"
build a few inbound and outbound "<a href="{{ tunnelrouting }}">tunnels</a>" - a
sequence of peers that pass messages in one direction (to and from the client,
respectively). In turn, when a client wants to send a message to another client,
the client passes that message out one of their outbound tunnels targeting one of the
other client's inbound tunnels, eventually reaching the destination. Every
participant in the network chooses the length of these tunnels, and in doing so,
makes a tradeoff between anonymity, latency, and throughput according to their
own needs. The result is that the number of peers relaying each end to end
message is the absolute minimum necessary to meet both the sender's and the
receiver's threat model.
{%- endtrans %}</p>
<p>{% trans netdb=site_url('docs/how/network-database') -%}
The first time a client wants to contact another client, they make a query
against the fully distributed "<a href="{{ netdb }}">network
database</a>" - a custom structured <a href="http://en.wikipedia.org/wiki/Distributed_hash_table">
distributed hash table (DHT)</a> based off the
<a href="http://en.wikipedia.org/wiki/Kademlia"> Kademlia algorithm</a>. This is done
to find the other client's inbound tunnels efficiently, but subsequent messages
between them usually includes that data so no further network database lookups
are required.
{%- endtrans %}</p>
<p>{% trans docs=site_url('docs') -%}
More details about how I2P works are <a href="{{ docs }}">available</a>.
{%- endtrans %}</p>
<h2>{{ _('What can you do with it?') }}</h2>
<p>{% trans i2ptunnel=site_url('docs/api/i2ptunnel') -%}
Within the I2P network, applications are not restricted in how they can
communicate - those that typically use UDP can make use of the base I2P
functionality, and those that typically use TCP can use the TCP-like streaming
library. We have a generic TCP/I2P bridge application
("<a href="{{ i2ptunnel }}">I2PTunnel</a>") that enables people to forward TCP streams
into the I2P network as well as to receive streams out of the network and
forward them towards a specific TCP/IP address.
{%- endtrans %}</p>
<p>{% trans -%}
I2PTunnel is currently used to let people run their own anonymous website
("eepsite") by running a normal webserver and pointing an I2PTunnel 'server'
at it, which people can access anonymously over I2P with a normal web browser
by running an I2PTunnel HTTP proxy ("eepproxy"). In addition, we use the same
technique to run an anonymous IRC network (where the IRC server is hosted
anonymously, and standard IRC clients use an I2PTunnel to contact it). There
are other application development efforts going on as well, such as one to
build an optimized swarming file transfer application (a la
<a href="http://www.bittorrent.com/">BitTorrent</a>), a
distributed data store (a la <a href="https://freenetproject.org/">Freenet</a> /
<a href="http://mnetproject.org/">MNet</a>), and a blogging system (a fully
distributed <a href="http://www.livejournal.com/">LiveJournal</a>), but those are
not ready for use yet.
{%- endtrans %}</p>
<p>{% trans -%}
I2P is not inherently an "outproxy" network - the client you send a message
to is the cryptographic identifier, not some IP address, so the message must
be addressed to someone running I2P. However, it is possible for that client
to be an outproxy, allowing you to anonymously make use of their Internet
connection. To demonstrate this, the "eepproxy" will accept normal non-I2P
URLs (e.g. "http://www.i2p.net") and forward them to a specific destination
that runs a <a href="http://www.squid-cache.org/">squid</a> HTTP proxy, allowing
simple anonymous browsing of the normal web. Simple outproxies like that are
not viable in the long run for several reasons (including the cost of running
one as well as the anonymity and security issues they introduce), but in
certain circumstances the technique could be appropriate.
{%- endtrans %}</p>
<p>{% trans team=site_url('about/team'), volunteer=site_url('get-involved'),
licenses=site_url('get-involved/develop/licenses'), sam=site_url('docs/api/sam'),
roadmap=site_url('get-involved/roadmap') -%}
The I2P development <a href="{{ team }}">team</a> is an open group, welcome to all
who are interested in <a href="{{ volunteer }}">getting involved</a>, and all of
the code is <a href="{{ licenses }}">open source</a>. The core I2P SDK and the
current router implementation is done in Java (currently working with both
sun and kaffe, gcj support planned for later), and there is a
<a href="{{ sam }}">simple socket based API</a> for accessing the network from
other languages (with a C library available, and both Python and Perl in
development). The network is actively being developed and has not yet reached
the 1.0 release, but the current <a href="{{ roadmap }}">roadmap</a> describes
our schedule.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,219 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Presentations on I2P') }}{% endblock %}
{% block content %}
<h1>{{ _('Presentations on I2P') }}</h1>
<p>{% trans papers=site_url('research/papers') -%}
Following are links to presentations, videos, and tutorials about I2P. Links to research papers on I2P are available <a href="{{ papers }}">here</a>.
{%- endtrans %}</p>
<p>{% trans email='press ~~~at~~~ i2p2.de' -%}
To request an addition to this page, please send to {{ email }}.
{%- endtrans %}</p>
<p>{% trans %}
Newest links are at the bottom of each section.
{%- endtrans %}</p>
<div class="links">
<h2>{{ _('Presentations') }}</h2>
<ul>
<li>{% trans mp3='http://invisibleip.sourceforge.net/iip/resources/codecon_0x90.mp3',
transcript='http://invisibleip.sourceforge.net/iip/resources/iip_transcript.txt' -%}
IIP Presentation at CodeCon
<a href="{{ mp3 }}">MP3 audio</a>
<a href="{{ transcript }}">transcript</a>
Lance James (0x90), February 2002.
{%- endtrans %}</li>
<li>{% trans mp3='http://invisibleip.sourceforge.net/iip/resources/toorconspeech.mp3',
slides='http://invisibleip.sourceforge.net/iip/resources/toorconspeech/' -%}
IIP Presentation at ToorCon
<a href="{{ mp3 }}">MP3 audio</a>
<a href="{{ slides }}">slides</a>
Lance James (0x90), September 2002.
{%- endtrans %}</li>
<li>{% trans video='http://www.youtube.com/watch?v=TsfdzfGZyu0',
pdf='http://events.ccc.de/congress/2007/Fahrplan/attachments/1017_24c3-i2p.pdf' -%}
<a href="{{ video }}">To Be or I2P</a>
(Youtube Video)
An introduction into anonymous communication with I2P.
<a href="{{ pdf }}">To Be or I2P (PDF presentation)</a>,
Jens Kubieziel, 24C3 Berlin, December 28, 2007.
{%- endtrans %}</li>
<li>{% trans video='http://marge.informatik.tu-chemnitz.de/archiv/CLT2009/V4-Sa1200-Security-Lars_Schimmer.mp4' -%}
<a href="{{ video }}">Video of I2P talk at Chemnitz Linux Tag</a>,
Lars Schimmer,
March 14-15, 2009
{%- endtrans %}</li>
<li>{% trans mp3='http://c2047862.cdn.cloudfiles.rackspacecloud.com/tnhc21.mp3' -%}
HOPE New York July 17, 2010 - Brief overview of I2P by zzz, at the end of Adrian Hong's talk
"Hackers for Human Rights".
<a href="{{ mp3 }}">MP3 audio</a>
{%- endtrans %}</li>
<li>{% trans link='http://www.irongeek.com/i.php?page=videos/shmoocon-firetalks-2011' -%}
<a href="{{ link }}">Into the I2P Darknet: Welcome to Cipherspace</a>
Adrian Crenshaw. Schmoocon Firetalk, January 2011
{%- endtrans %}</li>
<li>{% trans link='http://www.youtube.com/watch?v=TexNr_5J5AU' -%}
<a href="{{ link }}">Using techhnology to advance liberty</a>
(Youtube Video)
Eric Johnson.
<a href="http://agora.io/etienne">Agora I/O Unconference</a>, March 27, 2011.
I2P covered from 10:00 to 20:00 in the video.
{%- endtrans %}</li>
<li>{% trans pdf='http://patras.fosscomm.gr/talks/BSoD_Pub.pdf' -%}
<a href="{{ pdf }}">The Bright side of darknets</a>, FOSSCOMM Patras May 2011
{%- endtrans %}</li>
<li>{% trans link='http://www.youtube.com/watch?v=bI_1qlcwfE0' -%}
<a href="{{ link }}">Common Darknet Weaknesses</a>
(Youtube Video)
Adrian Crenshaw, <a href="http://aide.marshall.edu/">AIDE</a>, July 11-15, 2011.
{%- endtrans %}</li>
<li>{% trans link='http://www.irongeek.com/i.php?page=security/i2p-tor-workshop-notes' -%}
<a href="{{ link }}">I2P / Tor Workshop Notes</a>
Adrian Crenshaw. DEF CON 19, Las Vegas, August 6, 2011.
{%- endtrans %}</li>
<li>{% trans live='http://www.youtube.com/watch?v=xxKXkbohRZM',
studio='http://www.youtube.com/watch?v=xFxJ6Dc5ass',
slides='http://www.irongeek.com/downloads/Adrian-Crenshaw-darknet-weaknesses.pptx' -%}
<a href="{{ live }}">Cipherspaces/Darknets: An Overview Of Attack Strategies -
DEF CON Live version (Youtube Video)</a>,
<a href="{{ studio }}">"Studio" version (Youtube Video)</a>,
<a href="{{ slides }}">Slides (ppt)</a>
Adrian Crenshaw. DEF CON 19, Las Vegas, August 7, 2011.
{%- endtrans %}</li>
<li>{% trans -%}
<a href="http://0x375.org/">Modern cipherspace ecosystems</a>, 0x375 0x06 4/11/2011
{%- endtrans %}</li>
</ul>
<h2>{{ _('Tutorials') }}</h2>
<ul>
<li>{% trans link='http://www.youtube.com/watch?v=5J3nh1DoRMw' -%}
<a href="{{ link }}">I2P Windows Tutorial</a>
(Youtube Video)
This guide will show you how to install I2P in Windows XP.
By <a href="http://telecomix.org/">Telecomix</a>
{%- endtrans %}</li>
<li>
<li>{% trans link='http://www.youtube.com/watch?v=QeRN2G9VW5E' -%}
<a href="{{ link }}">I2P Debian Tutorial</a>
(Youtube Video)
This will guide you through how to install I2P on a Debian Linux System.
By <a href="http://telecomix.org/">Telecomix</a>
{%- endtrans %}</li>
<li>
<li>{% trans link='http://www.youtube.com/watch?v=2ylW85vc7SA' -%}
<a href="{{ link }}">How to set up anonymous site in I2P</a>
(Youtube Video)
How to set up an anonymous web site in I2P.
By <a href="http://telecomix.org/">Telecomix</a>
{%- endtrans %}</li>
<li>{% trans link='http://www.youtube.com/watch?v=d8mvGZqVgE4' -%}
<a href="{{ link }}">I2P Tutorial Mac OS X</a>
(Youtube Video)
A tutorial on how to run i2p on Mac OS X and how to connect to irc.telecomix.i2p.
By <a href="http://telecomix.org/">Telecomix</a>
{%- endtrans %}</li>
<li>{% trans link='http://www.youtube.com/watch?v=5jv7tVVJdTQ' -%}
<a href="{{ link }}">Felix Atari explains the basic principles of I2P</a>
(Youtube Video)
Agent Felix Atari of the Telecomix Crypto Munitions Bureau.
By <a href="http://telecomix.org/">Telecomix</a>
{%- endtrans %}</li>
<li>{% trans link='http://www.youtube.com/watch?v=WyN_QK-_3GA' -%}
<a href="{{ link }}">How to get onto I2P, the anonymous P2P Darknet (Windows Install)</a>
(Youtube Video)
This tutorial shows how to install and configure software needed to access I2P.
{%- endtrans %}</li>
<li>{% trans link='http://www.youtube.com/watch?v=q4owyd_CaGc' -%}
<a href="{{ link }}">How to connect to I2P</a>
(Youtube Video)
How to install I2P on Ubuntu.
{%- endtrans %}</li>
<li>{% trans link='http://www.irongeek.com/i.php?page=videos/i2p-darknet-software-in-linux' -%}
<a href="{{ link }}">Installing the I2P darknet software in Linux</a>
(Video)
Adrian Crenshaw.
January 2011
{%- endtrans %}</li>
<li>{% trans link='http://www.youtube.com/watch?v=NV90TRs_pGE' -%}
<a href="{{ link }}">Short garlic routing animation</a>
(Youtube Video)
Adrian Crenshaw.
{% endtrans %}</li>
</ul>
<h2>{{ _('Articles and Interviews') }}</h2>
<ul>
<li>{% trans link1='http://invisibleip.sourceforge.net/iip/mediaDCInterview1.php',
link2='http://invisibleip.sourceforge.net/iip/mediaDCInterview2.php' -%}
0x90 Interviewed by DistributedCity
<a href="{{ link1 }}">Part 1</a>
<a href="{{ link2 }}">Part 2</a>
July 26, 2002.
{%- endtrans %}</li>
<li>{% trans link='http://invisibleip.sourceforge.net/iip/resources/elpais-iip.txt' -%}
0x90 Interviewed by El Pais
(original in Spanish)
<a href="{{ link }}">English translation</a>
October 31, 2002.
{%- endtrans %}</li>
<li>{% trans link='http://www.businessweek.com/magazine/content/03_37/b3849089_mz063.htm' -%}
<a href="{{ link }}">2003 Business Week article referencing invisiblenet</a>
{%- endtrans %}</li>
<li>{% trans link='http://www.netzwelt.de/news/75371-i2p-das-anonyme-netz-im.html' -%}
<a href="{{ link }}">Netzwelt.de article about being anonymous in the Internet</a>
(German)
November 2007.
{%- endtrans %}</li>
<li>{% trans link='http://www.gulli.com/news/i2p-an-anonymous-network-2009-03-09/',
german='http://www.gulli.com/news/i2p-anonymes-netzwerk-im-2009-03-09/' -%}
<a href="{{ link }}">zzz interviewed by gulli.com</a>
March 2009
<a href="{{ german }}">German translation</a>
{%- endtrans %}</li>
<li>{% trans mp3='http://www.isdpodcast.com/podcasts/infosec-daily-podcast-episode-454.mp3' -%}
<a href="{{ mp3 }}">zzz interviewed on the InfoSec Daily Podcast Ep. 454 (mp3)</a>
August 18, 2011
{%- endtrans %}</li>
<li>{% trans link='http://how-to.linuxcareer.com/i2p-anonymity-for-the-masses' -%}
<a href="{{ link }}">I2P - Anonymity for the Masses</a>,
Jonathan Cox,
November 11, 2011.
{%- endtrans %}</li>
<li>{% trans mp3='http://www.isdpodcast.com/podcasts/infosec-daily-podcast-episode-596.mp3' -%}
<a href="{{ mp3 }}">zzz and Lance James interviewed on the InfoSec Daily Podcast Ep. 596 (mp3)</a>
February 16, 2012
{%- endtrans %}</li>
</div>
{% endblock %}

View File

@@ -0,0 +1,157 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Future Performance Improvements') }}{% endblock %}
{% block content %}
{% block lastupdated %}{{ _('August 2010') }}{% endblock %}
{% block accuratefor %}0.8{% endblock %}
<p>{% trans -%}
There are a few major techniques that can be done to improve the perceived
performance of I2P - some of the following are CPU related, others bandwidth
related, and others still are protocol related. However, all of those
dimensions affect the latency, throughput, and perceived performance of the
network, as they reduce contention for scarce resources. This list is of course
not comprehensive, but it does cover the major ones that are seen.
{%- endtrans %}</p>
<p>{% trans history=site_url('about/performance/history') -%}
For past performance improvements see the <a href="{{ history }}">
Performance History</a>.
{%- endtrans %}</p>
<h2>{{ _('Better peer profiling and selection') }}</h2>
<p>{% trans sybilpdf='http://www.cs.rice.edu/Conferences/IPTPS02/101.pdf'-%}
Probably one of the most important parts of getting faster performance will
be improving how routers choose the peers that they build their tunnels through
- making sure they don't use peers with slow links or ones with fast links that
are overloaded, etc. In addition, we've got to make sure we don't expose
ourselves to a <a href="{{ sybilpdf }}">Sybil</a> attack
from a powerful adversary with lots of fast machines.
{%- endtrans %}</p>
<h2>{{ _('Network database tuning') }}</h2>
<p>{% trans -%}
We're going to want to be more efficient with the network database's healing
and maintenance algorithms - rather than constantly explore the keyspace for new
peers - causing a significant number of network messages and router load - we
can slow down or even stop exploring until we detect that there's something new
worth finding (e.g. decay the exploration rate based upon the last time someone
gave us a reference to someone we had never heard of). We can also do some
tuning on what we actually send - how many peers we bounce back (or even if we
bounce back a reply), as well as how many concurrent searches we perform.
{%- endtrans %}</p>
<h2>{{ _('Session Tag Tuning and Improvements') }}</h2>
<p>{% trans elgamalaes=site_url('docs/how/elgamal-aes') -%}
The way the <a href="{{ elgamalaes }}">ElGamal/AES+SessionTag</a> algorithm
works is by managing a set of random one-time-use 32 byte arrays, and expiring
them if they aren't used quickly enough. If we expire them too soon, we're
forced to fall back on a full (expensive) ElGamal encryption, but if we don't
expire them quickly enough, we've got to reduce their quantity so that we don't
run out of memory (and if the recipient somehow gets corrupted and loses some
tags, even more encryption failures may occur prior to detection). With some
more active detection and feedback driven algorithms, we can safely and more
efficiently tune the lifetime of the tags, replacing the ElGamal encryption with
a trivial AES operation.
{%- endtrans %}</p>
<p>{% trans elgamalaes=site_url('docs/how/elgamal-aes') -%}
Additional ideas for improving Session Tag delivery are described on the
<a href="{{ elgamalaes }}#future">ElGamal/AES+SessionTag page</a>.
{%- endtrans %}</p>
<h2 id="prng">{{ _('Migrate sessionTag to synchronized PRNG') }}</h2>
<p>{% trans elgamalaes=site_url('docs/how/elgamal-aes') -%}
Right now, our <a href="{{ elgamalaes }}">ElGamal/AES+SessionTag</a>
algorithm works by tagging each encrypted message with a unique random
32 byte nonce (a "session tag"), identifying that message as being encrypted
with the associated AES session's key. This prevents peers from distinguishing
messages that are part of the same session, since each message has a completely
new random tag. To accomplish this, every few messages bundle a whole
new set of session tags within the encrypted message itself, transparently
delivering a way to identify future messages. We then have to keep track
of what messages are successfully delivered so that we know what tags
we may use.
{%- endtrans %}</p>
<p>{% trans -%}
This works fine and is fairly robust, however it is inefficient in terms
of bandwidth usage, as it requires the delivery of these tags ahead of
time (and not all tags may be necessary, or some may be wasted, due to
their expiration). On average though, predelivering the session tag costs
32 bytes per message (the size of a tag). As Taral suggested though, that
size can be avoided by replacing the delivery of the tags with a synchronized
PRNG - when a new session is established (through an ElGamal encrypted
block), both sides seed a PRNG for use and generate the session tags on
demand (with the recipient precalculating the next few possible values
to handle out of order delivery).
{%- endtrans %}</p>
<h2>{{ _('Longer lasting tunnels') }}</h2>
<p>{% trans -%}
The current default tunnel duration of 10 minutes is fairly arbitrary, though
it "feels okay". Once we've got tunnel healing code and more effective failure
detection, we'll be able to more safely vary those durations, reducing the
network and CPU load (due to expensive tunnel creation messages).
{%- endtrans %}</p>
<p>{% trans -%}
This appears to be an easy fix for high load on the big-bandwidth routers, but
we should not resort to it until we've tuned the tunnel building algorithms further.
However, the 10 minute tunnel lifetime is hardcoded in quite a few places,
so substantial effort would be required to change the duration.
Also, it would be difficult to maintain backward compatibility with such a change.
{%- endtrans %}</p>
<p>{% trans -%}
Currently, since the network average tunnel build success rate is fairly high,
there are no current plans to extend tunnel lifetime.
{%- endtrans %}</p>
<h2>{{ _('Adjust the timeouts') }}</h2>
<p>{% trans -%}
Yet another of the fairly arbitrary but "okay feeling" things we've got are the
current timeouts for various activities. Why do we have a 60 second "peer
unreachable" timeout? Why do we try sending through a different tunnel that a
LeaseSet advertises after 10 seconds? Why are the network database queries
bounded by 60 or 20 second limits? Why are destinations configured to ask for a
new set of tunnels every 10 minutes? Why do we allow 60 seconds for a peer to
reply to our request that they join a tunnel? Why do we consider a tunnel that
doesn't pass our test within 60 seconds "dead"?
{%- endtrans %}</p>
<p>{% trans -%}
Each of those imponderables can be addressed with more adaptive code, as well
as tunable parameters to allow for more appropriate tradeoffs between
bandwidth, latency, and CPU usage.
{%- endtrans %}</p>
<h2>{{ _('Full streaming protocol improvements') }}</h2>
<ul>
<li>
{% trans -%}
Perhaps re-enable the interactive stream profile (the
current implementation only uses the bulk stream profile).
{%- endtrans %}
</li>
<li>
{% trans -%}
Client level bandwidth limiting (in either or both directions on a stream,
or possibly shared across multiple streams). This would be in addition to
the router's overall bandwidth limiting, of course.
{%- endtrans %}
</li>
<li>
{% trans -%}
Access control lists (only allowing streams to or from certain other known
destinations).
{%- endtrans %}
</li>
<li>
{% trans -%}
Web controls and monitoring the health of the various streams, as well
as the ability to explicitly close or throttle them.
{%- endtrans %}
</li>
</ul>
<p>{% trans streaming=site_url('docs/api/streaming') -%}
Additional ideas for improving the streaming library are described on the
<a href="{{ streaming }}#future">streaming library page</a>.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,152 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Performance History') }}{% endblock %}
{% block content %}
<p>{% trans performance=site_url('about/performance') -%}
Notable performance improvements have been made using the techniques below.
There is more to do, see the <a href="{{ performance }}">Performance</a> page
for current issues and thoughts.
{%- endtrans %}</p>
<h2>{{ _('Native math') }}</h2>
<b>[{{ _('implemented') }}]</b>
<p>{% trans modpow='http://docs.oracle.com/javase/1.4.2/docs/api/java/math/BigInteger.html#modPow(java.math.BigInteger,%20java.math.BigInteger)',
gmp='http://gmplib.org/',
jbigi=site_url('misc/jbigi') -%}
When I last profiled the I2P code, the vast majority of time was spent within
one function: java.math.BigInteger's
<a href="{{ modpow }}">modPow</a>.
Rather than try to tune this method, we'll call out to
<a href="{{ gmp }}">GNU MP</a> - an insanely fast math library
(with tuned assembler for many architectures). (<i>Editor: see
<a href="{{ jbigi }}">NativeBigInteger for faster public key cryptography</a></i>)
{%- endtrans %}</p>
<p>{% trans %}
ugha and duck are working on the C/JNI glue code, and the existing java code
is already deployed with hooks for that whenever its ready. Preliminary results
look fantastic - running the router with the native GMP modPow is providing over
a 800&#37; speedup in encryption performance, and the load was cut in half. This
was just on one user's machine, and things are nowhere near ready for packaging
and deployment, yet.
{%- endtrans %}</p>
<h2>{% trans %}Garlic wrapping a "reply" LeaseSet{% endtrans %}</h2>
<b>[{{ _('implemented but needs tuning') }}]</b>
<p>{% trans -%}
This algorithm tweak will only be relevant for applications that want their
peers to reply to them (though that includes everything that uses I2PTunnel or
mihi's ministreaming lib):
{%- endtrans %}</p>
<p>{% trans -%}
Previously, when Alice sent Bob a message, when Bob replied he had to do a
lookup in the network database - sending out a few requests to get Alice's
current LeaseSet. If he already has Alice's current LeaseSet, he can instead
just send his reply immediately - this is (part of) why it typically takes a
little longer talking to someone the first time you connect, but subsequent
communication is faster. Currently - for all clients - we wrap
the sender's current LeaseSet in the garlic that is delivered to the recipient,
so that when they go to reply, they'll <i>always</i> have the LeaseSet locally
stored - completely removing any need for a network database lookup on replies.
This trades off a large portion of the sender's bandwidth for that faster reply.
If we didn't do this very often,
overall network bandwidth usage would decrease, since the recipient doesn't
have to do the network database lookup.
{%- endtrans %}</p>
<p>{% trans -%}
For unpublished LeaseSets such as "shared clients", this is the only way to
get the LeaseSet to Bob. Unfortunately this bundling every time adds
almost 100&#37; overhead to a high-bandwidth connection, and much more to
a connection with smaller messages.
{%- endtrans %}</p>
<p>{% trans -%}
Changes scheduled for release 0.6.2 will bundle the LeaseSet only when
necessary, at the beginning of a connection or when the LeaseSet changes.
This will substantially reduce the total overhead of I2P messaging.
{%- endtrans %}</p>
<h2>{{ _('More efficient TCP rejection') }}</h2>
<b>[{{ _('implemented') }}]</b>
<p>{% trans -%}
At the moment, all TCP connections do all of their peer validation after
going through the full (expensive) Diffie-Hellman handshaking to negotiate a
private session key. This means that if someone's clock is really wrong, or
their NAT/firewall/etc is improperly configured (or they're just running an
incompatible version of the router), they're going to consistently (though not
constantly, thanks to the shitlist) cause a futile expensive cryptographic
operation on all the peers they know about. While we will want to keep some
verification/validation within the encryption boundary, we'll want to update the
protocol to do some of it first, so that we can reject them cleanly
without wasting much CPU or other resources.
{%- endtrans %}</p>
<h2>{{ _('Adjust the tunnel testing') }}</h2>
<b>[{{ _('implemented') }}]</b>
<p>{% trans -%}
Rather than going with the fairly random scheme we have now, we should use a
more context aware algorithm for testing tunnels. e.g. if we already know its
passing valid data correctly, there's no need to test it, while if we haven't
seen any data through it recently, perhaps its worthwhile to throw some data its
way. This will reduce the tunnel contention due to excess messages, as well as
improve the speed at which we detect - and address - failing tunnels.
{%- endtrans %}</p>
<h2>{{ _('Persistent Tunnel / Lease Selection') }}</h2>
<p>{% trans -%}
Outbound tunnel selection implemented in 0.6.1.30, inbound lease selection
implemented in release 0.6.2.
{%- endtrans %}</p>
<p>{% trans -%}
Selecting tunnels and leases at random for every message creates a large
incidence of out-of-order delivery, which prevents the streaming lib from
increasing its window size as much as it could. By persisting with the
same selections for a given connection, the transfer rate is much faster.
{%- endtrans %}</p>
<h2>{{ _('Compress some data structures') }}</h2>
<b>[{{ _('implemented') }}]</b>
<p>{% trans -%}
The I2NP messages and the data they contain is already defined in a fairly
compact structure, though one attribute of the RouterInfo structure is not -
"options" is a plain ASCII name = value mapping. Right now, we're filling it
with those published statistics - around 3300 bytes per peer. Trivial to
implement GZip compression would nearly cut that to 1/3 its size, and when you
consider how often RouterInfo structures are passed across the network, that's
significant savings - every time a router asks another router for a networkDb
entry that the peer doesn't have, it sends back 3-10 RouterInfo of them.
{%- endtrans %}</p>
<h2>{{ _('Update the ministreaming protocol') }}</h2>
<b>[{{ _('replaced by full streaming protocol') }}]</b>
<p>{% trans -%}
Currently mihi's ministreaming library has a fairly simple stream negotiation
protocol - Alice sends Bob a SYN message, Bob replies with an ACK message, then
Alice and Bob send each other some data, until one of them sends the other a
CLOSE message. For long lasting connections (to an IRC server, for instance),
that overhead is negligible, but for simple one-off request/response situations
(an HTTP request/reply, for instance), that's more than twice as many messages as
necessary. If, however, Alice piggybacked her first payload in with the SYN
message, and Bob piggybacked his first reply with the ACK - and perhaps also
included the CLOSE flag - transient streams such as HTTP requests could be
reduced to a pair of messages, instead of the SYN+ACK+request+response+CLOSE.
{%- endtrans %}</p>
<h2>{{ _('Implement full streaming protocol') }}</h2>
<b>[<a href="{{ site_url('docs/api/streaming') }}">{{ _('implemented') }}</a>]</b>
<p>{% trans -%}
The ministreaming protocol takes advantage of a poor design decision in the
I2P client protocol (I2CP) - the exposure of "mode=GUARANTEED", allowing what
would otherwise be an unreliable, best-effort, message based protocol to be used
for reliable, blocking operation (under the covers, its still all unreliable and
message based, with the router providing delivery guarantees by garlic wrapping
an "ACK" message in with the payload, so once the data gets to the target, the
ACK message is forwarded back to us [through tunnels, of course]).
{%- endtrans %}</p>
<p>{% trans link='http://web.archive.org/web/20070607220008/http://dev.i2p.net/pipermail/i2p/2004-March/000167.html' -%}
As I've <a href="{{ link }}">said</a>, having
I2PTunnel (and the ministreaming lib) go this route was the best thing that
could be done, but more efficient mechanisms are available. When we rip out the
"mode=GUARANTEED" functionality, we're essentially leaving ourselves with an
I2CP that looks like an anonymous IP layer, and as such, we'll be able to
implement the streaming library to take advantage of the design experiences of
the TCP layer - selective ACKs, congestion detection, nagle, etc.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,111 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Performance') }}{% endblock %}
{% block content %}
<h1>{% trans %}How does I2P work, why is it slow, and why does it not use my full bandwidth?{% endtrans %}</h1>
<p>{% trans -%}
Probably one of the most frequent things people ask is "how fast is I2P?",
and no one seems to like the answer - "it depends". After trying out I2P, the
next thing they ask is "will it get faster?", and the answer to that is a most
emphatic <b>yes</b>.
{%- endtrans %}</p>
<p>{% trans -%}
I2P is a full dynamic network. Each client is known to other nodes and tests local known nodes for reachability and capacity.
Only reachable and capable nodes are saved to a local NetDB (This is generally only a portion of the network, around 500-1000).
When I2P builds tunnels, it selects the best resource from this pool. For example, a small subset of 20-50 nodes are only available to build tunnels with.
Because testing happens every minute, the pool of used nodes changes every minute.
Each I2P node knows a different part of the net, meaning that each router has a different set of I2P nodes to be used for tunnels.
Even if two routers have the same subset of known nodes, the tests for reachability and capacity will likely show different results, as the other routers could be under load just as one router tests, but be free if the second router tests.
{%- endtrans %}</p>
<p>{% trans -%}
The above describes why each I2P node has different nodes to build tunnels.
Because every I2P node has a different latency and bandwith, tunnels (which are built via those nodes) have different latency and bandwidth values.
And because every I2P node has different tunnels built, no two I2P nodes have the same tunnel sets.
{%- endtrans %}</p>
<p>{% trans -%}
A server/client is known as a "destination" and each destination has at least one inbound and one outbound tunnel. The default is 3 hops per tunnel.
This adds up to 12 hops (aka 12 different I2P nodes) for a full roundtrip client-server-client.
{%- endtrans %}</p>
<p>{% trans -%}
Each data package is sent through 6 other I2P nodes until it reaches the server:
{%- endtrans %}</p>
<pre>
client - hop1 - hop2 - hop3 - hopa1 - hopa2 - hopa3 - server
</pre>
<p>{% trans -%}
and on way back 6 different I2P nodes:
{%- endtrans %}</p>
<pre>
server - hopb1 - hopb2 - hopb3 - hopc1 - hopc2 - hopc3 - client
</pre>
<p>{% trans -%}
As most traffic on I2P (www, torrent,...) needs ack packages until new data is sent, it needs to wait until a ack package returns from the server.
In the end: send data, wait for ack, send more data, wait for ack,..
As the RTT (RoundTripTime) adds up from the latency of each individual I2P node and each connection on this roundtrip, it takes usually 1-3 seconds until a ack package comes back to the client.
With some internals of TCP and I2P transport, a data package has a limited size and cannot be as large as we want it to be.
Together these conditions set a limit of max bandwidth per tunnel of 20-50 kbyte/sec.
But if ONLY ONE hop in the tunnel has only 5 kb/sec bandwidth to spend, the whole tunnel is limited to 5 kb/sec, independent of the
latency and other limitations.
{%- endtrans %}</p>
<p>{% trans -%}
Due to encryption used and other setups in I2P (howto built up tunnels, latency, ...) it is quite expensive in CPU time to build a tunnel. This is
why a destination is only allowed to have a max of 6 IN and 6 OUT tunnels to transport data. With a max of 50 kb/sec per tunnel, a destination could
use roughly 300 kb/sec traffic combined ( in reality it could be more if shorter tunnels are used with low or no anonymity available).
Used tunnels are discarded every 10 minutes and new ones are built up.
This change of tunnels (and sometimes clients that shutdown hard due to usage of "shut down at once" or situations where there is power loss) does
sometimes break tunnels and connections, as seen on the IRC2P Network in loss of connection (ping timeout) or on when using eepget.
{%- endtrans %}</p>
<p>{% trans -%}
With a limited set of destinations and a limited set of tunnels per destination, one I2P node only uses a limited set of tunnels across other I2P nodes.
For example, if an I2P node is "hop1" in the small example above, we only see 1 participating tunnel originating from the client.
If we sum up the whole I2P network, only a rather limited number of participating tunnels could be built with a limited amount of bandwidth all together.
If one distributes these limited numbers across the number of I2P nodes, there is only a fraction of available bandwidth/capacity available for use.
{%- endtrans %}</p>
<p>{% trans -%}
To remain anonymous one router should not be used by the whole network for building tunnels.
If one router does act as a tunnel router for ALL I2P nodes, it becomes a very real central point of failure as well as a central point to grab IPs and data from the clients. This is not good.
I2P attempts to spread the load across a lot of I2P nodes because of this reason.
{%- endtrans %}</p>
<p>{% trans -%}
Another point is the full mesh network. Each connection hop-hop utilizes one TCP or UDP connection on the I2P nodes. With 1000 connections, one sees
1000 TCP connections. That is quite a lot and some home and small office routers (DSL, cable,..) only allow a small number of connections (or just go mad if you use more than X connections).
I2P tries to limit these connections to be under 1500 per UDP and per TCP type.
This limits the amount of traffic routed across your I2P node as well.
{%- endtrans %}</p>
<p>{% trans -%}
In summary, I2P is very complex and there is no easy way to pinpoint why your node is not used.
If your node is reachable and has a bandwidth setting of >128 kbyte/sec shared and is reachable 24/7, it should be used after some time for participating traffic.
If it is down in between, the testing of your I2P node done by other nodes will tell them: you are not reachable. This blocks your node for at least
24h on other nodes. So, the other nodes which tested you as down will not use your node for 24h for building tunnels. This is why your traffic will
be lower after a restart/shutdown for a minimum of 24h.
{%- endtrans %}</p>
<p>{% trans -%}
Also: other I2P nodes needs to know your I2P router to test it for reachability and capacity. It takes time for other nodes to get known to your node.
It will be faster if you use I2P and build more tunnels, e.g. use a torrent or www for some time.
{%- endtrans %}</p>
<h2>{{ _('Performance Improvements') }}</h2>
<p>{% trans future=site_url('about/performance/future') -%}
For possible future performance improvements see
<a href="{{ future }}">Future Performance Improvements</a>.
{%- endtrans %}</p>
<p>{% trans history=site_url('about/performance/history') -%}
For past performance improvements see the <a href="{{ history }}">
Performance History</a>.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,361 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Team') }}{% endblock %}
{% block content %}
<h1>{{ _('I2P Project Members') }}</h1>
<p>{% trans volunteer=site_url('get-involved') -%}
We are a small group of people spread around several continents, working to
advance different aspects of the project and discussing the design of the
network.
<a href="{{ volunteer }}">Get involved!</a>
{%- endtrans %}</p>
<table border="0">
<tr>
<td valign="top" rowspan="18"><b>{{ _('Admin') }}</b></td>
<td valign="top"><b>{{ _('Project Manager') }}</b></td>
<td valign="top">zzz</td>
<td valign="top"><i>{{ _('point of contact of last resort') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{{ _('Treasurer') }}</b></td>
<td valign="top">eche|on</td>
<td valign="top"><i>{{ _('manage donations / accounts / bounties') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{{ _('PR manager') }}</b></td>
<td valign="top">orion</td>
<td valign="top"><i>{{ _('press contact, manages public relations and affairs') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{% trans forum=i2pconv('forum.i2p') %}<a href="http://{{ forum }}/">Forum</a> admin{% endtrans %}</b></td>
<td valign="top">cervantes</td>
<td valign="top"><i>{{ _('manage the public user forum') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{{ _('Mirrors admin') }}</b></td>
<td valign="top">welterde</td>
<td valign="top"><i>{{ _('manage the project mirrors') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{% trans monotone=site_url('get-involved/guides/monotone') %}<a href="{{ monotone }}">Monotone</a> guru{% endtrans %}</b></td>
<td valign="top">welterde, eche|on</td>
<td valign="top"><i>{{ _('manage the public monotone repositories') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{{ _('Packager; Linux') }}</b></td>
<td valign="top">KillYourTV</td>
<td valign="top"><i>{{ _('Linux (Debian/Ubuntu) distribution packager') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{{ _('Packager; Windows') }}</b></td>
<td valign="top">KillYourTV</td>
<td valign="top"><i>{{ _('Windows installer packager') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{{ _('Release Manager') }}</b></td>
<td valign="top">zzz</td>
<td valign="top"><i>{{ _('Builds and signs the releases') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{{ _('Update admin') }}</b></td>
<td valign="top">KillYourTV</td>
<td valign="top"><i>{{ _('Monitors and recruits in-network update hosts') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{{ _('Reseed admin') }}</b></td>
<td valign="top">Meeh</td>
<td valign="top"><i>{{ _('Monitors, advises and recruits reseed hosts') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{{ _('Security expert') }}</b></td>
<td valign="top" class="blue">[{{ _('vacant') }}]</td>
<td valign="top"><i>{{ _('threat model / crypto expert') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{{ _('User Advocate') }}</b></td>
<td valign="top" class="blue">[{{ _('vacant') }}]</td>
<td valign="top"><i>{{ _('gather, prioritize, advocate for user needs') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{{ _('Web Designer') }}</b></td>
<td valign="top" class="blue">[{{ _('vacant') }}]</td>
<td valign="top"><i>{{ _('manage the public project website content design') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{% trans website=site_url() %}<a href="{{ website }}">Webserver</a> admin{% endtrans %}</b></td>
<td valign="top">welterde</td>
<td valign="top"><i>{{ _('manage the public project webservers') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{% trans website=site_url() %}<a href="{{ website }}">Website</a> admin{% endtrans %}</b></td>
<td valign="top">str4d</td>
<td valign="top"><i>{{ _('manage the public project website content') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{{ _('News Admin') }}</b></td>
<td valign="top">eche|on</td>
<td valign="top"><i>{{ _('manage router console news feed') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{{ _('Director of passion') }}</b></td>
<td valign="top" class="blue">[{{ _('vacant') }}]</td>
<td valign="top"><i>{{ _('community motivator') }}</i></td>
</tr>
<tr><td colspan="4"><hr /></td></tr>
<tr>
<td valign="top" rowspan="27"><b>{{ _('Dev') }}</b></td>
<td valign="top"><b>{{ _('Core Lead') }}</b></td>
<td valign="top">zzz</td>
<td valign="top"><i>{{ _('lead dev for the SDK and router') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{% trans postman=i2pconv('hq.postman.i2p') %}<a href="http://{{ postman }}/">I2P mail</a> lead{% endtrans %}</b></td>
<td valign="top">postman</td>
<td valign="top"><i>{{ _('organize and develop the i2p mail system') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{% trans i2host=i2pconv('i2host.i2p') %}<a href="http://{{ i2host }}/">I2Host</a> lead{% endtrans %}</b></td>
<td valign="top">sponge</td>
<td valign="top"><i>{{ _('I2Host addressbook application') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{% trans bob=i2pconv('bob.i2p') %}<a href="http://{{ bob }}/">BOB</a> lead{% endtrans %}</b></td>
<td valign="top">sponge</td>
<td valign="top"><i>{{ _('Basic Open Bridge') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{% trans bote=i2pconv('i2pbote.i2p') %}<a href="http://{{ bote }}/">I2P-Bote</a> lead{% endtrans %}</b></td>
<td valign="top">HungryHobo</td>
<td valign="top"><i>{{ _('I2PBote plugin') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{% trans bob=i2pconv('bob.i2p') %}<a href="http://{{ bob }}/">Robert</a> lead{% endtrans %}</b></td>
<td valign="top">sponge</td>
<td valign="top"><i>{{ _('Robert BitTorrent client') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{% trans forum=i2pconv('forum.i2p') %}<a href="http://{{ forum }}/viewforum?f=25">I2Phex</a> lead{% endtrans %}</b></td>
<td valign="top" class="blue">[{{ _('vacant') }}]</td>
<td valign="top"><i>{{ _('I2Phex Gnutella client') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{% trans forum=i2pconv('forum.i2p') %}<a href="http://{{ forum }}/viewforum?f=21">I2PSnark</a> lead{% endtrans %}</b></td>
<td valign="top">zzz</td>
<td valign="top"><i>{{ _('Maintains the integrated Bittorrent client') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{% trans forum=i2pconv('forum.i2p') %}<a href="http://{{ forum }}/viewforum?f=30">iMule</a> lead{% endtrans %}</b></td>
<td valign="top" class="blue">[{{ _('vacant') }}]</td>
<td valign="top"><i>{{ _('eMule client over I2P') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{% trans forum=i2pconv('forum.i2p') %}<a href="http://{{ forum }}/viewforum?f=29">Syndie</a> lead{% endtrans %}</b></td>
<td valign="top" class="blue">[{{ _('vacant') }}]</td>
<td valign="top"><i>{{ _('Syndie development') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{{ _('Susimail lead') }}</b></td>
<td valign="top" class="blue">[{{ _('vacant') }}]</td>
<td valign="top"><i>{{ _('Susimail development') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{{ _('Console') }}</b></td>
<td valign="top" class="blue">[{{ _('vacant') }}]</td>
<td valign="top"><i>{{ _('Router console HTML/CSS design') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{{ _('SAM') }}</b></td>
<td valign="top" class="blue">[{{ _('vacant') }}]</td>
<td valign="top"><i>{{ _('SAM maintainer') }}</i></td>
</tr>
<tr>
<td valign="top"><b>{{ _('I2PCPP lead') }}</b></td>
<td valign="top">orion</td>
<td valign="top"><i>{{ _('C++ Router') }}</i></td>
</tr>
<tr>
<td valign="top" rowspan="8"><b>{{ _('Console Translations') }}</b></td>
<td valign="top">walking</td>
<td valign="top"><i>{{ _('Chinese') }}</i></td>
</tr>
<tr>
<td valign="top">monkeybrains</td>
<td valign="top"><i>{{ _('Dutch') }}</i></td>
</tr>
<tr>
<td valign="top">magma</td>
<td valign="top"><i>{{ _('French') }}</i></td>
</tr>
<tr>
<td valign="top">eche|on, mixxy</td>
<td valign="top"><i>{{ _('German') }}</i></td>
</tr>
<tr>
<td valign="top">rus, 4get, slow</td>
<td valign="top"><i>{{ _('Russian') }}</i></td>
</tr>
<tr>
<td valign="top">user</td>
<td valign="top"><i>{{ _('Spanish') }}</i></td>
</tr>
<tr>
<td valign="top">thelastcode, hamada</td>
<td valign="top"><i>{{ _('Arabic') }}</i></td>
</tr>
<tr>
<td valign="top" class="blue">[{{ _('vacant') }}]</td>
<td valign="top"><i>{{ _('Other languages') }}</i></td>
</tr>
<tr>
<td valign="top" rowspan="5"><b>{{ _('Contributors') }}</b></td>
<td valign="top">cervantes</td>
<td valign="top"><i>{{ _('fire2pe dev, console enhancements') }}</i></td>
</tr>
<tr>
<td valign="top">Mathiasdm</td>
<td valign="top"><i>{{ _('desktopgui, dijjer port') }}</i></td>
</tr>
<tr>
<td valign="top">KillYourTV</td>
<td valign="top"><i>{{ _('Debian/Ubuntu Packager and PPA maintainer') }}</i></td>
</tr>
<tr>
<td valign="top">str4d</td>
<td valign="top"><i>{{ _('Routerconsole backend and UI work, website revamp, unit tests work') }}</i></td>
</tr>
<tr>
<td valign="top" class="blue">[{{ _('vacant') }}]</td>
<td valign="top" class="blue"><i>{{ _('Help needed on many fronts!') }}</i></td>
</tr>
<tr><td colspan="4"><hr /></td></tr>
<tr>
<td valign="top" rowspan="32" colspan="2"><b>{{ _('Past contributors') }}</b></td>
<td valign="top">mihi</td>
<td valign="top"><i>{{ _('I2PTunnel development, ministreaming library') }}</i></td>
</tr>
<tr>
<td valign="top">jrandom</td>
<td valign="top"><i>{{ _('Project lead, Syndie lead') }}</i></td>
</tr>
<tr>
<td valign="top">Complication</td>
<td valign="top"><i>{{ _('Project lead, Syndie lead, I2Phex, support guru') }}</i></td>
</tr>
<tr>
<td valign="top">mkvore</td>
<td valign="top"><i>{{ _('iMule lead') }}</i></td>
</tr>
<tr>
<td valign="top">redzara</td>
<td valign="top"><i>{{ _('I2Phex work') }}</i></td>
</tr>
<tr>
<td valign="top">striker</td>
<td valign="top"><i>{{ _('I2Phex work') }}</i></td>
</tr>
<tr>
<td valign="top">legion</td>
<td valign="top"><i>{{ _('I2Phex work') }}</i></td>
</tr>
<tr>
<td valign="top">Connely</td>
<td valign="top"><i>{{ _('Python SAM library, attack simulations') }}</i></td>
</tr>
<tr>
<td valign="top">mastiejaner</td>
<td valign="top"><i>{{ _('i2pmail development') }}</i></td>
</tr>
<tr>
<td valign="top">dust</td>
<td valign="top"><i>{{ _('Syndie help') }}</i></td>
</tr>
<tr>
<td valign="top">susi23</td>
<td valign="top"><i>{{ _('i2p mail,susimail and susidns apps') }}</i></td>
</tr>
<tr>
<td valign="top">sirup</td>
<td valign="top"><i>{{ _('I2Phex (port of Phex to I2P)') }}</i></td>
</tr>
<tr>
<td valign="top">Ragnarok</td>
<td valign="top"><i>{{ _('addressbook,i2p-bt,syndie client') }}</i></td>
</tr>
<tr>
<td valign="top">duck</td>
<td valign="top"><i>{{ _('organize and develop the i2p-bt BitTorrent port') }}</i></td>
</tr>
<tr>
<td valign="top">Ragnarok</td>
<td valign="top"><i>{{ _('addressbook, i2p-bt, syndie client development') }}</i></td>
</tr>
<tr>
<td valign="top">thecrypto</td>
<td valign="top"><i>{{ _('encryption and signature routines, I2PIM') }}</i></td>
</tr>
<tr>
<td valign="top">aum</td>
<td valign="top"><i>{{ _('SAM jython code, work on stasher (DHT) and v2v (VoI2P)') }}</i></td>
</tr>
<tr>
<td valign="top">hypercubus</td>
<td valign="top"><i>{{ _('installer, systray, bogobot') }}</i></td>
</tr>
<tr>
<td valign="top">ugha</td>
<td valign="top"><i>{{ _('jbigi development, wiki migration, doc cleanup') }}</i></td>
</tr>
<tr>
<td valign="top">oOo</td>
<td valign="top"><i>{{ _('java debugging and client development on I2PTunnel and the router console') }}</i></td>
</tr>
<tr>
<td valign="top">BrianR</td>
<td valign="top"><i>{{ _('SAM perl module') }}</i></td>
</tr>
<tr>
<td valign="top">eco</td>
<td valign="top"><i>{{ _('i2psnark work') }}</i></td>
</tr>
<tr>
<td valign="top">shendaras</td>
<td valign="top"><i>{{ _('java cleanup') }}</i></td>
</tr>
<tr>
<td valign="top">JAnonymous</td>
<td valign="top"><i>{{ _('docs. wiki migration') }}</i></td>
</tr>
<tr>
<td valign="top">jar</td>
<td valign="top"><i>{{ _('translations into French') }}</i></td>
</tr>
<tr>
<td valign="top">scintilla</td>
<td valign="top"><i>{{ _('C port of jcpuid') }}</i></td>
</tr>
<tr>
<td valign="top">smeghead</td>
<td valign="top"><i>{{ _('C# SAM library, pants, fortuna integration') }}</i></td>
</tr>
<tr>
<td valign="top">Nightblade</td>
<td valign="top"><i>{{ _('libSAM') }}</i></td>
</tr>
<tr>
<td valign="top">dinoman</td>
<td valign="top"><i>{{ _('i2p-bt tracker development') }}</i></td>
</tr>
<tr>
<td valign="top">DrWoo</td>
<td valign="top"><i>{{ _('i2p-bt tracker development') }}</i></td>
</tr>
<tr>
<td valign="top">dr|z3d</td>
<td valign="top"><i>{{ _('Console and website themes') }}</i></td>
</tr>
<tr>
<td valign="top" colspan="2">{% trans %}&hellip; and many others{% endtrans %}</td>
</tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,40 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('I2P Compared to Freenet') }}{% endblock %}
{% block content %}
<h2>Freenet</h2>
<i><a href="http://freenetproject.org/">[Freenet]</a></i>
<p>{% trans -%}
Freenet is a fully distributed, peer to peer anonymous publishing network, offering
secure ways to store data, as well as some approaches attempting to address the loads
of a flash flood. While Freenet is designed as a distributed data store, people have
built applications on top of it to do more generic anonymous communication, such as
static websites and message boards.
{%- endtrans %}</p>
<p>{% trans tahoe='https://tahoe-lafs.org/trac/tahoe-lafs' -%}
Compared to I2P, Freenet offers some substantial benefits - it is a distributed data
store, while I2P is not, allowing people to retrieve the content published by others
even when the publisher is no longer online. In addition, it should be able to
distribute popular data fairly efficiently. I2P itself does not and will not provide
this functionality. On the other hand, there is overlap for users who simply want to
communicate with each other anonymously through websites, message boards, file sharing
programs, etc. There have also been some attempts to develop a distributed data
store to run on top of I2P,
(most recently a port of <a href="{{ tahoe }}">Tahoe-LAFS</a>)
but nothing is yet ready for general use.
{%- endtrans %}</p>
<p>{% trans -%}
However, even ignoring any implementations issues, there are some concerns
about Freenet's algorithms from both a scalability and anonymity perspective, owing
largely to Freenet's heuristic driven routing. The interactions of various techniques
certainly may successfully deter various attacks, and perhaps some aspects of the
routing algorithms will provide the hoped for scalability. Unfortunately, not much
analysis of the algorithms involved has resulted in positive results, but there is still
hope. At the very least, Freenet does provide substantial anonymity against an attacker
who does not have the resources necessary to analyze it further.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,37 @@
{% extends "global/layout.html" %}
{% block title %}I2P Compared to GNUnet{% endblock %}
{% block content %}
<h2>GNUnet</h2>
<i><a href="https://gnunet.org/">[GNUnet]</a> </i>
<p>
TODO: Overview of GNUnet.
</p>
<p>
TODO: Comparison to I2P.
</p>
<h3>Comparison of GNUnet and I2P Terminology</h3>
<p>
TODO: Comparison of terminology
</p>
<table>
<tr><th align="left">GNUnet</th><th align="left">I2P</th></tr>
<tr><td>Pseudonym</td><td>Destination(?)</td></tr>
</table>
<h3>Benefits of GNUnet over I2P</h3>
<ul>
<li>TODO: fill out</li>
</ul>
<h3>Benefits of I2P over GNUnet</h3>
<ul>
<li>TODO: fill out</li>
</ul>
{% endblock %}

View File

@@ -0,0 +1,37 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Comparing I2P to other projects') }}{% endblock %}
{% block content %}
<p>{% trans -%}
There are a great many other applications and projects working on anonymous
communication and I2P has been inspired by much of their efforts. This is not
a comprehensive list of anonymity resources - both freehaven's
<a href="http://freehaven.net/anonbib/topic.html">Anonymity Bibliography</a>
and GNUnet's <a href="https://www.gnunet.org/links/">related projects</a>
serve that purpose well. That said, a few systems stand out for further
comparison. The following have individual comparison pages:
{%- endtrans %}</p>
<ul>
<li><a href="{{ site_url('comparison/tor') }}">Tor / Onion Routing</a></li>
<li><a href="{{ site_url('comparison/freenet') }}">Freenet</a></li>
{#<li><a href="{{ site_url('comparison/gnunet') }}">GNUnet</a></li>#}
</ul>
<p>{% trans othernetworks=site_url('comparison/other-networks') -%}
The following are discussed on the <a href="{{ othernetworks }}">other networks page:</a>
{%- endtrans %}</p>
<ul>
<li>Morphmix / Tarzan</li>
<li>Mixminion / Mixmaster</li>
<li>JAP</li>
<li>MUTE / AntsP2P</li>
<li>Haystack</li>
</ul>
<p>{% trans trac=i2pconv('trac.i2p2.i2p') -%}
The content of this page is subject to update, discussion and dispute, and we welcome comments and additions.
You may contribute an analysis by entering a <a href="http://{{ trac }}/report/1">new ticket on Trac</a>.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,244 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('I2P Compared to Other Anonymous Networks') }}{% endblock %}
{% block content %}
<p>{% trans -%}
The following networks are discussed on this page.
{%- endtrans %}</p>
<ul>
<li>Morphmix / Tarzan</li>
<li>Mixminion / Mixmaster</li>
<li>JAP</li>
<li>MUTE / AntsP2P</li>
<li>Haystack</li>
</ul>
<p>{% trans comparison=site_url('comparison'), trac=i2pconv('trac.i2p2.i2p') -%}
Most of the following sections are fairly old, and may not be accurate.
For an overview of available comparisons, see the
<a href="{{ comparison }}">main network comparisons page</a>.
You may contribute an analysis by entering a
<a href="http://{{ trac }}/report/1">new ticket on {{ trac }}</a>.
{%- endtrans %}</p>
<h2>Morphmix / Tarzan</h2>
<i><a href="https://home.zhaw.ch/~rer/projects/morphmix/">[Morphmix]</a>
<a href="http://pdos.csail.mit.edu/tarzan/">[Tarzan]</a></i>
<p>{% trans threatmodel=site_url('docs/how/threat-model') -%}
Morphmix and Tarzan are both fully distributed, peer to peer networks of
anonymizing proxies, allowing people to tunnel out through the low latency
mix network. Morphmix includes some very interesting collusion detection
algorithms and Sybil defenses, while Tarzan makes use of the scarcity of IP
addresses to accomplish the same. The two primary differences between
these systems and I2P are related to I2P's <a href="{{ threatmodel }}">threat model</a>
and their out-proxy design (as opposed to providing both sender and receiver
anonymity). There is source code available to both systems, but we are not aware
of their use outside of academic environments.
{%- endtrans %}</p>
<!--
Table needs correction, disabled for now.
Comments from arma on 2010-09-14 in #nottor:
You say "maybe" under the tarzan column, because tarzan says "we hope to get this level of protection, but it is an open research question how one would get it"
then i2p says "no, all solved, we solve that one" in its column. which either means you've got a brilliant new design but have failed to articulate it or publish about it, or you are misleading people.
this table has been around, and misleading people and frustrating me, for something like 8 or 10 years now.
the fundamental problem is that for the projects that exist, you put down their current levels of protection in the table (fine), but for i2p you put down your desired level of protection (not fine)
End of comments
<p>Stealing quite directly from the Tarzan paper, the following includes a quick
comparison of Tarzan, Crowds, Onion Routing (OR), and I2P:</p>
<table>
<tr>
<td style="width: 19%;"></td>
<td style="width: 27%;" colspan="4">Bad first relay/router</td>
<td style="width: 27%;" colspan="4">Bad intermediate relay/router</td>
<td style="width: 27%;" colspan="4">Bad last relay/router</td>
</tr>
<tr>
<td>Information exposed</td>
<td><b>OR</b></td>
<td><b>Crowds</b></td>
<td><b>Tarzan</b></td>
<td><b>I2P</b></td>
<td><b>OR</b></td>
<td><b>Crowds</b></td>
<td><b>Tarzan</b></td>
<td><b>I2P</b></td>
<td><b>OR</b></td>
<td><b>Crowds</b></td>
<td><b>Tarzan</b></td>
<td><b>I2P</b></td>
</tr>
<tr>
<td>Sender activity</td>
<td>Yes</td>
<td>Maybe</td>
<td>Maybe</td>
<td><b>No</b></td>
<td>No</td>
<td>No</td>
<td>Maybe</td>
<td><b>No</b></td>
<td>No</td>
<td>No</td>
<td>No</td>
<td><b>No</b></td>
</tr>
<tr>
<td>Recipient activity</td>
<td>No</td>
<td>Yes</td>
<td>No</td>
<td><b>No</b></td>
<td>No</td>
<td>Yes</td>
<td>No</td>
<td><b>No</b></td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td><b>No</b></td>
</tr>
<tr>
<td>Sender content</td>
<td>No</td>
<td>Maybe</td>
<td>No</td>
<td><b>No</b></td>
<td>No</td>
<td>No</td>
<td>No</td>
<td><b>No</b></td>
<td>No</td>
<td>No</td>
<td>No</td>
<td><b>No</b></td>
</tr>
<tr>
<td>Recipient content</td>
<td>No</td>
<td>Yes</td>
<td>No</td>
<td><b>No</b></td>
<td>No</td>
<td>Yes</td>
<td>No</td>
<td><b>No</b></td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td><b>No</b></td>
</tr>
</table>
-->
<h2>Mixminion / Mixmaster</h2>
<i><a href="http://mixminion.net/">[Mixminion]</a>
<a href="http://mixmaster.sourceforge.net/">[Mixmaster]</a></i>
<p>{% trans %}
Mixminion and Mixmaster are networks to support anonymous email against a very
powerful adversary.
High-latency messaging applications running on top of I2P
(for example
<a href="http://syndie.i2p2.de/">Syndie</a> or
I2PBote)
may perhaps prove adequate to meet the threat
model of those adversaries, while running in parallel along side the needs of low latency users, to provide
a significantly larger anonymity set.
High-latency support within the I2P router itself may or may not be added in a distant future release.
It is too early to say if I2P will meet the needs of users requiring extreme protection for email.
{%- endtrans %}</p>
<p>{% trans -%}
As with Tor and Onion Routing,
both Mixminion and Mixmaster take the directory based approach as well.
{%- endtrans %}</p>
<h2>JAP</h2>
<i><a href="http://anon.inf.tu-dresden.de/index_en.html">[JAP]</a></i>
<p>{% trans url='https://www.datenschutzzentrum.de/material/themen/presse/anonip3_e.htm' -%}
JAP (Java Anonymous Proxy) is a network of mix cascades for anonymizing web requests,
and as such it has a few centralized nodes (participants in the cascade) that blend
and mix requests from clients through the sequence of nodes (the cascade) before
proxying out onto the web. The scope, threat model, and security is substantially
different from I2P, but for those who don't require significant anonymity but still
are not satisfied with an Anonymizer-like service, JAP is worth reviewing. One
caution to note is that anyone under the jurisdiction of the German courts may want
to take care, as the German Federal Bureau of Criminal Investigation (FBCI) has
successfully mounted an
<a href="{{ url }}">attack</a>
on the network. Even though the method of this attack was later found to be illegal
in the German courts, the fact that the data was successfully collected is the
concern. Courts change their minds based upon circumstance, and this is evidence that
if a government body or intelligence agency wanted to, they could gather the data, even
if it may be found inadmissible in some courts later)
{%- endtrans %}</p>
<h2>MUTE / AntsP2P</h2>
<i><a href="http://mute-net.sourceforge.net/">[MUTE]</a>
<a href="http://antsp2p.sourceforge.net/">[AntsP2P]</a></i>
<p>{% trans antnet='http://citeseer.ist.psu.edu/57701.html' -%}
Both of these systems work through the same basic
<a href="{{ antnet }}">antnet</a> routing, providing some degree of
anonymity based on the threat model of providing plausible deniability against a simple
non-colluding adversary. With the antnet routing, they first either do a random walk or a
broadcast search to find some peer with the data or identity desired, and then use a feedback
algorithm to optimize that found path. This works well for applications that merely want to know
what other people around them have to offer - "How are y'all doing" vs. "Hey Alice, how are you" -
you basically get a local cluster of nodes that can share files with and maintain some degree of
anonymity (though you don't have much control over who is in that group of peers).
{%- endtrans %}</p>
<p>{% trans -%}
However, the algorithm does not scale well at all - if the application wants to speak with a
particular peer it ends up doing a broadcast search or random walk (though if they are lucky enough
for that to succeed, the antnet routing should optimize that found connection). This means that
while these networks can work great at small scales, they are not suitable for large networks where
someone wants to get in touch with another specific peer. That does not mean that there is no
value in these systems, just that their applicability is limited to situations where their
particular issues can be addressed.
{%- endtrans %}</p>
<h2>Haystack</h2>
<p>{% trans docs=site_url('docs') -%}
This was a closed-source network targeted at Iranian users.
Tor did a
<a href="http://blog.torproject.org/blog/ten-things-look-circumvention-tool">good writeup on what to look for in a circumvention tool</a>.
Suffice it to say that being closed source and publicly targeting a specific country are not good ideas.
I2P is, of course, open source. However, that source, and our
<a href="{{ docs }}">technical documentation</a>, need much more review.
{%- endtrans %}</p>
<h2>{{ _('Paid VPN Services') }}</h2>
<p>{% trans trac=i2pconv('trac.i2p2.i2p') -%}
You may contribute an analysis by entering a
<a href="http://{{ trac }}/report/1">new ticket on {{ trac }}</a>.
{%- endtrans %}</p>
<h2>{{ _('Others') }}</h2>
<p>{% trans trac=i2pconv('trac.i2p2.i2p') -%}
You may contribute an analysis by entering a
<a href="http://{{ trac }}/report/1">new ticket on {{ trac }}</a>.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,227 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('I2P Compared to Tor') }}{% endblock %}
{% block content %}
<h2>Tor / Onion Routing</h2>
<i><a href="https://www.torproject.org/">[Tor]</a>
<a href="http://www.onion-router.net">[Onion Routing]</a></i>
<p>{% trans netdb=site_url('docs/how/network-database'), peerselection=site_url('docs/how/peer-selection') -%}
Tor and Onion Routing are both anonymizing proxy networks,
allowing people to tunnel out through their low latency mix
network. The two primary differences between Tor /
Onion-Routing and I2P are again related to differences in
the threat model and the out-proxy design (though Tor
supports hidden services as well). In addition, Tor
takes the directory-based approach - providing a
centralized point to manage the overall 'view' of the
network, as well as gather and report statistics, as
opposed to I2P's distributed <a href="{{ netdb }}">network
database</a> and <a href="{{ peerselection }}">peer selection</a>.
{%- endtrans %}</p>
<p>{% trans -%}
The I2P/Tor outproxy functionality does have a few
substantial weaknesses against certain attackers -
once the communication leaves the mixnet, global passive
adversaries can more easily mount traffic analysis. In
addition, the outproxies have access to the cleartext
of the data transferred in both directions, and
outproxies are prone to abuse, along with all of the
other security issues we've come to know and love with
normal Internet traffic.
{%- endtrans %}</p>
<p>{% trans -%}
However, many people don't need to worry about those
situations, as they are outside their threat model. It
is, also, outside I2P's (formal) functional scope (if people want
to build outproxy functionality on top of an anonymous
communication layer, they can). In fact, some I2P users
currently take advantage of Tor to outproxy.
{%- endtrans %}</p>
<!--
<p>See also the
<a href="http://wiki.noreply.org/noreply/TheOnionRouter/TorFAQ#ComparisonI2P">the Tor FAQ</a>
for a Tor/I2P comparison from the Tor perspective.</p>
-->
<h3>{{ _('Comparison of Tor and I2P Terminology') }}</h3>
<p>{% trans -%}
While Tor and I2P are similar in many ways, much of the terminology is different.
{%- endtrans %}</p>
<table>
<tr><th align="left">Tor<th align="left">I2P
<tr><td>{{ _('Cell') }}<td>{{ _('Message') }}
<tr><td>{{ _('Client') }}<td>{{ _('Router or Client') }}
<tr><td>{{ _('Circuit') }}<td>{{ _('Tunnel') }}
<tr><td>{{ _('Directory') }}<td>{{ _('NetDb') }}
<tr><td>{{ _('Directory Server') }}<td>{{ _('Floodfill Router') }}
<tr><td>{{ _('Entry Guards') }}<td>{{ _('Fast Peers') }}
<tr><td>{{ _('Entry Node') }}<td>{{ _('Inproxy') }}
<tr><td>{{ _('Exit Node') }}<td>{{ _('Outproxy') }}
<tr><td>{{ _('Hidden Service') }}<td>{{ _('Eepsite or Destination') }}
<tr><td>{{ _('Hidden Service Descriptor') }}<td>{{ _('LeaseSet') }}
<tr><td>{{ _('Introduction point') }}<td>{{ _('Inbound Gateway') }}
<tr><td>{{ _('Node') }}<td>{{ _('Router') }}
<tr><td>{{ _('Onion Proxy') }}<td>{{ _('I2PTunnel Client (more or less)') }}
<tr><td>{{ _('Relay') }}<td>{{ _('Router') }}
<tr><td>{{ _('Rendezvous Point') }}<td>{{ _('somewhat like Inbound Gateway + Outbound Endpoint') }}
<tr><td>{{ _('Router Descriptor') }}<td>{{ _('RouterInfo') }}
<tr><td>{{ _('Server') }}<td>{{ _('Router') }}
</table>
<h3>{{ _('Benefits of Tor over I2P') }}</h3>
<ul>
<li>
{% trans -%}
Much bigger user base; much more visibility in the academic and hacker communities; benefits from
formal studies of anonymity, resistance, and performance;
has a non-anonymous, visible, university-based leader
{%- endtrans %}
</li>
<li>{% trans %}Has already solved some scaling issues I2P has yet to address{% endtrans %}</li>
<li>{% trans %}Has significant funding{% endtrans %}</li>
<li>{% trans %}Has more developers, including several that are funded{% endtrans %}</li>
<li>
{% trans -%}
More resistant to state-level blocking due to TLS transport layer and bridges
(I2P has proposals for "full restricted routes" but these are not yet implemented)
{%- endtrans %}
</li>
<li>{% trans %}Big enough that it has had to adapt to blocking and DOS attempts{% endtrans %}</li>
<li>{% trans %}Designed and optimized for exit traffic, with a large number of exit nodes{% endtrans %}</li>
<li>
{% trans -%}
Better documentation, has formal papers and specifications,
better website, many more translations
{%- endtrans %}
</li>
<li>{% trans %}More efficient with memory usage{% endtrans %}</li>
<li>{% trans %}Tor client nodes have very low bandwidth overhead{% endtrans %}</li>
<li>
{% trans -%}
Centralized control reduces the complexity at each
node and can efficiently address Sybil attacks
{%- endtrans %}
</li>
<li>
{% trans -%}
A core of high capacity nodes provides higher
throughput and lower latency
{%- endtrans %}
</li>
<li>{% trans %}C, not Java (ewww){% endtrans %}</li>
</ul>
<h3>{{ _('Benefits of I2P over Tor') }}</h3>
<ul>
<li>{% trans %}Designed and optimized for hidden services, which are much faster than in Tor{% endtrans %}</li>
<li>{% trans %}Fully distributed and self organizing{% endtrans %}</li>
<li>
{% trans -%}
Peers are selected by continuously profiling and ranking performance,
rather than trusting claimed capacity
{%- endtrans %}
</li>
<li>
{% trans -%}
Floodfill peers ("directory servers") are varying and untrusted,
rather than hardcoded
{%- endtrans %}
</li>
<li>{% trans %}Small enough that it hasn't been blocked or DOSed much, or at all{% endtrans %}</li>
<li>{% trans %}Peer-to-peer friendly{% endtrans %}</li>
<li>{% trans %}Packet switched instead of circuit switched{% endtrans %}
<ul>
<li>
{% trans -%}
implicit transparent load balancing of messages
across multiple peers, rather than a single path
{%- endtrans %}
</li>
<li>
{% trans -%}
resilience vs. failures by running multiple
tunnels in parallel, plus rotating tunnels
{%- endtrans %}
</li>
<li>
{% trans -%}
scale each client's connections at O(1) instead
of O(N) (Alice has e.g. 2 inbound tunnels that are
used by all of the peers Alice is talking with,
rather than a circuit for each)
{%- endtrans %}
</li>
</ul>
</li>
<li>
{% trans -%}
Unidirectional tunnels instead of bidirectional
circuits, doubling the number of nodes a peer has to
compromise to get the same information.
{%- endtrans %}
</li>
<li>
{% trans -%}
Protection against detecting client activity, even
when an attacker is participating in the tunnel, as
tunnels are used for more than simply passing end
to end messages (e.g. netDb, tunnel management,
tunnel testing)
{%- endtrans %}
</li>
<li>
{% trans -%}
Tunnels in I2P are short lived, decreasing the number
of samples that an attacker can use to mount an
active attack with, unlike circuits in Tor, which are
typically long lived.
{%- endtrans %}
</li>
<li>
{% trans -%}
I2P APIs are designed specifically for anonymity and
security, while SOCKS is designed for functionality.
{%- endtrans %}
</li>
<li>{% trans %}Essentially all peers participate in routing for others{% endtrans %}</li>
<li>
{% trans -%}
The bandwidth overhead of being a full peer is low,
while in Tor, while client nodes don't require much
bandwidth, they don't fully participate in the mixnet.
{%- endtrans %}
</li>
<li>{% trans %}Integrated automatic update mechanism{% endtrans %}</li>
<li>{% trans %}Both TCP and UDP transports{% endtrans %}</li>
<li>{% trans %}Java, not C (ewww){% endtrans %}</li>
</ul>
<h3>{{ _('Other potential benefits of I2P but not yet implemented') }}</h3>
<p>{% trans %}...and may never be implemented, so don't count on them!{% endtrans %}</p>
<ul>
<li>
{% trans -%}
Defense vs. message count analysis by garlic wrapping
multiple messages
{%- endtrans %}
</li>
<li>
{% trans -%}
Defense vs. long term intersection by adding delays
at various hops (where the delays are not discernible
by other hops)
{%- endtrans %}
</li>
<li>
{% trans -%}
Various mixing strategies at the tunnel level (e.g.
create a tunnel that will handle 500 messages / minute,
where the endpoint will inject dummy messages if there
are insufficient messages, etc)
{%- endtrans %}
</li>
</ul>
{% endblock %}

View File

@@ -0,0 +1,68 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Contact') }}{% endblock %}
{% block content %}
<h1>IRC</h1>
<p>{% trans -%}
Our primary IRC network is the Irc2P network within I2P; a default tunnel to this network is set up with new router installs.
We are also present on multiple standard networks like <a href="http://www.oftc.net/oftc/OFTC">OFTC</a>,
<a href="http://www.einirc.de/">EIN</a> and <a href="http://freenode.net/">Freenode</a>.
All I2P-related channels on all these network are linked to the main channels on Irc2P via relay bots.
{%- endtrans %}</p>
<pre>
{% filter escape %}
{{ _('Channel list:') }}
#i2p {{ _('General i2p discussion') }}
#i2p-chat {{ _('Offtopic') }}
#i2p-dev {{ _('Development talk') }}
#i2p-help {{ _('Help channel') }}
{% endfilter %}
</pre>
<h1>{{ _('Forums') }}</h1>
<p>{% trans zzz=i2pconv('zzz.i2p') -%}
Most of the discussion about I2P's development happens on the <a href="http://{{ zzz }}">I2P developer forum</a>. This is usually the best place to start with inquiries, if the dev IRC channel is inactive.
{%- endtrans %}</p>
<h1>{{ _('Mailing lists') }}</h1>
<p>{% trans -%}
I2P does have a mailing list, but it is rarely used as the current small team of developers prefer to communicate via IRC or the developer forum. This may change in future.
{%- endtrans %}</p>
<h2>{{ _('Subscribing') }}</h2>
<p>{% trans -%}
To subscribe to a mailing list, go to the list information page (linked below) and fill out the form. I2P-internal email addresses (foobar@mail.i2p) can be used.
{%- endtrans %}</p>
<h2>{{ _('Unsubscribing') }}</h2>
<p>{% trans -%}
To unsubscribe from a mailing list or edit your subscription options, go to the list information page (linked below) and enter your subscription email address.
{%- endtrans %}</p>
<h2>{{ _('Lists') }}</h2>
<ul>
<li>
<a href="https://lists.welterde.de/mailman/listinfo/i2p-general">i2p-general</a>(<a href="https://lists.welterde.de/pipermail/i2p-general/">{{ _('Archive') }}</a>)<br/>
{% trans %}General I2P discussion - anything that doesn't fit in a different list goes here.{% endtrans %}
</li>
</ul>
<h1>NNTP</h1>
<p>{% trans -%}
You don't like mailing lists? Then this is for you. All mailing lists are available via NNTP as well.
{%- endtrans %}</p>
<pre>
{% filter escape %}
{{ _('Group-List-mapping:') }}
i2p.general i2p-general
{{ _('Servers:') }}
news.welterde.de news.welterde.i2p
{% endfilter %}
</pre>
{% endblock %}

View File

@@ -0,0 +1,347 @@
{% extends "global/layout.html" %}
{% block title %}BOB{% endblock %}
{% block lastupdated %}{% trans %}August 2010{% endtrans %}{% endblock %}
{% block content %}
<h1>{% trans %}BOB - Basic Open Bridge{% endtrans %}</h1>
<h2>{% trans %}Technical differences from SAM (for the better?){% endtrans %}</h2>
<p>{% trans -%}
BOB has separate command and data channels.
One, an application command channel socket to router to configure.
Two, the application data sockets to/from router that carry only data.
The command channel is only needed for making or setting the initial
destination key, and to set the destination key to port bindings.
All connections run in parallel.
{%- endtrans %}</p>
<p>{% trans -%}
SAM has one connection that does everything, and you need to parse every packet.
{%- endtrans %}</p>
<p>{% trans -%}
BOB does not hold keypair values, nor does the router.
Your application holds the keypair values.
This is to reduce any extra complexity in the router code, it also adds to
your privacy.
{%- endtrans %}</p>
<p>{% trans -%}
SAM router stores every keypair you ever make.
{%- endtrans %}</p>
<p>{% trans -%}
Those are the important differences.
{%- endtrans %}</p>
<p>{% trans -%}
<code>KEYS</code> = keypair public+private, these are BASE64
{%- endtrans %}</p>
<p>{% trans -%}
<code>KEY</code> = public key, also BASE64
{%- endtrans %}</p>
<p>{% trans -%}
<code>ERROR</code> as is implied returns the message <code>"ERROR "+DESCRIPTION+"\n"</code>, where the <code>DESCRIPTION</code> is what went wrong.
{%- endtrans %}</p>
<p>{% trans -%}
<code>OK</code> returns <code>"OK"</code>, and if data is to be returned, it is on the same line. <code>OK</code> means the command is finished.
{%- endtrans %}</p>
<p>{% trans -%}
<code>DATA</code> lines contain information that you requested. There may be multiple <code>DATA</code> lines per request.
{%- endtrans %}</p>
<p>{% trans -%}
<b>NOTE:</b> The help command is the ONLY command that has an exception to
the rules... it can actually return nothing! This is intentional, since
help is a HUMAN and not an APPLICATION command.
{%- endtrans %}</p>
<p>{% trans -%}
<b>PLEASE NOTE:</b>
For CURRENT details on the commands PLEASE use the built-in help command.
Just telnet to localhost 2827 and type help and you can get full documentation on each command.
{%- endtrans %}</p>
<p>{% trans -%}
Commands never get obsoleted or changed, however new commands do get added from time to time.
{%- endtrans %}</p>
<p>{% trans -%}
Here are the commands we have as of this writing:
{%- endtrans %}</p>
{% highlight lang='text' %}
{{ _('COMMAND') }} {{ _('OPERAND') }} {{ _('RETURNS') }}
help (optional command to get help on) NOTHING or OK and description of the command
clear ERROR or OK
getdest ERROR or OK and KEY
getkeys ERROR or OK and KEYS
getnick tunnelname ERROR or OK
inhost hostname or IP address ERROR or OK
inport port number ERROR or OK
list ERROR or DATA lines and final OK
newkeys ERROR or OK and KEY
option ERROR or OK
outhost hostname or IP address ERROR or OK
outport port number ERROR or OK
quiet ERROR or OK
quit OK and terminates the command connection
setkeys KEYS ERROR or OK
setnick tunnel nickname ERROR or OK
show ERROR or OK and information
showprops ERROR or OK and information
start ERROR or OK
status tunnel nickname ERROR or OK and information
stop ERROR or OK
verify KEY ERROR or OK
visit OK, and dumps BOB's threads to the wrapper.log
zap nothing, quits BOB
{% endhighlight %}
<p>{% trans -%}
Once set up, all TCP sockets can and will block as needed, and there is no need for any
additional messages to/from the command channel. This allows the router to pace the
stream without exploding with OOM like SAM does as it chokes on attempting to shove
many streams in or out one socket -- that can't scale when you have alot of connections!
{%- endtrans %}</p>
<p>{% trans -%}
What is also nice about this particular interface is that writing anything to interface
to it, is much much easier than SAM. There is no other processing to do after the set up.
It's configuration is so simple, that very simple tools, such as nc (netcat) can be used
to point to some application. The value there is that one could schedule up and down times
for an application, and not have to change the application to do that, or to even have
to stop that application. Instead, you can literally "unplug" the destination, and
"plug it in" again. As long as the same IP/port addresses and destination keys are used
when bringing the bridge up, the normal TCP application won't care, and won't notice.
It will simply be fooled -- the destinations are not reachable, and that nothing is coming in.
{%- endtrans %}</p>
<p>{% trans -%}
For the following example, we'll setup a very simple local loopback connection,
with two destinations. Destination "mouth" will be the CHARGEN service from
the INET superserver daemon. Destination "ear" will be a local port that you
can telnet into, and watch the pretty ASCII test puke forth.
{%- endtrans %}</p>
{% highlight lang='text' %}
{% trans %}EXAMPLE SESSION DIALOGUE -- simple telnet 127.0.0.1 2827 works{% endtrans %}
A = {{ _('Application') }}
C = {% trans %}BOB's Command response.{% endtrans %}
{{ _('FROM') }} {{ _('TO') }} {{ _('DIALOGUE') }}
A C setnick mouth
C A OK Nickname set to mouth
A C newkeys
C A OK ZMPz1zinTdy3~zGD~f3g9aikZTipujEvvXOEyYfq4Su-mNKerqG710hFbkR6P-xkouVyNQsqWLI8c6ngnkSwGdUfM7hGccqBYDjIubTrlr~0g2-l0vM7Y8nSqtFrSdMw~pyufXZ0Ys3NqUSb8NuZXpiH2lCCkFG21QPRVfKBGwvvyDVU~hPVfBHuR8vkd5x0teMXGGmiTzdB96DuNRWayM0y8vkP-1KJiPFxKjOXULjuXhLmINIOYn39bQprq~dAtNALoBgd-waZedYgFLvwHDCc9Gui8Cpp41EihlYGNW0cu0vhNFUN79N4DEpO7AtJyrSu5ZjFTAGjLw~lOvhyO2NwQ4RiC4UCKSuM70Fz0BFKTJquIjUNkQ8pBPBYvJRRlRG9HjAcSqAMckC3pvKKlcTJJBAE8GqexV7rdCCIsnasJXle-6DoWrDkY1s1KNbEVH6i1iUEtmFr2IHTpPeFCyWfZ581CAFNRbbUs-MmnZu1tXAYF7I2-oXTH2hXoxCGAAAA
{% endhighlight %}
<p><b>{% trans -%}
MAKE NOTE OF THE ABOVE DESTINATION KEY, YOURS WILL BE DIFFERENT!
{%- endtrans %}</b></p>
{% highlight lang='text' %}
{{ _('FROM') }} {{ _('TO') }} {{ _('DIALOGUE') }}
A C outhost 127.0.0.1
C A OK outhost set
A C outport 19
C A OK outbound port set
A C start
C A OK tunnel starting
{% endhighlight %}
<p>{% trans -%}
At this point, there was no error, a destination with a nickname of "mouth"
is set up. When you contact the destination provided, you actually connect
to the <code>CHARGEN</code> service on <code>19/TCP</code>.
{%- endtrans %}</p>
<p>{% trans -%}
Now for the other half, so that we can actually contact this destination.
{%- endtrans %}</p>
{% highlight lang='text' %}
{{ _('FROM') }} {{ _('TO') }} {{ _('DIALOGUE') }}
A C setnick ear
C A OK Nickname set to ear
A C newkeys
C A OK 8SlWuZ6QNKHPZ8KLUlExLwtglhizZ7TG19T7VwN25AbLPsoxW0fgLY8drcH0r8Klg~3eXtL-7S-qU-wdP-6VF~ulWCWtDMn5UaPDCZytdGPni9pK9l1Oudqd2lGhLA4DeQ0QRKU9Z1ESqejAIFZ9rjKdij8UQ4amuLEyoI0GYs2J~flAvF4wrbF-LfVpMdg~tjtns6fA~EAAM1C4AFGId9RTGot6wwmbVmKKFUbbSmqdHgE6x8-xtqjeU80osyzeN7Jr7S7XO1bivxEDnhIjvMvR9sVNC81f1CsVGzW8AVNX5msEudLEggpbcjynoi-968tDLdvb-CtablzwkWBOhSwhHIXbbDEm0Zlw17qKZw4rzpsJzQg5zbGmGoPgrSD80FyMdTCG0-f~dzoRCapAGDDTTnvjXuLrZ-vN-orT~HIVYoHV7An6t6whgiSXNqeEFq9j52G95MhYIfXQ79pO9mcJtV3sfea6aGkMzqmCP3aikwf4G3y0RVbcPcNMQetDAAAA
A C inhost 127.0.0.1
C A OK inhost set
A C inport 37337
C A OK inbound port set
A C start
C A OK tunnel starting
A C quit
C A OK Bye!
{% endhighlight %}
<p>{% trans -%}
Now all we need to do is telnet into 127.0.0.1, port 37337,
send the destination key or host address from addressbook we want to contact.
In this case, we want to contact "mouth", all we do is paste in the
key and it goes.
{%- endtrans %}</p>
<p>{% trans -%}
<b>NOTE:</b> The "quit" command in the command channel does NOT disconnect the tunnels like SAM.
{%- endtrans %}</p>
{% highlight lang='text' %}
$ telnet 127.0.0.1 37337
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
ZMPz1zinTdy3~zGD~f3g9aikZTipujEvvXOEyYfq4Su-mNKerqG710hFbkR6P-xkouVyNQsqWLI8c6ngnkSwGdUfM7hGccqBYDjIubTrlr~0g2-l0vM7Y8nSqtFrSdMw~pyufXZ0Ys3NqUSb8NuZXpiH2lCCkFG21QPRVfKBGwvvyDVU~hPVfBHuR8vkd5x0teMXGGmiTzdB96DuNRWayM0y8vkP-1KJiPFxKjOXULjuXhLmINIOYn39bQprq~dAtNALoBgd-waZedYgFLvwHDCc9Gui8Cpp41EihlYGNW0cu0vhNFUN79N4DEpO7AtJyrSu5ZjFTAGjLw~lOvhyO2NwQ4RiC4UCKSuM70Fz0BFKTJquIjUNkQ8pBPBYvJRRlRG9HjAcSqAMckC3pvKKlcTJJBAE8GqexV7rdCCIsnasJXle-6DoWrDkY1s1KNbEVH6i1iUEtmFr2IHTpPeFCyWfZ581CAFNRbbUs-MmnZu1tXAYF7I2-oXTH2hXoxCGAAAA
!"#$%&amp;'()*+,-./0123456789:;&lt;=&gt;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefg
!"#$%&amp;'()*+,-./0123456789:;&lt;=&gt;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgh
"#$%&amp;'()*+,-./0123456789:;&lt;=&gt;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghi
#$%&amp;'()*+,-./0123456789:;&lt;=&gt;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghij
$%&amp;'()*+,-./0123456789:;&lt;=&gt;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijk
...
{% endhighlight %}
<p>{% trans -%}
After a few virtual miles of this spew, press <code>Control-]</code>
{%- endtrans %}</p>
{% highlight lang='text' %}
...
cdefghijklmnopqrstuvwxyz{|}~ !"#$%&amp;'()*+,-./0123456789:;&lt;=&gt;?@ABCDEFGHIJK
defghijklmnopqrstuvwxyz{|}~ !"#$%&amp;'()*+,-./0123456789:;&lt;=&gt;?@ABCDEFGHIJKL
efghijklmnopqrstuvwxyz{|}~ !"#$%&amp;'()*+,-./0123456789:;&lt;=
telnet&gt; c
Connection closed.
{% endhighlight %}
<p>{% trans -%}
Here is what happened...
{%- endtrans %}</p>
{% highlight lang='text' %}
telnet -&gt; ear -&gt; i2p -&gt; mouth -&gt; chargen -.
telnet &lt;- ear &lt;- i2p &lt;- mouth &lt;-----------'
{% endhighlight %}
<p>{% trans -%}
You can connect to EEPSITES too!
{%- endtrans %}</p>
{% highlight lang='text' %}
$ telnet 127.0.0.1 37337
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
i2host.i2p
GET / HTTP/1.1
HTTP/1.1 200 OK
Date: Fri, 05 Dec 2008 14:20:28 GMT
Connection: close
Content-Type: text/html
Content-Length: 3946
Last-Modified: Fri, 05 Dec 2008 10:33:36 GMT
Accept-Ranges: bytes
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;I2HOST&lt;/title&gt;
&lt;link rel="shortcut icon" href="favicon.ico"&gt;
&lt;/head&gt;
...
&lt;a href="http://sponge.i2p/"&gt;--Sponge.&lt;/a&gt;&lt;/pre&gt;
&lt;img src="/counter.gif" alt="!@^7A76Z!#(*&amp;amp;%"&gt; visitors. &lt;/body&gt;
&lt;/html&gt;
Connection closed by foreign host.
$
{% endhighlight %}
<p>{% trans -%}
Pretty cool isn't it? Try some other well known EEPSITES if you like, nonexistent ones,
etc, to get a feel for what kind of output to expect in different situations.
For the most part, it is suggested that you ignore any of the error messages.
They would be meaningless to the application, and are only presented for human debugging.
{%- endtrans %}</p>
<p>{% trans -%}
Let's put down our destinations now that we are all done with them.
{%- endtrans %}</p>
<p>{% trans -%}
First, lets see what destination nicknames we have.
{%- endtrans %}</p>
{% highlight lang='text' %}
{{ _('FROM') }} {{ _('TO') }} {{ _('DIALOGUE') }}
A C list
C A DATA NICKNAME: mouth STARTING: false RUNNING: true STOPPING: false KEYS: true QUIET: false INPORT: not_set INHOST: localhost OUTPORT: 19 OUTHOST: 127.0.0.1
C A DATA NICKNAME: ear STARTING: false RUNNING: true STOPPING: false KEYS: true QUIET: false INPORT: 37337 INHOST: 127.0.0.1 OUTPORT: not_set OUTHOST: localhost
C A OK Listing done
{% endhighlight %}
<p>{% trans -%}
Alright, there they are. First, let's remove "mouth".
{%- endtrans %}</p>
{% highlight lang='text' %}
{{ _('FROM') }} {{ _('TO') }} {{ _('DIALOGUE') }}
A C getnick mouth
C A OK Nickname set to mouth
A C stop
C A OK tunnel stopping
A C clear
C A OK cleared
{% endhighlight %}
<p>{% trans -%}
Now to remove "ear", note that this is what happens when you type too fast,
and shows you what typical ERROR messages looks like.
{%- endtrans %}</p>
{% highlight lang='text' %}
{{ _('FROM') }} {{ _('TO') }} {{ _('DIALOGUE') }}
A C getnick ear
C A OK Nickname set to ear
A C stop
C A OK tunnel stopping
A C clear
C A ERROR tunnel is active
A C clear
C A OK cleared
A C quit
C A OK Bye!
{% endhighlight %}
<p>{% trans -%}
I won't bother to show an example of the receiver end of a bridge
because it is very simple. There are two possible settings for it, and
it is toggled with the "quiet" command.
{%- endtrans %}</p>
<p>{% trans -%}
The default is NOT quiet, and the first data to come into your
listening socket is the destination that is making the contact. It is a
single line consisting of the BASE64 address followed by a newline.
Everything after that is for the application to actually consume.
{%- endtrans %}</p>
<p>{% trans -%}
In quiet mode, think of it as a regular Internet connection. No
extra data comes in at all. It's just as if you are plain connected to
the regular Internet. This mode allows a form of transparency much like
is available on the router console tunnel settings pages, so that you
can use BOB to point a destination at a web server, for example, and
you would not have to modify the web server at all.
{%- endtrans %}</p>
<p>{% trans -%}
The advantage with using BOB for this is as discussed
previously. You could schedule random uptimes for the application,
redirect to a different machine, etc. One use of this may be something
like wanting to try to goof up router-to-destination upness guessing.
You could stop and start the destination with a totally different
process to make random up and down times on services. That way you
would only be stopping the ability to contact such a service, and not
have to bother shutting it down and restarting it. You could redirect
and point to a different machine on your LAN while you do updates, or
point to a set of backup machines depending on what is running, etc,
etc. Only your imagination limits what you could do with BOB.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,122 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Datagrams{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}August 2010{% endtrans %}{% endblock %}
{% block accuratefor %}0.8{% endblock %}
{% block content %}
<h2>{% trans %}Datagram Overview{% endtrans %}</h2>
<p>{% trans i2cp=site_url('docs/protocol/i2cp') -%}
Datagrams build upon the base <a href="{{ i2cp }}">I2CP</a> to provide authenticated
and repliable messages in a standard format. This lets applications reliably read
the "from" address out of a datagram and know that the address really sent the
message. This is necessary for some applications since the base I2P message is
completely raw - it has no "from" address (unlike IP packets). In addition, the
message and sender are authenticated by signing the payload.
{%- endtrans %}</p>
<p>{% trans streaming=site_url('docs/api/streaming'),
transports=site_url('docs/transport') -%}
Datagrams, like <a href="{{ streaming }}">streaming library packets</a>,
are an application-level construct.
These protocols are independent of the low-level <a href="{{ transports }}">transports</a>;
the protocols are converted to I2NP messages by the router, and
either protocol may be carried by either transport.
{%- endtrans %}</p>
<h2>{% trans %}Application Guide{% endtrans %}</h2>
<p>{% trans url='http://docs.i2p-projekt.de/javadoc/net/i2p/client/datagram/package-summary.html',
sam= site_url('docs/api/sam'),
socks=site_url('docs/api/socks') -%}
Applications written in Java may use the
<a href="{{ url }}">datagram API</a>,
while applications in other languages
can use <a href="{{ sam }}">SAM</a>'s datagram support.
There is also limited support in i2ptunnel in the <a href="{{ socks }}">SOCKS proxy</a>,
the 'streamr' tunnel types, and udpTunnel classes.
{%- endtrans %}</p>
<h3>{% trans %}Datagram Length{% endtrans %}</h3>
<p>{% trans -%}
The application designer should carefully consider the tradeoff of repliable vs. non-repliable
datagrams. Also, the datagram size will affect reliability, due to tunnel fragmentation into 1KB
tunnel messages. The more message fragments, the more likely that one of them will be dropped
by an intermediate hop. Messages larger than a few KB are not recommended.
Over about 10 KB, the delivery probablility drops dramatically.
Messages over 16 KB cannot be delivered over NTCP, dropping delivery chances even more.
{%- endtrans %}</p>
<p>{% trans elgamalaes=site_url('docs/how/elgamal-aes') -%}
Also note that the various overheads added by lower layers, in particular asymmetric
<a href="{{ elgamalaes }}">ElGamal/AES</a>, place a large burden on intermittent messages
such as used by a Kademlia-over-UDP application. The implementations are currently tuned
for frequent traffic using the streaming library. There are a high number
of session tags delivered, and a short session tag lifetime, for example.
There are currently no configuration parameters available within I2CP to tune
the ElGamal Session Tag parameters.
{%- endtrans %}</p>
<h3>{% trans %}I2CP Protocol Number and Ports{% endtrans %}</h3>
<p>{% trans -%}
The standard I2CP protocol number for datagrams is PROTO_DATAGRAM (17).
Applications may or may not choose to set the
protocol in the I2CP header. It is not set by default.
It must be set to demultiplex datagram and streaming traffic received on the same Destination.
{%- endtrans %}</p>
<p>{% trans i2cp=site_url('docs/protocol/i2cp') -%}
As datagrams are not connection-oriented, the application may require
port numbers to correlate datagrams with particular peers or communications sessions,
as is traditional with UDP over IP.
Applications may add 'from' and 'to' ports to the I2CP (gzip) header as described in
the <a href="{{ i2cp }}#format">I2CP page</a>.
{%- endtrans %}</p>
<p>{% trans i2psession='http://docs.i2p-projekt.de/javadoc/net/i2p/client/I2PSession.html' -%}
There is no method within the datagram API to specify whether it is non-repliable (raw)
or repliable. The application should be designed to expect the appropriate type.
The I2CP protocol number or port should be used by the application to
indicate datagram type.
The I2CP protocol numbers PROTO_DATAGRAM (signed) and PROTO_DATAGRAM_RAW are defined in the
<a href="{{ i2psession }}">I2PSession API</a>
for this purpose. A common design pattern in client/server datagram applications is to
use signed datagrams for a request which includes a nonce, and use a raw datagram
for the reply, returning the nonce from the request.
{%- endtrans %}</p>
<p>{% trans i2psession='http://docs.i2p-projekt.de/javadoc/net/i2p/client/I2PSession.html',
i2psessionmuxed='http://docs.i2p-projekt.de/javadoc/net/i2p/client/I2PSessionMuxedImpl.html' -%}
The protocols and ports may be set in I2CP's
<a href="{{ i2psession }}">I2PSession API</a>,
as implemented in
<a href="{{ i2psessionmuxed }}">I2PSessionMuxedImpl</a>.
{%- endtrans %}</p>
<h3>{% trans %}Data Integrity{% endtrans %}</h3>
<p>{% trans i2cp=site_url('docs/protocol/i2cp') -%}
Data integrity is assured by the gzip CRC-32 checksum implemented in
<a href="{{ i2cp }}#format">the I2CP layer</a>.
There is no checksum field in the datagram protocol.
{%- endtrans %}</p>
<h3>{% trans %}Packet Encapsulation{% endtrans %}</h3>
<p>{% trans garlicrouting=site_url('docs/how/garlic-routing'),
i2cp=site_url('docs/protocol/i2cp'),
i2np=site_url('docs/protocol/i2np'),
tunnelmessage=site_url('docs/spec/tunnel-message') -%}
Each datagram is sent through I2P as a single message (or as an individual clove in a
<a href="{{ garlicrouting }}">Garlic Message</a>).
Message encapsulation is implemented in the underlying
<a href="{{ i2cp }}">I2CP</a>,
<a href="{{ i2np }}">I2NP</a>, and
<a href="{{ tunnelmessage }}">tunnel message</a> layers.
There is no packet delimiter mechanism or length field in the datagram protocol.
{%- endtrans %}</p>
<h2 id="spec">{% trans %}Specification{% endtrans %}</h2>
<p><a href="{{ site_url('docs/spec/datagrams') }}">{% trans -%}
See the Datagrams Specification page.
{%- endtrans %}</a></p>
{% endblock %}

View File

@@ -0,0 +1,206 @@
{% extends "global/layout.html" %}
{% block title %}I2PControl API{% endblock %}
{% block content %}
<h1>{% trans %}I2PControl - Remote Control Service{% endtrans %}</h1>
<p>{% trans itoopie='http://'+i2pconv('itoopie.i2p')+'/' -%}
I2P enables a <a href="http://en.wikipedia.org/wiki/JSON-RPC">JSONRPC2</a> interface via the plugin <a href="{{ itoopie }}">I2PControl</a>.
The aim of the interface is to provide simple way to interface with a running I2P node. A client, itoopie, has been developed in parallel.
The JSONRPC2 implementation for the client as well as the plugin is provided by the java libraries <a href="http://software.dzhuvinov.com/json-rpc-2.0.html">JSON-RPC 2.0</a>.
A list of implementations of JSON-RPC for various languages can be found at <a href="http://json-rpc.org/wiki/implementations">the JSON-RPC wiki</a>.
{%- endtrans %}</p>
<p>{% trans %}I2PControl is by default listening on localhost:7650{% endtrans %}</p>
<h2>{% trans %}API, version 1.{% endtrans %}</h2>
<p>{% trans -%}
Parameters are only provided in a named way (maps).
{%- endtrans %}</p>
<h4>{% trans %}JSON-RPC 2 format{% endtrans %}</h4>
<div class="box" style="clear: none;"><pre>
{{ _('Request:') }}
{"id":"id", "method":"Method-name","params":{"Param-key-1":"param-value-1", "Param-key-2":"param-value-2", "Token":"**actual token**"}, "jsonrpc":"2.0"}
{{ _('Response:') }}
{"id":"id","result":{"Result-key-1":"result-value-1","Result-key-2":"result-value-2"},"jsonrpc":"2.0"}
</pre></div>
<ul>method-name &ndash; {{ _('Description') }}
<ul>{{ _('Request:') }}
<li>Param-key-1 &ndash; {{ _('Description') }}</li>
<li>Param-key-2 &ndash; {{ _('Description') }}</li>
<li>Token &ndash; {% trans %}Token used for authenticating every request (excluding the 'Authenticate' RPC method){% endtrans %}</li>
</ul>
<ul>{{ _('Response:') }}
<li>Result-key-1 &ndash; {{ _('Description') }}</li>
<li>Result-key-2 &ndash; {{ _('Description') }}</li>
</ul>
</ul>
<h4>{% trans %}Implemented methods{% endtrans %}</h4>
<ul>Authenticate &ndash; {% trans %}Creates and returns an authentication token used for further communication.{% endtrans %}
<ul>{{ _('Request:') }}
<li>API &ndash; [long] {% trans %}The version of the I2PControl API used by the client.{% endtrans %}</li>
<li>Password &ndash; [String] {% trans %}The password used for authenticating against the remote server.{% endtrans %}</li>
</ul>
<ul>{{ _('Response:') }}
<li>API &ndash; [long] {% trans %}The primary I2PControl API version implemented by the server.{% endtrans %}</li>
<li>Token &ndash; [String] {% trans %}The token used for further communication.{% endtrans %}</li>
</ul>
</ul>
<ul>Echo &ndash; {% trans %}Echoes the value of the echo key, used for debugging and testing.{% endtrans %}
<ul>{{ _('Request:') }}
<li>Echo &ndash; [String] {% trans %}Value will be returned in response.{% endtrans %}</li>
<li>Token &ndash; [String] {% trans %}Token used for authenticating the client. Is provided by the server via the 'Authenticate' RPC method.{% endtrans %}</li>
</ul>
<ul>{{ _('Response:') }}
<li>Result &ndash; [String] {% trans %}Value of the key 'echo' in the request.{% endtrans %}</li>
</ul>
</ul>
<ul>GetRate &ndash; {% trans %}Fetches rateStat from router statManager. Creates stat if not already created.{% endtrans %}
<ul>{{ _('Request:') }}
<li>Stat &ndash; [String] {% trans ratestats=site_url('misc/ratestats') %}Determines which rateStat to fetch, see <a href="{{ ratestats }}">ratestats</a>.{% endtrans %}</li>
<li>Period &ndash; [long] {% trans %}Determines which period a stat is fetched for. Measured in ms.{% endtrans %}</li>
<li>Token &ndash; [String] {% trans %}Token used for authenticating the client. Is provided by the server via the 'Authenticate' RPC method.{% endtrans %}</li>
</ul>
<ul>{{ _('Response:') }}
<li>Result &ndash; [double] {% trans %}Returns the average value for the reuested rateStat and period.{% endtrans %}</li>
</ul>
</ul>
<ul>I2PControl &ndash; {% trans %}Manages I2PControl. Ports, passwords and the like.{% endtrans %}
<ul>{{ _('Request:') }}
<li>*i2pcontrol.address &ndash; [String] {% trans %}Sets a new listen address for I2PControl (only 127.0.0.1 and 0.0.0.0 are implemented in I2PControl currently).{% endtrans %}</li>
<li>*i2pcontrol.password &ndash; [String] {% trans %}Sets a new password for I2PControl, all Authentication tokens will be revoked.{% endtrans %}</li>
<li>*i2pcontrol.port &ndash; [String] {% trans %}Switches which port I2PControl will listen for connections on.{% endtrans %}</li>
<li>Token &ndash; [String] {% trans %}Token used for authenticating the client. Is provided by the server via the 'Authenticate' RPC method.{% endtrans %}</li>
</ul>
<ul>{{ _('Response:') }}
<li>**i2pcontrol.address &ndash; [null] {% trans %}Returned if address was changed{% endtrans %}</li>
<li>**i2pcontrol.password &ndash; [null] {% trans %}Returned if setting was changed{% endtrans %}</li>
<li>**i2pcontrol.port &ndash; [null] {% trans %}Returned if setting was changed{% endtrans %}</li>
<li>SettingsSaved &ndash; [Boolean] {% trans %}Returns true if any changes were made.{% endtrans %}</li>
<li>RestartNeeded &ndash; [Boolean] {% trans %}Returns true if any changes requiring a restart to take effect were made.{% endtrans %}</li>
</ul>
</ul>
<ul>RouterInfo &ndash; {% trans %}Fetches basic information about the I2P router. Uptime, version etc.{% endtrans %}
<ul>{{ _('Request:') }}
<li>*i2p.router.status &ndash; [n/a]</li>
<li>*i2p.router.uptime &ndash; [n/a]</li>
<li>*i2p.router.version &ndash; [n/a]</li>
<li>*i2p.router.net.bw.inbound.1s &ndash; [n/a] </li>
<li>*i2p.router.net.bw.inbound.15s &ndash; [n/a] </li>
<li>*i2p.router.net.bw.outbound.1s &ndash; [n/a] </li>
<li>*i2p.router.net.bw.outbound.15s &ndash; [n/a] </li>
<li>*i2p.router.net.status &ndash; [n/a]</li>
<li>*i2p.router.net.tunnels.participating &ndash; [n/a] </li>
<li>*i2p.router.netdb.activepeers &ndash; [n/a] </li>
<li>*i2p.router.netdb.fastpeers &ndash; [n/a] </li>
<li>*i2p.router.netdb.highcapacitypeers &ndash; [n/a] </li>
<li>*i2p.router.netdb.isreseeding &ndash; [n/a] </li>
<li>*i2p.router.netdb.knownpeers &ndash; [n/a] </li>
<li>Token &ndash; [String] {% trans %}Token used for authenticating the client. Is provided by the server via the 'Authenticate' RPC method.{% endtrans %}</li>
</ul>
<ul>{{ _('Response:') }}
<li>**i2p.router.status &ndash; [String] {% trans %}What the status of the router is.{% endtrans %}</li>
<li>**i2p.router.uptime &ndash; [long] {% trans %}What the uptime of the router is in ms.{% endtrans %}</li>
<li>**i2p.router.version &ndash; [String] {% trans %}What version of I2P the router is running.{% endtrans %}</li>
<li>**i2p.router.net.bw.inbound.1s &ndash; [double] {% trans %}The 1 second average inbound bandwidth in Bps.{% endtrans %}</li>
<li>**i2p.router.net.bw.inbound.15s &ndash; [double] {% trans %}The 15 second average inbound bandwidth in Bps.{% endtrans %}</li>
<li>**i2p.router.net.bw.outbound.1s &ndash; [double] {% trans %}The 1 second average outbound bandwidth in Bps.{% endtrans %}</li>
<li>**i2p.router.net.bw.outbound.15s &ndash; [double] {% trans %}The 15 second average outbound bandwidth in Bps.{% endtrans %}</li>
<li>**i2p.router.net.status &ndash; [long] {% trans %}What the current network status is. According to the below enum:{% endtrans %}
<ul>
<li>0 &ndash; OK</li>
<li>1 &ndash; TESTING</li>
<li>2 &ndash; FIREWALLED</li>
<li>3 &ndash; HIDDEN</li>
<li>4 &ndash; WARN_FIREWALLED_AND_FAST</li>
<li>5 &ndash; WARN_FIREWALLED_AND_FLOODFILL</li>
<li>6 &ndash; WARN_FIREWALLED_WITH_INBOUND_TCP</li>
<li>7 &ndash; WARN_FIREWALLED_WITH_UDP_DISABLED</li>
<li>8 &ndash; ERROR_I2CP</li>
<li>9 &ndash; ERROR_CLOCK_SKEW</li>
<li>10 &ndash; ERROR_PRIVATE_TCP_ADDRESS</li>
<li>11 &ndash; ERROR_SYMMETRIC_NAT</li>
<li>12 &ndash; ERROR_UDP_PORT_IN_USE</li>
<li>13 &ndash; ERROR_NO_ACTIVE_PEERS_CHECK_CONNECTION_AND_FIREWALL</li>
<li>14 &ndash; ERROR_UDP_DISABLED_AND_TCP_UNSET</li>
</ul>
</li>
<li>**i2p.router.net.tunnels.participating &ndash; [long] {% trans %}How many tunnels on the I2P net are we participating in.{% endtrans %}</li>
<li>**i2p.router.netdb.activepeers &ndash; [long] {% trans %}How many peers have we communicated with recently.{% endtrans %}</li>
<li>**i2p.router.netdb.fastpeers &ndasg; [long] {% trans %}How many peers are considered 'fast'.{% endtrans %}</li>
<li>**i2p.router.netdb.highcapacitypeers &ndash; [long] {% trans %}How many peers are considered 'high capacity'.{% endtrans %}</li>
<li>**i2p.router.netdb.isreseeding &ndash; [boolean] {% trans %}Is the router reseeding hosts to its NetDB?{% endtrans %}</li>
<li>**i2p.router.netdb.knownpeers &ndash; [long] {% trans %}How many peers are known to us (listed in our NetDB).{% endtrans %}</li>
</ul>
</ul>
<ul>RouterManager &ndash; {% trans %}Manages I2P router restart/shutdown.{% endtrans %}
<ul>{{ _('Request:') }}
<li>*Reseed &ndash; [n/a] {% trans %}Initiates a router reseed, fetching peers into our NetDB from a remote host.{% endtrans %}</li>
<li>*Restart &ndash; [n/a] {% trans %}Restarts the router.{% endtrans %}</li>
<li>*RestartGraceful &ndash; [n/a] {% trans %}Restarts the router gracefully (waits for participating tunnels to expire).{% endtrans %}</li>
<li>*Shutdown &ndash; [n/a] {% trans %}Shuts down the router.{% endtrans %}</li>
<li>*ShutdownGraceful &ndash; [n/a] {% trans %}Shuts down the router gracefully (waits for participating tunnels to expire).{% endtrans %}</li>
<li>Token &ndash; [String] {% trans %}Token used for authenticating the client. Is provided by the server via the 'Authenticate' RPC method.{% endtrans %}</li>
</ul>
<ul>{{ _('Response:') }}
<li>**Reseed &ndash; [null] {% trans %}If requested, verifies that a reseed has been initiated.{% endtrans %}</li>
<li>**Restart &ndash; [null] {% trans %}If requested, verifies that a restart has been initiated.{% endtrans %}</li>
<li>**RestartGraceful &ndash; [null] {% trans %}If requested, verifies that a graceful restart has been initiated.{% endtrans %}</li>
<li>**Shutdown &ndash; [null] {% trans %}If requested, verifies that a shutdown has been initiated{% endtrans %}</li>
<li>**ShutdownGraceful &ndash; [null] {% trans %}If requested, verifies that a graceful shutdown has been initiated{% endtrans %}</li>
</ul>
</ul>
<ul>NetworkSetting &ndash; {% trans %}Fetches or sets various network related settings. Ports, addresses etc.{% endtrans %}
<ul>{{ _('Request:') }}
<li>*i2p.router.net.ntcp.port &ndash; [String] {% trans %}What port is used for the TCP transport. If null is submitted, current setting will be returned.{% endtrans %}</li>
<li>*i2p.router.net.ntcp.hostname &ndash; [String] {% trans %}What hostname is used for the TCP transport. If null is submitted, current setting will be returned.{% endtrans %}</li>
<li>*i2p.router.net.ntcp.autoip &ndash; [String] {% trans %}Use automatically detected ip for TCP transport. If null is submitted, current setting will be returned.{% endtrans %}</li>
<li>*i2p.router.net.ssu.port &ndash; [String] {% trans %}What port is used for the UDP transport. If null is submitted, current setting will be returned.{% endtrans %}</li>
<li>*i2p.router.net.ssu.hostname &ndash; [String] {% trans %}What hostname is used for the UDP transport. If null is submitted, current setting will be returned.{% endtrans %}</li>
<li>*i2p.router.net.ssu.autoip &ndash; [String] {% trans %}Which methods should be used for detecting the ip address of the UDP transport. If null is submitted, current setting will be returned.{% endtrans %}</li>
<li>*i2p.router.net.ssu.detectedip &ndash; [null] {% trans %}What ip has been detected by the UDP transport.{% endtrans %}</li>
<li>*i2p.router.net.upnp &ndash; [String] {% trans %}Is UPnP enabled. If null is submitted, current setting will be returned.{% endtrans %}</li>
<li>*i2p.router.net.bw.share &ndash; [String] {% trans %}How many percent of bandwidth is usable for participating tunnels. If null is submitted, current setting will be returned.{% endtrans %}</li>
<li>*i2p.router.net.bw.in &ndash; [String] {% trans %}How many KB/s of inbound bandwidth is allowed. If null is submitted, current setting will be returned.{% endtrans %}</li>
<li>*i2p.router.net.bw.out &ndash; [String] {% trans %}How many KB/s of outbound bandwidth is allowed. If null is submitted, current setting will be returned.{% endtrans %}</li>
<li>*i2p.router.net.laptopmode &ndash; [String] {% trans %}Is laptop mode enabled (change router identity and UDP port when IP changes ). If null is submitted, current setting will be returned.{% endtrans %}</li>
<li>Token &ndash; [String] {% trans %}Token used for authenticating the client. Is provided by the server via the 'Authenticate' RPC method. If null is submitted, current setting will be returned.{% endtrans %}</li>
</ul>
<ul>{{ _('Response:') }}
<li>**i2p.router.net.ntcp.port &ndash; [String] {% trans %}If requested, returns the port used for the TCP transport.{% endtrans %}</li>
<li>**i2p.router.net.ntcp.hostname &ndash; [String] {% trans %}If requested, returns the hostname used for the TCP transport.{% endtrans %}</li>
<li>**i2p.router.net.ntcp.autoip &ndash; [String] {% trans %}If requested, returns the method used for automatically detecting ip for the TCP transport.{% endtrans %}</li>
<li>**i2p.router.net.ssu.port &ndash; [String] {% trans %}If requested, returns the port used for the UDP transport.{% endtrans %}</li>
<li>**i2p.router.net.ssu.hostname &ndash; [String] {% trans %}If requested, returns the hostname used for the UDP transport.{% endtrans %}</li>
<li>**i2p.router.net.ssu.autoip &ndash; [String] {% trans %}If requested, returns methods used for detecting the ip address of the UDP transport.{% endtrans %}</li>
<li>**i2p.router.net.ssu.detectedip &ndash; [String] {% trans %}If requested, returns what ip has been detected by the UDP transport.{% endtrans %}</li>
<li>**i2p.router.net.upnp &ndash; [String] {% trans %}If requested, returns the UPNP setting.{% endtrans %}</li>
<li>**i2p.router.net.bw.share &ndash; [String] {% trans %}If requested, returns how many percent of bandwidth is usable for participating tunnels.{% endtrans %}</li>
<li>**i2p.router.net.bw.in &ndash; [String] {% trans %}If requested, returns how many KB/s of inbound bandwidth is allowed.{% endtrans %}</li>
<li>**i2p.router.net.bw.out &ndash; [String] {% trans %}If requested, returns how many KB/s of outbound bandwidth is allowed.{% endtrans %}</li>
<li>**i2p.router.net.laptopmode &ndash; [String] {% trans %}If requested, returns the laptop mode.{% endtrans %}</li>
<li>SettingsSaved &ndash; [boolean] {% trans %}Have the provided settings been saved.{% endtrans %}</li>
<li>RestartNeeded &ndash; [boolean] {% trans %}Is a restart needed for the new settings to be used.{% endtrans %}</li>
</ul>
</ul>
<p>* {% trans %}denotes an optional value.{% endtrans %}</p>
<p>** {% trans %}denotes a possibly occuring return value{% endtrans %}</p>
<h3>{% trans %}Error codes{% endtrans %}</h3>
<ul>{% trans %}Standard JSON-RPC2 error codes.{% endtrans %}
<li>-32700 &ndash; {% trans %}JSON parse error.{% endtrans %}</li>
<li>-32600 &ndash; {% trans %}Invalid request.{% endtrans %}</li>
<li>-32601 &ndash; {% trans %}Method not found.{% endtrans %}</li>
<li>-32602 &ndash; {% trans %}Invalid parameters.{% endtrans %}</li>
<li>-32603 &ndash; {% trans %}Internal error.{% endtrans %}</li>
</ul>
<ul>{% trans %}I2PControl specific error codes.{% endtrans %}
<li>-32001 &ndash; {% trans %}Invalid password provided.{% endtrans %}</li>
<li>-32002 &ndash; {% trans %}No authentication token presented.{% endtrans %}</li>
<li>-32003 &ndash; {% trans %}Authentication token doesn't exist.{% endtrans %}</li>
<li>-32004 &ndash; {% trans %}The provided authentication token was expired and will be removed.{% endtrans %}</li>
<li>-32005 &ndash; {% trans %}The version of the I2PControl API used wasn't specified, but is required to be specified.{% endtrans %}</li>
<li>-32006 &ndash; {% trans %}The version of the I2PControl API specified is not supported by I2PControl.{% endtrans %}</li>
</ul>
{% endblock %}

View File

@@ -0,0 +1,166 @@
{% extends "global/layout.html" %}
{% block title %}i2ptunnel{% endblock %}
{% block content %}
<!--Description of i2ptunnel and tunneling modes
default services
client modes
server modes
-->
<h1>I2PTunnel</h1>
<h2 id="overview">{% trans %}Overview{% endtrans %}</h2>
<p>{% trans naming=site_url('docs/naming') -%}
I2PTunnel is a tool for interfacing with and providing services on I2P.
Destination of an I2PTunnel can be defined using a <a href="{{ naming }}">hostname</a>,
<a href="{{ naming }}#base32">Base32</a>, or a full 516-byte destination key.
An established I2PTunnel will be available on your client machine as localhost:port.
If you wish to provide a service on I2P network, you simply create I2PTunnel to the
appropriate ip_address:port. A corresponding 516-byte destination key will be generated
for the service and it will become avaliable throughout I2P.
A web interface for I2PTunnel management is avaliable on
<a href="http://localhost:7657/i2ptunnel/">localhost:7657/i2ptunnel/</a>.
{%- endtrans %}</p>
<h2 id="default-services">{% trans %}Default Services{% endtrans %}</h2>
<h3 id="default-server-tunnels">{% trans %}Server tunnels{% endtrans %}</h3>
<ul>
<li>{% trans -%}
<b>I2P Webserver</b> - A tunnel pointed to a Jetty webserver run
on <a href="http://localhost:7658">localhost:7658</a> for convenient and quick hosting on I2P.
<br>The document root is:{% endtrans %}
<br><b>Unix</b> - %APPDATA%\I2P\eepsite\docroot
<br><b>Windows</b> - C:\Users\**username**\AppData\Roaming\I2P\eepsite\docroot
</li>
</ul>
<h3 id="default-client-tunnels">{% trans %}Client tunnels{% endtrans %}</h3>
<ul>
<li><b>I2P HTTP Proxy</b> - <i>localhost:4444</i></a> - {% trans -%}
A HTTP proxy used for browsing I2P and the regular internet anonymously through I2P.
Browsing internet through I2P uses a random proxy specified by the "Outproxies:" option.
{%- endtrans %}</li>
<li><b>Irc2P</b> - <i>localhost:6668</i> - {% trans %}An IRC tunnel to the default anonymous IRC network, Irc2P.{% endtrans %}</li>
<li><b>mtn.i2p2.i2p</b> - <i>localhost:8998</i> - {% trans monotone='http://en.wikipedia.org/wiki/Monotone_%28software%29' -%}
The anonymous <a href="{{ monotone }}">monotone</a>
sourcecode repository for I2P
{%- endtrans %}</li>
<li><b>smtp.postman.i2p</b> - <i>localhost:7659</i> - {% trans postman=i2pconv('hq.postman.i2p') -%}
A SMTP service provided by postman at <a href="http://{{ postman }}/?page_id=16">{{ postman }}</a>
{%- endtrans %}</li>
<li><b>pop3.postman.i2p</b> - <i>localhost:7660</i> - {% trans postman=i2pconv('hq.postman.i2p') -%}
The accompanying POP sevice of postman at <a href="http://{{ postman }}/?page_id=16">{{ postman }}</a>
{%- endtrans %}</li>
</ul>
<h2 id="client-modes">{% trans %}Client Modes{% endtrans %}</h2>
<h3 id="client-modes-standard">{% trans %}Standard{% endtrans %}</h3>
<p>{% trans -%}
Opens a local TCP port that connects to a service (like HTTP, FTP or SMTP) on a destination inside of I2P.
The tunnel is directed to a random host from the comma seperated (", ") list of destinations.
{%- endtrans %}</p>
<h3 id="client-mode-http">HTTP</h3>
<p>{% trans -%}
A HTTP-client tunnel. The tunnel connects to the destination specified by the URL
in a HTTP request. Supports proxying onto internet if an outproxy is provided. Strips HTTP connections of the following headers:
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
<b>Accept, Accept-Charset, Accept-Encoding, Accept-Language
and Accept-Ranges</b> as they vary greatly between browsers and can be used as an identifier.
{%- endtrans %}</li>
<li><b>Referer:</b></li>
<li><b>Via:</b></li>
<li><b>From:</b></li>
</ul>
<p>{% trans -%}
HTTP client/server tunnels are via I2Ptunnel force-enabling compression via the following http headers:
{%- endtrans %}</p>
<ul>
<li><b>Accept-Encoding: </b></li>
<li><b>X-Accept-Encoding: </b> x-i2p-gzip;q=1.0, identity;q=0.5, deflate;q=0, gzip;q=0, *;q=0</li>
</ul>
<p>{% trans -%}
Depending on if the tunnel is using an outproxy or not it will append the following User-Agent:
{%- endtrans %}</p>
<ul>
<li><i>{% trans %}Outproxy:{% endtrans %} </i><b>User-Agent:</b> Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6</li>
<li><i>{% trans %}Internal I2P use:{% endtrans %} </i><b>User-Agent:</b> MYOB/6.66 (AN/ON)</li>
</ul>
</p>
<h3 id="client-mode-irc">IRC</h3>
<p>{% trans -%}
Creates a connection to a random IRC server specified by the comma seprated (", ")
list of destinations. Only a whitelisted subset of IRC commands are allowed due to anonymity concerns.
{%- endtrans %}
<br>{% trans %}Whitelist:{% endtrans %}</p>
<ul>
<li>MODE</li>
<li>JOIN</li>
<li>NICK</li>
<li>QUIT</li>
<li>PART</li>
<li>WALLOPS</li>
<li>ERROR</li>
<li>KICK</li>
<li>H</li>
<li>TOPIC</li>
</ul>
<h3 id="client-mode-socks">SOCKS 4/4a/5</h3>
<p>{% trans -%}
Enables using the I2P router as a SOCKS proxy.
{%- endtrans %}</p>
<h3 id="client-mode-socks-irc">SOCKS IRC</h3>
<p>{% trans -%}
Enables using the I2P router as a SOCKS proxy with the command whitelist specified by
<a href="#client-mode-irc">IRC</a> client mode.
{%- endtrans %}</p>
<h3 id="client-mode-connect">CONNECT</h3>
<p>{% trans -%}
Creates a HTTP tunnel and uses the HTTP request method "CONNECT"
to build a TCP tunnel that usually is used for SSL and HTTPS.
{%- endtrans %}</p>
<h3 id="client-mode-streamr">Streamr</h3>
<p>{% trans -%}
Creates a UDP-server attached to a Streamr client I2PTunnel. The streamr client tunnel will
subscribe to a streamr server tunnel.
{%- endtrans %}</p>
<img src="{{ url_for('static', filename='images/I2PTunnel-streamr.png') }}">
<br>
<h2 id="server-modes">{% trans %}Server Modes{% endtrans %}</h2>
<h3 id="server-mode-standard">{% trans %}Standard{% endtrans %}</h3>
<p>{% trans -%}
Creates a destination to a local ip:port with an open TCP port.
{%- endtrans %}</p>
<h3 id="server-mode-http">HTTP</h3>
<p>{% trans -%}
Creates a destination to a local HTTP server ip:port. Supports gzip for requests with
Accept-encoding: x-i2p-gzip, replies with Content-encoding: x-i2p-gzip in such a request.
{%- endtrans %}</p>
<h3 id="server-mode-http-bidir">HTTP Bidirectional</h3>
<p>{% trans -%}
Functions as both a I2PTunnel HTTP Server, and a I2PTunnel HTTP client with no outproxying
capabilities. An example application would be a web application that does client-type
requests, or loopback-testing an eepsite as a diagnostic tool.
{%- endtrans %}</p>
<h3 id="server-mode-irc">IRC</h3>
<p>{% trans -%}
Creates a destination that filters the reqistration sequence of a client and passes
the clients destination key as a hostname to the IRC-server.
{%- endtrans %}</p>
<h3 id="server-mode-streamr">Streamr</h3>
<p>{% trans -%}
A UDP-client that connects to a media server is created. The UDP-Client is coupled with a Streamr server I2PTunnel.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,56 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Ministreaming Library{% endtrans %}{% endblock %}
{% block content %}
<h2>{% trans %}Note{% endtrans %}</h2>
<p>{% trans streaming=site_url('docs/api/streaming'), api='http://docs.i2p-projekt.de/javadoc/net/i2p/client/streaming/package-summary.html' -%}
The ministreaming library has been enhanced and extended by the
"full" <a href="{{ streaming }}">streaming library</a>.
Ministreaming is deprecated and is incompatible with today's applications.
The following documentation is old.
Also note that streaming extends ministreaming in the same Java package (net.i2p.client.streaming),
so the current <a href="{{ api }}">API documentation</a> contains both.
Obsolete ministreaming classes and methods are clearly marked as deprecated in the Javadocs.
{%- endtrans %}</p>
<h2>{% trans %}Ministreaming Library{% endtrans %}</h2>
<p>{% trans i2cp=site_url('docs/protocol/i2cp') %}
The ministreaming library is a layer on top of the core
<a href="{{ i2cp }}">I2CP</a> that allows reliable, in order, and authenticated streams
of messages to operate across an unreliable, unordered, and unauthenticated
message layer. Just like the TCP to IP relationship, this streaming
functionality has a whole series of tradeoffs and optimizations available, but
rather than embed that functionality into the base I2P code, it has been factored
off into its own library both to keep the TCP-esque complexities separate and to
allow alternative optimized implementations.
{%- endtrans %}</p>
<p>{% trans i2ptunnel=site_url('docs/api/i2ptunnel'), minwww=site_url('misc/minwww') -%}
The ministreaming library was written by mihi as a part of his
<a href="{{ i2ptunnel }}">I2PTunnel</a> application and then factored out and released
under the BSD license. It is called the "mini"streaming library because it makes
some simplifications in the implementation, while a more robust streaming library
could be further optimized for operation over I2P. The two main issues with
the ministreaming library are its use of the traditional TCP two phase
establishment protocol and the current fixed window size of 1. The establishment
issue is minor for long lived streams, but for short ones, such as quick HTTP
requests, the impact can be <a href="{{ minwww }}">significant</a>. As for the window
size, the ministreaming library doesn't maintain any ID or ordering within the
messages sent (or include any application level ACK or SACK), so it must wait
on average twice the time it takes to send a message before sending another.
{%- endtrans %}</p>
<p>{% trans api='http://docs.i2p-projekt.de/javadoc/net/i2p/client/streaming/package-summary.html',
samv3=site_url('docs/api/samv3') -%}
Even with those issues, the ministreaming library performs quite well in many
situations, and its <a href="{{ api }}">API</a>
is both quite simple and capable of remaining unchanged as different streaming
implementations are introduced. The library is deployed in its own
ministreaming.jar.
Developers in Java who would like to use it can
access the API directly, while developers in other languages can use it through
<a href="{{ samv3 }}">SAM</a>'s streaming support.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,366 @@
{% extends "global/layout.html" %}
{% block title %}SAM V1 Specification{% endblock %}
{% block lastupdated %}August 2010{% endblock %}
{% block accuratefor %}0.8{% endblock %}
{% block content %}
<p>Specified below is version 1 of a simple client protocol for interacting with
I2P.
Newer alternatives:
<a href="{{ site_url('docs/api/samv2') }}">SAM V2</a>,
<a href="{{ site_url('docs/api/samv3') }}">SAM V3</a>,
<a href="{{ site_url('docs/api/bob') }}">BOB</a>.
</p>
<pre>
----------------------------------------------------------------------
Simple Anonymous Messaging (SAM version 1.0) Specification
----------------------------------------------------------------------
Client application talks to SAM bridge, which deals with
all of the I2P functionality (using the streaming
lib for virtual streams, or I2CP directly for async messages).
All client&lt;--&gt;SAM bridge communication is unencrypted and
unauthenticated over a single TCP socket. Access to the SAM
bridge should be protected through firewalls or other means
(perhaps the bridge may have ACLs on what IPs it accepts
connections from).
All of these SAM messages are sent on a single line in plain ASCII,
terminated by the newline character (\n). The formatting shown
below is merely for readability, and while the first two words in
each message must stay in their specific order, the ordering of
the key=value pairs can change (e.g. "ONE TWO A=B C=D" or
"ONE TWO C=D A=B" are both perfectly valid constructions). In
addition, the protocol is case-sensitive.
Communication can take three distinct forms:
* <a href="{{ site_url('docs/api/streaming') }}">Virtual streams</a>
* <a href="{{ site_url('docs/spec/datagrams') }}#repliable">Repliable datagrams</a> (messages with a FROM field)
* <a href="{{ site_url('docs/spec/datagrams') }}#raw">Anonymous datagrams</a> (raw anonymous messages)
----------------------------------------------------------------------
SAM connection handshake
----------------------------------------------------------------------
No SAM communication can occur until after the client and bridge have
agreed on a protocol version, which is done by the client sending
a HELLO and the bridge sending a HELLO REPLY:
HELLO VERSION MIN=$min MAX=$max
and
HELLO REPLY RESULT=$result VERSION=1.0
The current version for both must be "1.0".
The RESULT value may be one of:
OK
NOVERSION
----------------------------------------------------------------------
SAM sessions
----------------------------------------------------------------------
A SAM session is created by a client opening a socket to the SAM
bridge, operating a handshake, and sending a SESSION CREATE message,
and the session terminates when the socket is disconnected.
Each I2P Destination can only be used for one SAM session at a time,
and can only use one of those forms (messages received through other
forms are dropped).
The SESSION CREATE message sent by the client to the bridge is as
follows:
SESSION CREATE
STYLE={STREAM,DATAGRAM,RAW}
DESTINATION={$name,TRANSIENT}
[DIRECTION={BOTH,RECEIVE,CREATE}]
[option=value]*
DESTINATION specifies what destination should be used for
sending and receiving messages/streams. If a $name is given, the
SAM bridge looks through its own local storage for an associated
destination (and private key). If no association exists matching
that name, it creates a new one. If the destination is specified
as TRANSIENT, it always creates a new one.
The DIRECTION can be specified for STREAM sessions, instructing
the bridge that the client will either be creating or receiving
streams, or both. If this is not specified, BOTH will be assumed.
Attempting to create an outbound stream when DIRECTION=RECEIVE
should result in an error, and incoming streams when
DIRECTION=CREATE should be ignored.
Additional options given should be fed into the I2P session
configuration if not interpreted by the SAM bridge (e.g.
"tunnels.depthInbound=0"). These options are documented below.
The SAM bridge itself should already be configured with what router
it should communicate over I2P through (though if need be there may
be a way to provide an override, e.g. i2cp.tcp.host=localhost and
i2cp.tcp.port=7654).
After receiving the session create message, the SAM bridge will reply
with a session status message, as follows:
SESSION STATUS
RESULT=$result
DESTINATION={$name,TRANSIENT}
[MESSAGE=...]
The RESULT value may be one of:
OK
DUPLICATED_DEST
I2P_ERROR
INVALID_KEY
If it's not OK, the MESSAGE should contain human-readable information
as to why the session could not be created.
----------------------------------------------------------------------
SAM virtual streams
----------------------------------------------------------------------
Virtual streams are guaranteed to be sent reliably and in order, with
failure and success notification as soon as it is available.
After establishing the session with STYLE=STREAM, both the client
and the SAM bridge may asynchronously send various messages back and
forth to manage the streams, as listed below:
STREAM CONNECT
ID=$id
DESTINATION=$base64key
This establishes a new virtual connection from the local destination
to the specified peer, marking it with the session-scoped unique ID.
The unique ID is an ASCII base 10 integer from 1 through (2^31-1).
The SAM bridge must reply to this with a stream status message:
STREAM STATUS
RESULT=$result
ID=$id
[MESSAGE=...]
The RESULT value may be one of:
OK
CANT_REACH_PEER
I2P_ERROR
INVALID_KEY
TIMEOUT
If the RESULT is OK, the destination specified is up and authorized
the connection; if the connection was not possible (timeout, etc),
RESULT will contain the appropriate error value (accompanied by an
optional human-readable MESSAGE).
On the receiving end, the SAM bridge simply notifies the client as
follows:
STREAM CONNECTED
DESTINATION=$base64key
ID=$id
This tells the client that the given destination has created a virtual
connection with them. The following data stream will be marked with
the given unique ID, that is an ASCII base 10 integer from -1 through
-(2^31-1).
When the client wants to send data on the virtual connection, they
do so as follows:
STREAM SEND
ID=$id
SIZE=$numBytes\n[$numBytes of data]
This adds the specified data to the buffer being sent to the peer
over the virtual connection. The send size $numBytes is how many
8bit bytes are included after the newline, which may be 1 through
32768 (32KB).
The SAM bridge will then do its best to deliver the message as
quickly and efficiently as possible, perhaps buffering multiple SEND
messages together. If there is an error delivering the data, or if
the remote side closes the connection, the SAM bridge will tell the
client:
STREAM CLOSED
RESULT=$result
ID=$id
[MESSAGE=...]
The RESULT value may be one of:
OK
CANT_REACH_PEER
I2P_ERROR
PEER_NOT_FOUND
TIMEOUT
If the connection has been cleanly closed by the other peer, $result
is set to OK. If $result is not OK, MESSAGE may convey a descriptive
message, such as "peer unreachable", etc. Whenever a client would
like to close the connection, they send the SAM bridge the close
message:
STREAM CLOSE
ID=$id
The bridge then cleans up what it needs to and discards that ID - no
further messages can be sent or received on it.
For the other side of the communication, whenever the peer has sent
some data and it is available for the client, the SAM bridge will
promptly deliver it:
STREAM RECEIVED
ID=$id
SIZE=$numBytes\n[$numBytes of data]
All streams are implicitly closed by the connection between the SAM
bridge and the client being dropped.
----------------------------------------------------------------------
SAM repliable datagrams
----------------------------------------------------------------------
While I2P doesn't inherently contain a FROM address, for ease of use
an additional layer is provided as repliable datagrams - unordered
and unreliable messages of up to 31KB in size that include a FROM
address (leaving up to 1KB for header material). This FROM address
is authenticated internally by SAM (making use of the destination's
signing key to verify the source) and includes replay prevention.
After establishing a SAM session with STYLE=DATAGRAM, the client can
send the SAM bridge:
DATAGRAM SEND
DESTINATION=$base64key
SIZE=$numBytes\n[$numBytes of data]
When a datagram arrives, the bridge delivers it to the client via:
DATAGRAM RECEIVED
DESTINATION=$base64key
SIZE=$numBytes\n[$numBytes of data]
The SAM bridge never exposes to the client the authentication headers
or other fields, merely the data that the sender provided. This
continues until the session is closed (by the client dropping the
connection).
----------------------------------------------------------------------
SAM anonymous datagrams
----------------------------------------------------------------------
Squeezing the most out of I2P's bandwidth, SAM allows clients to send
and receive anonymous datagrams, leaving authentication and reply
information up to the client themselves. These datagrams are
unreliable and unordered, and may be up to 32KB in size.
After establishing a SAM session with STYLE=RAW, the client can
send the SAM bridge:
RAW SEND
DESTINATION=$base64key
SIZE=$numBytes\n[$numBytes of data]
When a raw datagram arrives, the bridge delivers it to the client
via:
RAW RECEIVED
SIZE=$numBytes\n[$numBytes of data]
----------------------------------------------------------------------
SAM utility functionality
----------------------------------------------------------------------
The following message can be used by the client to query the SAM
bridge for name resolution:
NAMING LOOKUP
NAME=$name
which is answered by
NAMING REPLY
RESULT=$result
NAME=$name
[VALUE=$base64key]
[MESSAGE=$message]
The RESULT value may be one of:
OK
INVALID_KEY
KEY_NOT_FOUND
If NAME=ME, then the reply will contain the base64key used by the
current session (useful if you're using a TRANSIENT one). If $result
is not OK, MESSAGE may convey a descriptive message, such as "bad
format", etc.
Public and private base64 keys can be generated using the following
message:
DEST GENERATE
which is answered by
DEST REPLY
PUB=$pubkey
PRIV=$privkey
----------------------------------------------------------------------
RESULT values
----------------------------------------------------------------------
These are the values that can be carried by the RESULT field, with
their meaning:
OK Operation completed successfully
CANT_REACH_PEER The peer exists, but cannot be reached
DUPLICATED_DEST The specified Destination is already in use
I2P_ERROR A generic I2P error (e.g. I2CP disconnection, etc.)
INVALID_KEY The specified key is not valid (bad format, etc.)
KEY_NOT_FOUND The naming system can't resolve the given name
PEER_NOT_FOUND The peer cannot be found on the network
TIMEOUT Timeout while waiting for an event (e.g. peer answer)
----------------------------------------------------------------------
Tunnel, I2CP, and Streaming Options
----------------------------------------------------------------------
These options may be passed in as name=value pairs at the end of a
SAM SESSION CREATE line.
All sessions may include <a href="{{ site_url('docs/protocol/i2cp') }}#options">I2CP options such as tunnel lengths</a>.
STREAM sessions may include <a href="{{ site_url('docs/api/streaming') }}#options">Streaming lib options</a>.
See those references for option names and defaults.
----------------------------------------------------------------------
BASE 64 Notes
----------------------------------------------------------------------
Base 64 encoding must use the I2P standard Base 64 alphabet "A-Z, a-z, 0-9, -, ~".
----------------------------------------------------------------------
Client library implementations:
----------------------------------------------------------------------
Client libraries are available for C, C++, C#, Perl, and Python.
These are in the apps/sam/ directory in the <a href="{{ get_url('downloads_list') }}">I2P Source Package</a>.
----------------------------------------------------------------------
Default SAM Setup
----------------------------------------------------------------------
The default SAM port is 7656. SAM is not enabled by default in the I2P Router;
it must be started manually, or configured to start automatically,
on the configure clients page in the router console, or in the clients.config file.
</pre>
{% endblock %}

View File

@@ -0,0 +1,433 @@
{% extends "global/layout.html" %}
{% block title %}SAM V2 Specification{% endblock %}
{% block lastupdated %}August 2010{% endblock %}
{% block accuratefor %}0.8{% endblock %}
{% block content %}
<p>Specified below is a simple client protocol for interacting with I2P.
</p>
<p>
SAM V2 was introduced in I2P release 0.6.1.31.
Significant differences from SAM V1 are marked with "***".
Alternatives:
<a href="{{ site_url('docs/api/sam') }}">SAM V1</a>,
<a href="{{ site_url('docs/api/samv3') }}">SAM V3</a>,
<a href="{{ site_url('docs/api/bob') }}">BOB</a>.
</p>
<p />
<b>Version 2 Changes</b>
Compared to version 1, SAM v2 provides a way to manage several sockets
on the same I2P destination <i>in parallel</i>, i.e. the client does not
have to wait for data being successfully sent on one socket before sending
data on another socket. All data transits through the same
client&lt;--&gt;SAM socket.
For multiple sockets, see <a href="{{ site_url('docs/api/samv3') }}">SAM V3</a>.
</p>
<pre>
----------------------------------------------------------------------
Simple Anonymous Messaging (SAM version 2.0) Specification
----------------------------------------------------------------------
Client application talks to SAM bridge, which deals with
all of the I2P functionality (using the streaming
lib for virtual streams, or I2CP directly for async messages).
All client&lt;--&gt;SAM bridge communication is unencrypted and
unauthenticated over a single TCP socket. Access to the SAM
bridge should be protected through firewalls or other means
(perhaps the bridge may have ACLs on what IPs it accepts
connections from).
All of these SAM messages are sent on a single line in plain ASCII,
terminated by the newline character (\n). The formatting shown
below is merely for readability, and while the first two words in
each message must stay in their specific order, the ordering of
the key=value pairs can change (e.g. "ONE TWO A=B C=D" or
"ONE TWO C=D A=B" are both perfectly valid constructions). In
addition, the protocol is case-sensitive.
Communication can take three distinct forms:
* <a href="{{ site_url('docs/api/streaming') }}">Virtual streams</a>
* <a href="{{ site_url('docs/spec/datagrams') }}#repliable">Repliable datagrams</a> (messages with a FROM field)
* <a href="{{ site_url('docs/spec/datagrams') }}#raw">Anonymous datagrams</a> (raw anonymous messages)
----------------------------------------------------------------------
SAM connection handshake
----------------------------------------------------------------------
No SAM communication can occur until after the client and bridge have
agreed on a protocol version, which is done by the client sending
a HELLO and the bridge sending a HELLO REPLY:
HELLO VERSION MIN=$min MAX=$max
and
*** HELLO REPLY RESULT=$result VERSION=2.0
*** In order to force protocol version 2.0, the values of $min and $max
*** must be "2.0".
The RESULT value may be one of:
OK
NOVERSION
----------------------------------------------------------------------
SAM sessions
----------------------------------------------------------------------
A SAM session is created by a client opening a socket to the SAM
bridge, operating a handshake, and sending a SESSION CREATE message,
and the session terminates when the socket is disconnected.
Each I2P Destination can only be used for one SAM session at a time,
and can only use one of those forms (messages received through other
forms are dropped).
The SESSION CREATE message sent by the client to the bridge is as
follows:
SESSION CREATE
STYLE={STREAM,DATAGRAM,RAW}
DESTINATION={$name,TRANSIENT}
[DIRECTION={BOTH,RECEIVE,CREATE}]
[option=value]*
DESTINATION specifies what destination should be used for
sending and receiving messages/streams. If a $name is given, the
SAM bridge looks through its own local storage for an associated
destination (and private key). If no association exists matching
that name, it creates a new one. If the destination is specified
as TRANSIENT, it always creates a new one.
The DIRECTION can be specified for STREAM sessions, instructing
the bridge that the client will either be creating or receiving
streams, or both. If this is not specified, BOTH will be assumed.
Attempting to create an outbound stream when DIRECTION=RECEIVE
should result in an error, and incoming streams when
DIRECTION=CREATE should be ignored.
Additional options given should be fed into the I2P session
configuration if not interpreted by the SAM bridge (e.g.
"tunnels.depthInbound=0"). These options are documented below.
The SAM bridge itself should already be configured with what router
it should communicate over I2P through (though if need be there may
be a way to provide an override, e.g. i2cp.tcp.host=localhost and
i2cp.tcp.port=7654).
After receiving the session create message, the SAM bridge will reply
with a session status message, as follows:
SESSION STATUS
RESULT=$result
DESTINATION={$name,TRANSIENT}
[MESSAGE=...]
The RESULT value may be one of:
OK
DUPLICATED_DEST
I2P_ERROR
INVALID_KEY
If it's not OK, the MESSAGE should contain human-readable information
as to why the session could not be created.
----------------------------------------------------------------------
SAM virtual streams
----------------------------------------------------------------------
Virtual streams are guaranteed to be sent reliably and in order, with
failure and success notification as soon as it is available.
After establishing the session with STYLE=STREAM, both the client
and the SAM bridge may asynchronously send various messages back and
forth to manage the streams, as listed below:
STREAM CONNECT
ID=$id
DESTINATION=$base64key
This establishes a new virtual connection from the local destination
to the specified peer, marking it with the session-scoped unique ID.
The unique ID is an ASCII base 10 integer from 1 through (2^31-1).
The SAM bridge replies to this with a stream status message:
STREAM STATUS
RESULT=$result
ID=$id
[MESSAGE=...]
The RESULT value may be one of:
OK
CANT_REACH_PEER
I2P_ERROR
INVALID_KEY
TIMEOUT
If the RESULT is OK, the destination specified is up and authorized
the connection; if the connection was not possible (timeout, etc),
RESULT will contain the appropriate error value (accompanied by an
optional human-readable MESSAGE).
On the receiving end, the SAM bridge simply notifies the client as
follows:
STREAM CONNECTED
DESTINATION=$base64key
ID=$id
This tells the client that the given destination has created a virtual
connection with them. The following data stream will be marked with
the given unique ID, that is an ASCII base 10 integer from -1 through
-(2^31-1).
When the client wants to send data on the virtual connection, they
do so as follows:
STREAM SEND
ID=$id
SIZE=$numBytes\n[$numBytes of data]
This asks the SAM bridge to add the specified data to the buffer
being sent to the peer over the virtual connection. The send size
$numBytes is how many 8bit bytes are included after the newline,
which may be 1 through 32768 (32KB).
*** The SAM bridge immediately replies with:
***
*** STREAM SEND
*** ID=$id
*** RESULT=$result
*** STATE=$bufferState
***
*** where $bufferState can be :
*** - BUFFER_FULL : SAM's buffer has 32 or more KB of data
*** to send, and subsequent SEND requests
*** will fail ;
*** - READY : SAM's buffer is not full, and the next SEND
*** request is granted to be successful.
***
*** and $result is one of :
*** - OK : the data has been buffered successfully
*** - FAILED : the buffer was full, no data has been buffered
***
*** If the SAM bridge replied with BUFFER_FULL, it will send another
*** message as soon as its buffer is available again :
***
*** STREAM READY_TO_SEND ID=$id
***
***
***
*** When the result is OK, the SAM bridge will then do its best to deliver
*** the message as quickly and efficiently as possible, perhaps buffering
*** multiple SEND messages together. If there is an error delivering the
*** data, or if the remote side closes the connection, the SAM bridge will
*** tell the client:
STREAM CLOSED
RESULT=$result
ID=$id
[MESSAGE=...]
The RESULT value may be one of:
OK
CANT_REACH_PEER
I2P_ERROR
PEER_NOT_FOUND
TIMEOUT
If the connection has been cleanly closed by the other peer, $result
is set to OK. If $result is not OK, MESSAGE may convey a descriptive
message, such as "peer unreachable", etc. Whenever a client would
like to close the connection, they send the SAM bridge the close
message:
STREAM CLOSE
ID=$id
The bridge then cleans up what it needs to and discards that ID - no
further messages can be sent or received on it.
For the other side of the communication, whenever the peer has sent
some data and it is available for the client, the SAM bridge will
promptly deliver it:
STREAM RECEIVED
ID=$id
SIZE=$numBytes\n[$numBytes of data]
*** With SAM version 2.0, though, the client has first to tell the SAM
*** bridge how much incoming data is allowed for the whole session, by
*** sending a message :
***
*** STREAM RECEIVE
*** ID=$id
*** LIMIT=$limit\n
***
*** where $limit can be :
***
*** - NONE : the SAM bridge will keep on listening and deliver
*** incoming data (same behavior as in version 1.0)
***
*** - an integer (less than 2^64) : the number of received bytes
*** after which the SAM bridge will stop listening on
*** the incoming stream.
***
*** Whenever the client is ready to accept more bytes
*** from the stream, it has to send such a message again,
*** with a greater $limit.
***
*** The client has to send such STREAM RECEIVE messages after the
*** connection to the peer has been established, i.e. after the client
*** has received a "STREAM CONNECTED" or a "STREAM STATUS RESULT=OK"
*** from the SAM bridge.
All streams are implicitly closed by the connection between the SAM
bridge and the client being dropped.
----------------------------------------------------------------------
SAM repliable datagrams
----------------------------------------------------------------------
While I2P doesn't inherently contain a FROM address, for ease of use
an additional layer is provided as repliable datagrams - unordered
and unreliable messages of up to 31KB in size that include a FROM
address (leaving up to 1KB for header material). This FROM address
is authenticated internally by SAM (making use of the destination's
signing key to verify the source) and includes replay prevention.
After establishing a SAM session with STYLE=DATAGRAM, the client can
send the SAM bridge:
DATAGRAM SEND
DESTINATION=$base64key
SIZE=$numBytes\n[$numBytes of data]
When a datagram arrives, the bridge delivers it to the client via:
DATAGRAM RECEIVED
DESTINATION=$base64key
SIZE=$numBytes\n[$numBytes of data]
The SAM bridge never exposes to the client the authentication headers
or other fields, merely the data that the sender provided. This
continues until the session is closed (by the client dropping the
connection).
----------------------------------------------------------------------
SAM anonymous datagrams
----------------------------------------------------------------------
Squeezing the most out of I2P's bandwidth, SAM allows clients to send
and receive anonymous datagrams, leaving authentication and reply
information up to the client themselves. These datagrams are
unreliable and unordered, and may be up to 32KB in size.
After establishing a SAM session with STYLE=RAW, the client can
send the SAM bridge:
RAW SEND
DESTINATION=$base64key
SIZE=$numBytes\n[$numBytes of data]
When a raw datagram arrives, the bridge delivers it to the client
via:
RAW RECEIVED
SIZE=$numBytes\n[$numBytes of data]
----------------------------------------------------------------------
SAM utility functionality
----------------------------------------------------------------------
The following message can be used by the client to query the SAM
bridge for name resolution:
NAMING LOOKUP
NAME=$name
which is answered by
NAMING REPLY
RESULT=$result
NAME=$name
[VALUE=$base64key]
[MESSAGE=$message]
The RESULT value may be one of:
OK
INVALID_KEY
KEY_NOT_FOUND
If NAME=ME, then the reply will contain the base64key used by the
current session (useful if you're using a TRANSIENT one). If $result
is not OK, MESSAGE may convey a descriptive message, such as "bad
format", etc.
Public and private base64 keys can be generated using the following
message:
DEST GENERATE
which is answered by
DEST REPLY
PUB=$pubkey
PRIV=$privkey
----------------------------------------------------------------------
RESULT values
----------------------------------------------------------------------
These are the values that can be carried by the RESULT field, with
their meaning:
OK Operation completed successfully
CANT_REACH_PEER The peer exists, but cannot be reached
DUPLICATED_DEST The specified Destination is already in use
I2P_ERROR A generic I2P error (e.g. I2CP disconnection, etc.)
INVALID_KEY The specified key is not valid (bad format, etc.)
KEY_NOT_FOUND The naming system can't resolve the given name
PEER_NOT_FOUND The peer cannot be found on the network
TIMEOUT Timeout while waiting for an event (e.g. peer answer)
----------------------------------------------------------------------
Tunnel, I2CP, and Streaming Options
----------------------------------------------------------------------
These options may be passed in as name=value pairs at the end of a
SAM SESSION CREATE line.
All sessions may include <a href="{{ site_url('docs/protocol/i2cp') }}#options">I2CP options such as tunnel lengths</a>.
STREAM sessions may include <a href="{{ site_url('docs/api/streaming') }}#options">Streaming lib options</a>.
See those references for option names and defaults.
----------------------------------------------------------------------
BASE 64 Notes
----------------------------------------------------------------------
Base 64 encoding must use the I2P standard Base 64 alphabet "A-Z, a-z, 0-9, -, ~".
----------------------------------------------------------------------
Client library implementations:
----------------------------------------------------------------------
Client libraries are available for C, C++, C#, Perl, and Python.
These are in the apps/sam/ directory in the <a href="{{ get_url('downloads_list') }}">I2P Source Package</a>.
Some may be older and have not been updated for SAMv2 support.
----------------------------------------------------------------------
Default SAM Setup
----------------------------------------------------------------------
The default SAM port is 7656. SAM is not enabled by default in the I2P Router;
it must be started manually, or configured to start automatically,
on the configure clients page in the router console, or in the clients.config file.
</pre>
{% endblock %}

View File

@@ -0,0 +1,520 @@
{% extends "global/layout.html" %}
{% block title %}SAM V3{% endblock %}
{% block lastupdated %}August 2010{% endblock %}
{% block accuratefor %}0.8{% endblock %}
{% block content %}
<p>Specified below is a simple client protocol for interacting with I2P.
</p>
<p>SAM version 3
was introduced in I2P release 0.7.3.
Alternatives:
<a href="{{ site_url('docs/api/sam') }}">SAM V1</a>,
<a href="{{ site_url('docs/api/samv2') }}">SAM V2</a>,
<a href="{{ site_url('docs/api/bob') }}">BOB</a>.
</p>
<p />
<b>Version 3 Changes</b>
SAM v2 provided a way to manage several sockets
on the same I2P destination <i>in parallel</i>, i.e. the client does not
have to wait for data being successfully sent on one socket before sending
data on another socket. But all data transited through the same
client&lt;--&gt;SAM socket, which was quite complicated to manage for the client.
<p />
SAM v3 manages sockets in a different way: each <i>I2P socket</i>
matches a unique client&lt;--&gt;SAM socket, which is much more simple to handle.
This is similar to <a href="{{ site_url('docs/api/bob') }}">BOB</a>.
<br />
SAM v3 also offers a UDP port for sending datagrams through I2P, and
can forward back I2P datagrams to the client's datagram server.
<p />
<b>Version 3 Protocol</b>
<pre>
----------------------------------------------------------------------
Simple Anonymous Messaging (SAM version 3.0) Specification
----------------------------------------------------------------------
Client application talks to SAM bridge, which deals with
all of the I2P functionality (using the streaming
lib for virtual streams, or I2CP directly for async messages).
All client&lt;--&gt;SAM bridge communication is unencrypted and
unauthenticated. Access to the SAM
bridge should be protected through firewalls or other means
(perhaps the bridge may have ACLs on what IPs it accepts
connections from).
All of these SAM messages are sent on a single line in plain ASCII,
terminated by the newline character (\n). The formatting shown
below is merely for readability, and while the first two words in
each message must stay in their specific order, the ordering of
the key=value pairs can change (e.g. "ONE TWO A=B C=D" or
"ONE TWO C=D A=B" are both perfectly valid constructions). In
addition, the protocol is case-sensitive.
In the following, message examples are preceded by "-&gt; " for
messages sent by the client to the SAM bridge, and by "&lt;- " for
messages sent by the SAM bridge to the client.
I2P communications can take three distinct forms:
* <a href="{{ site_url('docs/api/streaming') }}">Virtual streams</a>
* <a href="{{ site_url('docs/spec/datagrams') }}#repliable">Repliable datagrams</a> (messages with a FROM field)
* <a href="{{ site_url('docs/spec/datagrams') }}#raw">Anonymous datagrams</a> (raw anonymous messages)
I2P communications are supported by I2P sessions, and each I2P
session is bound to an address (called destination). An I2P session
is associated with one of the three types above, and cannot carry
communications of another type.
----------------------------------------------------------------------
SAM connection handshake
----------------------------------------------------------------------
No SAM communication can occur until after the client and bridge have
agreed on a protocol version, which is done by the client sending
a HELLO and the bridge sending a HELLO REPLY:
-&gt; HELLO VERSION MIN=$min MAX=$max
and
&lt;- HELLO REPLY RESULT=OK VERSION=3.0
*** In order to force protocol version 3.0, the values of $min and $max
*** must be "3.0".
If the SAM bridge cannot find a suitable version, it replies with :
&lt;- HELLO REPLY RESULT=NOVERSION
If some error occurred, such as a bad request format, it replies with :
&lt;- HELLO REPLY RESULT=I2P_ERROR MESSAGE={$message}
----------------------------------------------------------------------
SAM sessions
----------------------------------------------------------------------
A SAM session is created by a client opening a socket to the SAM
bridge, operating a handshake, and sending a SESSION CREATE message,
and the session terminates when the socket is disconnected.
Each registered I2P Destination is uniquely associated with a session ID
(or nickname).
Each session is uniquely associated with :
* the socket from which the client creates the session
* its ID (or nickname)
The session creation message can only use one of these forms (messages
received through other forms are answered with an error message) :
-&gt; SESSION CREATE
STYLE={STREAM,DATAGRAM,RAW}
ID={$nickname}
DESTINATION={$private_destination_key,TRANSIENT}
[option=value]*
DESTINATION specifies what destination should be used for
sending and receiving messages/streams. It has to be a suitable
private base64 destination key. If the destination is
specified as TRANSIENT, the SAM bridge creates a new destination.
{$nickname} is the choice of the client. No whitespace is allowed.
Additional options given are passed to the I2P session
configuration if not interpreted by the SAM bridge (e.g.
outbound.length=0). These options are documented below.
The SAM bridge itself should already be configured with what router
it should communicate over I2P through (though if need be there may
be a way to provide an override, e.g. i2cp.tcp.host=localhost and
i2cp.tcp.port=7654).
After receiving the session create message, the SAM bridge will reply
with a session status message, as follows:
If the creation was successful :
&lt;- SESSION STATUS RESULT=OK DESTINATION={$private_destination_key}
If the nickname is already associated with a session :
&lt;- SESSION STATUS RESULT=DUPLICATED_ID
If the destination is already in use :
&lt;- SESSION STATUS RESULT=DUPLICATED_DEST
If the destination is not a valid private destination key :
&lt;- SESSION STATUS RESULT=INVALID_KEY
If some other error has occurred :
&lt;- SESSION STATUS RESULT=I2P_ERROR MESSAGE={$message}
If it's not OK, the MESSAGE should contain human-readable information
as to why the session could not be created.
SAM sessions live and die with the socket they are associated with.
When the socket is closed, the session dies, and all communications
using the session die at the same time. And the other way round, when
the session dies for any reason, the SAM bridge closes the socket.
----------------------------------------------------------------------
SAM virtual streams
----------------------------------------------------------------------
Virtual streams are guaranteed to be sent reliably and in order, with
failure and success notification as soon as it is available.
Streams are bidirectional communication sockets between two I2P
destinations, but their opening has to be requested by one of them.
Hereafter, CONNECT commands are used by the SAM client for such a
request. FORWARD / ACCEPT commands are used by the SAM client when
he wants to listen to requests coming from other I2P destinations.
-----------------------------
SAM virtual streams : CONNECT
-----------------------------
A client asks for a connection by :
* opening a new socket with the SAM bridge
* passing the same HELLO handshake as above
* sending the connection command :
-&gt; STREAM CONNECT
ID={$nickname}
DESTINATION=$peer_public_base64_key
[SILENT={true,false}]
This establishes a new virtual connection from the local session
whose ID is {$nickname} to the specified peer.
If SILENT=true is passed, the SAM bridge won't issue any other message
on the socket : if the connection fails, the socket will be closed.
If the connection succeeds, all remaining data passing through the
current socket is forwarded from and to the connected I2P destination
peer.
If SILENT=false, which is the default value, the SAM bridge sends a
last message to its client before forwarding or shutting down the
socket :
&lt;- STREAM STATUS
RESULT=$result
[MESSAGE=...]
The RESULT value may be one of:
OK
CANT_REACH_PEER
I2P_ERROR
INVALID_KEY
INVALID_ID
TIMEOUT
If the RESULT is OK, all remaining data passing through the
current socket is forwarded from and to the connected I2P destination
peer. If the connection was not possible (timeout, etc),
RESULT will contain the appropriate error value (accompanied by an
optional human-readable MESSAGE), and the SAM bridge closes the
socket.
----------------------------
SAM virtual streams : ACCEPT
----------------------------
A client waits for an incoming connection request by :
* opening a new socket with the SAM bridge
* passing the same HELLO handshake as above
* sending the accept command :
-&gt; STREAM ACCEPT
ID={$nickname}
[SILENT={true,false}]
This makes the session ${nickname} listen for one incoming
connection request from the I2P network.
The SAM bridge answers with :
&lt;- STREAM STATUS
RESULT=$result
[MESSAGE=...]
The RESULT value may be one of:
OK
I2P_ERROR
INVALID_ID
If the result is not OK, the socket is closed immediately by the SAM
bridge. If the result is OK, the SAM bridge starts waiting for an
incoming connection request from another I2P peer. When a request
arrives, the SAM bridge accepts it and :
* If SILENT=true was passed, the SAM bridge won't issue any other message
on the client socket : all remaining data passing through the
current socket is forwarded from and to the connected I2P destination
peer.
* If SILENT=false was passed, which is the default value, the SAM bridge
sends the client a ASCII line containing the base64 public destination key
of the requesting peer. After this '\n' terminated line, all remaining data
passing through the current socket is forwarded from and to the connected
I2P destination peer, until one of the peer closes the socket.
-----------------------------
SAM virtual streams : FORWARD
-----------------------------
A client can use a regular socket server and wait for connection requests
coming from I2P. For that, the client has to :
* open a new socket with the SAM bridge
* pass the same HELLO handshake as above
* send the forward command :
-&gt; STREAM FORWARD
ID={$nickname}
PORT={$port}
[HOST={$host}]
[SILENT={true,false}]
This makes the session ${nickname} listen for incoming
connection requests from the I2P network.
The SAM bridge answers with :
&lt;- STREAM STATUS
RESULT=$result
[MESSAGE=...]
The RESULT value may be one of:
OK
I2P_ERROR
INVALID_ID
* {$host} is the hostname or IP address of the socket server to which
SAM will forward connection requests. If not given, SAM takes the IP
of the socket that issued the forward command.
* {$port} is the port number of the socket server to which SAM will
forward connection requests. It is mandatory.
When a connection request arrives from I2P, the SAM bridge requests a
socket connection from {$host}:{$port}. If it is accepted after no more
than 3 seconds, SAM will accept the connection from I2P, and then :
* If SILENT=true was passed, all data passing through the obtained
current socket is forwarded from and to the connected I2P destination
peer.
* If SILENT=false was passed, which is the default value, the SAM bridge
sends on the obtained socket an ASCII line containing the base64 public
destination key of the requesting peer. After this '\n' terminated line,
all remaining data passing through the socket is forwarded from and to
the connected I2P destination peer, until one of the sides closes the
socket.
The I2P router will stop listening to incoming connection requests as
soon as the "forwarding" socket is closed.
----------------------------------------------------------------------
SAM repliable datagrams : sending a datagram
----------------------------------------------------------------------
While I2P doesn't inherently contain a FROM address, for ease of use
an additional layer is provided as repliable datagrams - unordered
and unreliable messages of up to 31KB in size that include a FROM
address (leaving up to 1KB for header material). This FROM address
is authenticated internally by SAM (making use of the destination's
signing key to verify the source) and includes replay prevention.
After establishing a SAM session with STYLE=DATAGRAM, the client can
send datagrams through SAM's UDP port (7655).
The first line of a datagram sent through this port has to be in the
following format :
3.0 {$nickname} {$base64_public_destination_key}
* 3.0 is the version of SAM
* {$nickname} is the id of the DGRAM session that will be used
* {$base64_public_destination_key} is the destination of the
datagram
* this line is '\n' terminated.
The first line will be discarded by SAM before sending the remaining
of the message to the specified destination.
----------------------------------------------------------------------
SAM repliable datagrams : receiving a datagram
----------------------------------------------------------------------
Received datagrams are written by SAM on the socket from which the
datagram session was opened, unless specified otherwise by the CREATE
command.
When a datagram arrives, the bridge delivers it to the client via the
message :
&lt;- DATAGRAM RECEIVED
DESTINATION=$base64key
SIZE=$numBytes\n[$numBytes of data]
The SAM bridge never exposes to the client the authentication headers
or other fields, merely the data that the sender provided. This
continues until the session is closed (by the client dropping the
connection).
----------------------------------------------------------------------
SAM repliable datagrams : forwarding datagrams
----------------------------------------------------------------------
When creating a datagram session, the client can ask SAM to forward
incoming messages to a specified ip:port. It does so by issuing the
CREATE command with PORT and HOST options :
-&gt; SESSION CREATE
STYLE=DATAGRAM
ID={$nickname}
DESTINATION={$private_destination_key,TRANSIENT}
PORT={$port}
[HOST={$host}]
[option=value]*
* {$host} is the hostname or IP address of the datagram server to
which SAM will forward datagrams. If not given, SAM takes the
IP of the socket that issued the forward command.
* {$port} is the port number of the datagram server to which SAM
will forward datagrams.
When a datagram arrives, the bridge sends to the specified host:port
a message containing the following data :
${sender_base64_destination_key}\n{$datagram_payload}
----------------------------------------------------------------------
SAM anonymous datagrams
----------------------------------------------------------------------
Squeezing the most out of I2P's bandwidth, SAM allows clients to send
and receive anonymous datagrams, leaving authentication and reply
information up to the client themselves. These datagrams are
unreliable and unordered, and may be up to 32KB in size.
After establishing a SAM session with STYLE=RAW, the client can
send anonymous datagrams through the SAM bridge exactly the same way
he sends non anonymous datagrams.
Both ways of receiving datagrams are also available for anonymous
datagrams.
When anonymous datagrams are to be written to the socket that created
the session,the bridge delivers it to the client via:
&lt;- RAW RECEIVED
SIZE=$numBytes\n[$numBytes of data]
When anonymous datagrams are to be forwarded to some host:port,
the bridge sends to the specified host:port a message containing
the following data :
{$datagram_payload}
----------------------------------------------------------------------
SAM utility functionality
----------------------------------------------------------------------
The following message can be used by the client to query the SAM
bridge for name resolution:
NAMING LOOKUP
NAME=$name
which is answered by
NAMING REPLY
RESULT=$result
NAME=$name
[VALUE=$base64key]
[MESSAGE=$message]
The RESULT value may be one of:
OK
INVALID_KEY
KEY_NOT_FOUND
If NAME=ME, then the reply will contain the base64key used by the
current session (useful if you're using a TRANSIENT one). If $result
is not OK, MESSAGE may convey a descriptive message, such as "bad
format", etc.
Public and private base64 keys can be generated using the following
message:
DEST GENERATE
which is answered by
DEST REPLY
PUB=$pubkey
PRIV=$privkey
----------------------------------------------------------------------
RESULT values
----------------------------------------------------------------------
These are the values that can be carried by the RESULT field, with
their meaning:
OK Operation completed successfully
CANT_REACH_PEER The peer exists, but cannot be reached
DUPLICATED_DEST The specified Destination is already in use
I2P_ERROR A generic I2P error (e.g. I2CP disconnection, etc.)
INVALID_KEY The specified key is not valid (bad format, etc.)
KEY_NOT_FOUND The naming system can't resolve the given name
PEER_NOT_FOUND The peer cannot be found on the network
TIMEOUT Timeout while waiting for an event (e.g. peer answer)
----------------------------------------------------------------------
Tunnel, I2CP, and Streaming Options
----------------------------------------------------------------------
These options may be passed in as name=value pairs at the end of a
SAM SESSION CREATE line.
All sessions may include <a href="{{ site_url('docs/protocol/i2cp') }}#options">I2CP options such as tunnel lengths</a>.
STREAM sessions may include <a href="{{ site_url('docs/api/streaming') }}#options">Streaming lib options</a>.
See those references for option names and defaults.
----------------------------------------------------------------------
BASE 64 Notes
----------------------------------------------------------------------
Base 64 encoding must use the I2P standard Base 64 alphabet "A-Z, a-z, 0-9, -, ~".
----------------------------------------------------------------------
Client library implementations:
----------------------------------------------------------------------
Client libraries are available for C, C++, C#, Perl, and Python.
These are in the apps/sam/ directory in the <a href="{{ get_url('downloads_list') }}">I2P Source Package</a>.
Some may be older and have not been updated for SAMv3 support.
----------------------------------------------------------------------
Default SAM Setup
----------------------------------------------------------------------
The default SAM port is 7656. SAM is not enabled by default in the I2P Router;
it must be started manually, or configured to start automatically,
on the configure clients page in the router console, or in the clients.config file.
The default SAM UDP port is 7655, listening on 0.0.0.0.
These may be changed by adding the arguments sam.udp.port=nnnnn and/or
sam.udp.host=w.x.y.z to the invocation.
</pre>
{% endblock %}

View File

@@ -0,0 +1,75 @@
{% extends "global/layout.html" %}
{% block title %}SOCKS{% endblock %}
{% block content %}
<h2>{% trans %}SOCKS and SOCKS proxies{% endtrans %}</h2>
<p>{% trans %}
The SOCKS proxy is working as of release 0.7.1. SOCKS 4/4a/5 are supported.
Enable SOCKS by creating a SOCKS client tunnel in i2ptunnel.
Both shared-clients and non-shared are supported.
There is no SOCKS outproxy so it is of limited use.
{%- endtrans %}</p>
<p>{% trans faq=site_url('faq') %}
As it says on the <a href="{{ faq }}#socks">FAQ</a>:
{%- endtrans %}</p>
<pre>{% trans -%}
Many applications leak sensitive
information that could identify you on the Internet. I2P only filters
connection data, but if the program you intend to run sends this
information as content, I2P has no way to protect your anonymity. For
example, some mail applications will send the IP address of the machine
they are running on to a mail server. There is no way for I2P to filter
this, thus using I2P to 'socksify' existing applications is possible, but
extremely dangerous.
{%- endtrans %}</pre>
<p>{% trans -%}
And quoting from a 2005 email:
{%- endtrans %}</p>
<pre>{% trans -%}
... there is a reason why human and
others have both built and abandoned the SOCKS proxies. Forwarding
arbitrary traffic is just plain unsafe, and it behooves us as
developers of anonymity and security software to have the safety of
our end users foremost in our minds.
{%- endtrans %}</pre>
<p>{% trans -%}
Hoping that we can simply strap an arbitrary client on top of I2P
without auditing both its behavior and its exposed protocols for
security and anonymity is naive. Pretty much *every* application
and protocol violates anonymity, unless it was designed for it
specifically, and even then, most of those do too. That's the
reality. End users are better served with systems designed for
anonymity and security. Modifying existing systems to work in
anonymous environments is no small feat, orders of magnitude more
work that simply using the existing I2P APIs.
{%- endtrans %}</p>
<p>{% trans -%}
The SOCKS proxy
supports standard addressbook names, but not Base64 destinations.
Base32 hashes should work as of release 0.7.
It supports outgoing connections only, i.e. an I2PTunnel Client.
UDP support is stubbed out but not working yet.
Outproxy selection by port number is stubbed out.
{%- endtrans %}</p>
<h3>{% trans %}See Also{% endtrans %}</h3>
<ul>
<li>{% trans meeting81=get_url('meetings_show', id=81), meeting82=get_url('meetings_show', id=82) -%}
The notes for <a href="{{ meeting81 }}">Meeting 81</a> and
<a href="{{ meeting82 }}">Meeting 82</a> in March 2004.
{%- endtrans %}</li>
<li>
<a href="http://www.abenteuerland.at/onioncat/">Onioncat</a>
<li>
<a href="http://{{ i2pconv('zzz.i2p') }}/">{{ i2pconv('zzz.i2p') }}</a>
</ul>
<h3>{% trans %}If You Do Get Something Working{% endtrans %}</h3>
<p>{% trans -%}
Please let us know. And please provide substantial warnings about the
risks of socks proxies.
{%- endtrans %}
{% endblock %}

View File

@@ -0,0 +1,528 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Streaming Library{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}July 2013{% endtrans %}{% endblock %}
{% block accuratefor %}0.9.7{% endblock %}
{% block content %}
<h2>{% trans %}Overview{% endtrans %}</h2>
<p>{% trans datagrams=site_url('docs/spec/datagrams') -%}
The streaming library is technically part of the "application" layer,
as it is not a core router function.
In practice, however, it provides a vital function for almost all
existing I2P applications, by providing a TCP-like
streams over I2P, and allowing existing apps to be easily ported to I2P.
The other end-to-end transport library for client communication is the
<a href="{{ datagrams }}">datagram library</a>.
{%- endtrans %}</p>
<p>{% trans i2cp=site_url('docs/protocol/i2cp') -%}
The streaming library is a layer on top of the core
<a href="{{ i2cp }}">I2CP API</a> that allows reliable, in-order, and authenticated streams
of messages to operate across an unreliable, unordered, and unauthenticated
message layer. Just like the TCP to IP relationship, this streaming
functionality has a whole series of tradeoffs and optimizations available, but
rather than embed that functionality into the base I2P code, it has been factored
off into its own library both to keep the TCP-esque complexities separate and to
allow alternative optimized implementations.
{%- endtrans %}</p>
<p>{% trans -%}
In consideration of the relatively high cost of messages,
the streaming library's protocol for scheduling and delivering those messages has been optimized to
allow individual messages passed to contain as much information as is available.
For instance, a small HTTP transaction proxied through the streaming library can
be completed in a single round trip - the first messages bundle a SYN, FIN, and
the small HTTP request payload, and the reply bundles the SYN,
FIN, ACK, and the HTTP response payload. While an additional
ACK must be transmitted to tell the HTTP server that the SYN/FIN/ACK has been
received, the local HTTP proxy can often deliver the full response to the browser
immediately.
{%- endtrans %}</p>
<p>{% trans -%}
The streaming library bears much resemblance to an
abstraction of TCP, with its sliding windows, congestion control algorithms
(both slow start and congestion avoidance), and general packet behavior (ACK,
SYN, FIN, RST, rto calculation, etc).
{%- endtrans %}</p>
<p>{% trans -%}
The streaming library is
a robust library
which is optimized for operation over I2P.
It has a one-phase setup, and
it contains a full windowing implementation.
{%- endtrans %}</p>
<h2 id="api">{% trans %}API{% endtrans %}</h2>
<p>{% trans i2cp=site_url('docs/protocol/i2cp') -%}
The streaming library API provides a standard socket paradigm to Java applications.
The lower-level <a href="{{ i2cp }}">I2CP</a> API is completely hidden, except that
applications may pass <a href="{{ i2cp }}#options">I2CP parameters</a> through the
streaming library, to be interpreted by I2CP.
{%- endtrans %}</p>
<p>{% trans i2cp=site_url('docs/protocol/i2cp'),
i2psktmf='http://docs.i2p-projekt.de/javadoc/net/i2p/client/streaming/I2PSocketManagerFactory.html',
i2psktm='http://docs.i2p-projekt.de/javadoc/net/i2p/client/streaming/I2PSocketManager.html',
i2psess='http://docs.i2p-projekt.de/javadoc/net/i2p/client/I2PSession.html',
i2pskt='http://docs.i2p-projekt.de/javadoc/net/i2p/client/streaming/I2PSocket.html',
i2psskt='http://docs.i2p-projekt.de/javadoc/net/i2p/client/streaming/I2PServerSocket.html' -%}
The standard interface to the streaming lib is for the application to use the
<a href="{{ i2psktmf }}">I2PSocketManagerFactory</a> to create an
<a href="{{ i2psktm }}">I2PSocketManager</a>. The application then asks the
socket manager for an <a href="{{ i2psess }}">I2PSession</a>, which will cause
a connection to the router via <a href="{{ i2cp }}">I2CP</a>. The application
can then setup connections with an <a href="{{ i2pskt }}">I2PSocket</a> or
receive connections with an <a href="{{ i2psskt }}">I2PServerSocket</a>.
{%- endtrans %}</p>
<p>{% trans url='http://docs.i2p-projekt.de/javadoc/net/i2p/client/streaming/package-summary.html' -%}
Here are the <a href="{{ url }}">full streaming library Javadocs</a>.
{%- endtrans %}</p>
<p>{% trans -%}
For a good example of usage, see the i2psnark code.
{%- endtrans %}</p>
<h3 id="options">{% trans %}Options and Defaults{% endtrans %}</h3>
<p>{% trans i2psktmf='http://docs.i2p-projekt.de/javadoc/net/i2p/client/streaming/I2PSocketManagerFactory.html' -%}
The options and current default values are listed below.
Options are case-sensitive and may be set for the whole router, for a particular client, or for an individual socket on a
per-connection basis.
Many values are tuned for HTTP performance over typical I2P conditions. Other applications such
as peer-to-peer services are strongly encouraged to
modify as necessary, by setting the options and passing them via the call to
<a href="{{ i2psktmf }}">I2PSocketManagerFactory</a>.createManager(_i2cpHost, _i2cpPort, opts).
Time values are in ms.
{%- endtrans %}</p>
<p>{% trans samv3=site_url('docs/api/samv3'), bob=site_url('docs/api/bob'), i2ptunnel=site_url('docs/api/i2ptunnel') -%}
Note that higher-layer APIs, such as <a href="{{ samv3 }}">SAM</a>,
<a href="{{ bob }}">BOB</a>, and <a href="{{ i2ptunnel }}">I2PTunnel</a>,
may override these defaults with their own defaults.
Also note that many options only apply to servers listening for incoming connections.
{%- endtrans %}</p>
<p>{% trans -%}
As of release 0.9.1, most, but not all, options may be changed on an active socket manager or session.
See the javadocs for details.
{%- endtrans %}</p>
<table>
<tr><th>{{ _('Option') }}</th><th>{{ _('Default') }}</th><th>{{ _('Notes') }}</th>
</tr>
<tr><td>i2cp.accessList</td><td>null</td><td>{% trans -%}
Comma- or space-separated list of Base64 peer Hashes used for either access list or blacklist.
{%- endtrans %} {% trans release='0.7.13' -%}
As of release {{ release }}.
{%- endtrans %}</td></tr>
<tr><td>i2cp.enableAccessList</td><td>false</td><td>{% trans -%}
Use the access list as a whitelist for incoming connections.
{%- endtrans %} {% trans release='0.7.13' -%}
As of release {{ release }}.
{%- endtrans %}</td></tr>
<tr><td>i2cp.enableBlackList</td><td>false</td><td>{% trans -%}
Use the access list as a blacklist for incoming connections.
{%- endtrans %} {% trans release='0.7.13' -%}
As of release {{ release }}.
{%- endtrans %}</td></tr>
<!--
<tr><td>i2p.streaming.alpha</td><td>0.125</td><td>
Ref. RFC 6298. Floating point value.
{% trans release='0.9.8' -%}
As of release {{ release }}.
{%- endtrans %}</td></tr>
-->
<tr><td>i2p.streaming.answerPings</td><td>true</td><td>{% trans -%}
Whether to respond to incoming pings
{%- endtrans %}</td></tr>
<!--
<tr><td>i2p.streaming.beta</td><td>0.25</td><td>
Ref. RFC 6298. Floating point value.
{% trans release='0.9.8' -%}
As of release {{ release }}.
{%- endtrans %}</td></tr>
-->
<tr><td>i2p.streaming.blacklist</td><td>null</td><td>{% trans -%}
Comma- or space-separated list of Base64 peer Hashes to be
blacklisted for incoming connections to ALL destinations in the context.
This option must be set in the context properties, NOT in the createManager() options argument.
Note that setting this in the router context will not affect clients outside the
router in a separate JVM and context.
{%- endtrans %} {% trans release='0.9.3' -%}
As of release {{ release }}.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.bufferSize</td><td>64K</td><td>{% trans -%}
How much transmit data (in bytes) will be accepted that hasn't been written out yet.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.congestionAvoidanceGrowthRateFactor</td><td>1</td><td>{% trans -%}
When we're in congestion avoidance, we grow the window size at the rate
of <code>1/(windowSize*factor)</code>. In standard TCP, window sizes are in bytes,
while in I2P, window sizes are in messages.
A higher number means slower growth.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.connectDelay</td><td>-1</td><td>{% trans -%}
How long to wait after instantiating a new con
before actually attempting to connect. If this is
&lt;= 0, connect immediately with no initial data. If greater than 0, wait
until the output stream is flushed, the buffer fills,
or that many milliseconds pass, and include any initial data with the SYN.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.connectTimeout</td><td>5*60*1000</td><td>{% trans -%}
How long to block on connect, in milliseconds. Negative means indefinitely. Default is 5 minutes.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.disableRejectLogging</td><td>false</td><td>{% trans -%}
Whether to disable warnings in the logs when an incoming connection is rejected due to connection limits.
{%- endtrans %} {% trans release='0.9.4' -%}
As of release {{ release }}.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.enforceProtocol</td><td>false</td><td>{% trans -%}
Whether to listen only for the streaming protocol.
Setting to true will prohibit communication with Destinations earlier than release 0.7.1
(released March 2009). Set to true if running multiple protocols on this Destination.
{%- endtrans %} {% trans release='0.9.1' -%}
As of release {{ release }}.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.inactivityAction</td><td>2 (send) </td><td>{% trans -%}
(0=noop, 1=disconnect)
What to do on an inactivity timeout - do nothing, disconnect, or send a duplicate ack.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.inactivityTimeout</td><td>90*1000</td></tr>
<tr><td>i2p.streaming.initialAckDelay</td><td>2000</td></tr>
<tr><td>i2p.streaming.initialResendDelay</td><td>1000</td><td>{% trans -%}
The initial value of the resend delay field in the packet header, times 1000.
Not fully implemented; see below.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.initialRTO</td><td>9000</td><td>{% trans -%}
Initial timeout
(if no <a href="#sharing">sharing data</a> available).
{%- endtrans %} {% trans release='0.9.8' -%}
As of release {{ release }}.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.initialRTT</td><td>8000 </td><td>{% trans -%}
Initial round trip time estimate
(if no <a href="#sharing">sharing data</a> available).
Disabled as of release 0.9.8; uses actual RTT.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.initialWindowSize</td><td>6</td><td>({% trans %}if no <a href="#sharing">sharing data</a> available{% endtrans %}) {% trans -%}
In standard TCP, window sizes are in bytes, while in I2P, window sizes are in messages.
{%- endtrans %}</td></tr>
<!--
<tr><td>i2p.streaming.kappa</td><td>4.0</td><td>
Ref. RFC 6298 "K". Floating point value.
{% trans release='0.9.8' -%}
As of release {{ release }}.
{%- endtrans %}</td></tr>
-->
<tr><td>i2p.streaming.maxConcurrentStreams</td><td>-1 </td><td>{% trans -%}
(0 or negative value means unlimited)
This is a total limit for incoming and outgoing combined.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.maxConnsPerMinute</td><td>0 </td><td>{% trans -%}
Incoming connection limit (per peer; 0 means disabled)
{%- endtrans %} {% trans release='0.7.14' -%}
As of release {{ release }}.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.maxConnsPerHour</td><td>0 </td><td>{% trans -%}
(per peer; 0 means disabled)
{%- endtrans %} {% trans release='0.7.14' -%}
As of release {{ release }}.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.maxConnsPerDay</td><td>0 </td><td>{% trans -%}
(per peer; 0 means disabled)
{%- endtrans %} {% trans release='0.7.14' -%}
As of release {{ release }}.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.maxMessageSize</td><td>1730</td><td>{% trans -%}
The MTU in bytes.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.maxResends</td><td>8</td><td>{% trans -%}
Maximum number of retransmissions before failure.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.maxTotalConnsPerMinute</td><td>0 </td><td>{% trans -%}
Incoming connection limit (all peers; 0 means disabled)
{%- endtrans %} {% trans release='0.7.14' -%}
As of release {{ release }}.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.maxTotalConnsPerHour</td><td>0 </td><td>{% trans -%}
(all peers; 0 means disabled)
Use with caution as exceeding this will disable a server for a long time.
{%- endtrans %} {% trans release='0.7.14' -%}
As of release {{ release }}.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.maxTotalConnsPerDay</td><td>0 </td><td>{% trans -%}
(all peers; 0 means disabled)
Use with caution as exceeding this will disable a server for a long time.
{%- endtrans %} {% trans release='0.7.14' -%}
As of release {{ release }}.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.maxWindowSize</td><td>128</td></tr>
<tr><td>i2p.streaming.profile</td><td>1 (bulk)</td><td>{% trans -%}
(2=interactive not supported)
This doesn't currently do anything, but setting it to a value other than 1 will cause an error.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.readTimeout</td><td>-1</td><td>{% trans -%}
How long to block on read, in milliseconds. Negative means indefinitely.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.slowStartGrowthRateFactor</td><td>1</td><td>{% trans -%}
When we're in slow start, we grow the window size at the rate
of 1/(factor). In standard TCP, window sizes are in bytes,
while in I2P, window sizes are in messages.
A higher number means slower growth.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.tcbcache.rttDampening</td><td>0.75</td><td>{% trans -%}
Ref: RFC 2140. Floating point value.
May be set only via context properties, not connection options.
{%- endtrans %} {% trans release='0.9.8' -%}
As of release {{ release }}.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.tcbcache.rttdevDampening</td><td>0.75</td><td>{% trans -%}
Ref: RFC 2140. Floating point value.
May be set only via context properties, not connection options.
{%- endtrans %} {% trans release='0.9.8' -%}
As of release {{ release }}.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.tcbcache.wdwDampening</td><td>0.75</td><td>{% trans -%}
Ref: RFC 2140. Floating point value.
May be set only via context properties, not connection options.
{%- endtrans %} {% trans release='0.9.8' -%}
As of release {{ release }}.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.writeTimeout</td><td>-1</td><td>{% trans -%}
How long to block on write/flush, in milliseconds. Negative means indefinitely.
{%- endtrans %}</td></tr>
</table>
<h2>{% trans %}Protocol Specification{% endtrans %}</h2>
<p><a href="{{ site_url('docs/spec/streaming') }}">{% trans -%}
See the Streaming Library Specification page.
{%- endtrans %}</a></p>
<h2>{% trans %}Implementation Details{% endtrans %}</h2>
<h3>{% trans %}Setup{% endtrans %}</h3>
<p>{% trans -%}
The initiator sends a packet with the SYNCHRONIZE flag set. This packet may contain the initial data as well.
The peer replies with a packet with the SYNCHRONIZE flag set. This packet may contain the initial response data as well.
{%- endtrans %}</p>
<p>{% trans -%}
The initiator may send additional data packets, up to the initial window size, before receiving the SYNCHRONIZE response.
These packets will also have the send Stream ID field set to 0.
Recipients must buffer packets received on unknown streams for a short period of time, as they may
arrive out of order, in advance of the SYNCHRONIZE packet.
{%- endtrans %}</p>
<h3>{% trans %}MTU Selection and Negotiation{% endtrans %}</h3>
<p>{% trans -%}
The maximum message size (also called the MTU / MRU) is negotiated to the lower value supported by
the two peers. As tunnel messages are padded to 1KB, a poor MTU selection will lead to
a large amount of overhead.
The MTU is specified by the option i2p.streaming.maxMessageSize.
The current default MTU of 1730 was chosen to fit precisely into two 1K I2NP tunnel messages,
including overhead for the typical case.
{%- endtrans %}</p>
<p>{% trans -%}
The first message in a connection includes a 387 byte (typical) Destination added by the streaming layer,
and usually a 898 byte (typical) LeaseSet, and Session keys, bundled in the Garlic message by the router.
(The LeaseSet and Session Keys will not be bundled if an ElGamal Session was previously established).
Therefore, the goal of fitting a complete HTTP request in a single 1KB I2NP message is not always attainable.
However, the selection of the MTU, together with careful implementation of fragmentation
and batching strategies in the tunnel gateway processor, are important factors in network bandwidth,
latency, reliability, and efficiency, especially for long-lived connections.
{%- endtrans %}</p>
<h3>{% trans %}Data Integrity{% endtrans %}</h3>
<p>{% trans i2cp=site_url('docs/protocol/i2cp') -%}
Data integrity is assured by the gzip CRC-32 checksum implemented in
<a href="{{ i2cp }}#format">the I2CP layer</a>.
There is no checksum field in the streaming protocol.
{%- endtrans %}</p>
<h3>{% trans %}Packet Encapsulation{% endtrans %}</h3>
<p>{% trans garlicrouting=site_url('docs/how/garlic-routing'), i2cp=site_url('docs/protocol/i2cp'),
i2np=site_url('docs/protocol/i2np'), tunnelmessage=site_url('docs/spec/tunnel-message') -%}
Each packet is sent through I2P as a single message (or as an individual clove in a
<a href="{{ garlicrouting }}">Garlic Message</a>). Message encapsulation is implemented
in the underlying <a href="{{ i2cp }}">I2CP</a>, <a href="{{ i2np }}">I2NP</a>, and
<a href="{{ tunnelmessage }}">tunnel message</a> layers. There is no packet delimiter
mechanism or payload length field in the streaming protocol.
{%- endtrans %}</p>
<h3>{% trans %}Windowing{% endtrans %}</h3>
<p>{% trans -%}
The streaming lib uses standard slow-start (exponential window growth) and congestion avoidance (linear window growth)
phases, with exponential backoff.
Windowing and acknowledgments use packet count, not byte count.
{%- endtrans %}</p>
<h3>{% trans %}Close{% endtrans %}</h3>
<p>{% trans -%}
Any packet, including one with the SYNCHRONIZE flag set, may have the CLOSE flag sent as well.
The connection is not closed until the peer responds with the CLOSE flag.
CLOSE packets may contain data as well.
{%- endtrans %}</p>
<h3 id="sharing">{% trans %}Control Block Sharing{% endtrans %}</h3>
<p>{% trans -%}
The streaming lib supports "TCP" Control Block sharing.
This shares three important streaming lib parameters
(window size, round trip time, round trip time variance)
across connections to the same remote peer.
This is used for "temporal" sharing at connection open/close time,
not "ensemble" sharing during a connection (See
<a href="http://www.ietf.org/rfc/rfc2140.txt">RFC 2140</a>).
There is a separate share per ConnectionManager (i.e. per local Destination)
so that there is no information leakage to other Destinations on the
same router.
The share data for a given peer expires after a few minutes.
The following Control Block Sharing parameters can be set per router:
{%- endtrans %}
<ul>
<li>RTT_DAMPENING = 0.75</li>
<li>RTTDEV_DAMPENING = 0.75</li>
<li>WINDOW_DAMPENING = 0.75</li>
</ul>
</p>
<h3 id="other">{% trans %}Other Parameters{% endtrans %}</h3>
<p>{% trans -%}
The following parameters are hardcoded, but may be of interest for analysis:
{%- endtrans %}</p>
<ul>
<li>MIN_RESEND_DELAY = 2*1000 (minimum RTO)
<li>MAX_RESEND_DELAY = 45*1000 (maximum RTO)
<li>MIN_WINDOW_SIZE = 1
<li>TREND_COUNT = 3
<li>MIN_MESSAGE_SIZE = 512 (minimum MTU)
<li>INBOUND_BUFFER_SIZE = maxMessageSize * (maxWindowSize + 2)
<li>INITIAL_TIMEOUT (valid only before RTT is sampled) = 9000
<li>"alpha" ( RTT dampening factor as per RFC 6298 ) = 0.125</li>
<li>"beta" ( RTTDEV dampening factor as per RFC 6298 ) = 0.25</li>
<li>"K" ( RTDEV multiplier as per RFC 6298 ) = 4</li>
<li>PASSIVE_FLUSH_DELAY = 250
<li>Maximum RTT estimate: 60*1000
</ul>
</p>
<h3>{% trans %}History{% endtrans %}</h3>
<p>{% trans -%}
The streaming library has grown organically for I2P - first mihi implemented the
"mini streaming library" as part of I2PTunnel, which was limited to a window
size of 1 message (requiring an ACK before sending the next one), and then it was
refactored out into a generic streaming interface (mirroring TCP sockets) and the
full streaming implementation was deployed with a sliding window protocol and
optimizations to take into account the high bandwidth x delay product. Individual
streams may adjust the maximum packet size and other options. The default
message size is selected to fit precisely in two 1K I2NP tunnel messages,
and is a reasonable tradeoff between the bandwidth costs of
retransmitting lost messages, and the latency and overhead of multiple messages.
{%- endtrans %}</p>
<h2 id="future">{% trans %}Future Work{% endtrans %}</h2>
<p>{% trans -%}
The behavior of the streaming library has a profound impact on
application-level performance, and as such, is an important
area for further analysis.
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
Additional tuning of the streaming lib parameters may be necessary.
{%- endtrans %}</li>
<li>{% trans ntcpdisc=site_url('docs/discussions/ntcp') -%}
Another area for research is the interaction of the streaming lib with the
NTCP and SSU transport layers.
See <a href="{{ ntcpdisc }}">the NTCP discussion page</a> for details.
{%- endtrans %}</li>
<li>{% trans -%}
The interaction of the routing algorithms with the streaming lib strongly affects performance.
In particular, random distribution of messages to multiple tunnels in a pool
leads to a high degree of out-of-order delivery which results in smaller window
sizes than would otherwise be the case. The router currently routes
messages for a single from/to destination pair through a consistent set
of tunnels, until tunnel expiration or delivery failure. The router's
failure and tunnel selection algorithms should be reviewed for possible
improvements.
{%- endtrans %}</li>
<li>{% trans -%}
The data in the first SYN packet may exceed the receiver's MTU.
{%- endtrans %}</li>
<li>{% trans -%}
The DELAY_REQUESTED field could be used more.
{%- endtrans %}</li>
<li>{% trans -%}
Duplicate initial SYNCHRONIZE packets on short-lived streams may not be recognized and removed.
{%- endtrans %}</li>
<li>{% trans -%}
Don't send the MTU in a retransmission.
{%- endtrans %}</li>
<li>{% trans -%}
Data is sent along unless the outbound window is full.
(i.e. no-Nagle or TCP_NODELAY)
Probably should have a configuration option for this.
{%- endtrans %}</li>
<li>{% trans -%}
zzz has added debug code to the streaming library to log packets in a wireshark-compatible
(pcap) format; Use this to further analyze performance.
The format may require enhancement to map more streaming lib parameters to TCP fields.
{%- endtrans %}</li>
<li>{% trans -%}
There are proposals to replace the streaming lib with standard TCP
(or perhaps a null layer together with raw sockets).
This would unfortunately be incompatible with the streaming lib
but it would be good to compare the performance of the two.
{%- endtrans %}</li>
</ul>
{% endblock %}

View File

@@ -0,0 +1,303 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Bittorrent over I2P{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}September 2012{% endtrans %}{% endblock %}
{% block accuratefor %}0.9.2{% endblock %}
{% block content %}
<p>{% trans -%}
There are several bittorrent clients and trackers on I2P.
As I2P addressing uses a Destination instead of an IP and port, minor
changes are required to tracker and client software for operation on I2P.
These changes are specified below.
Note carefully the guidelines for compatibility with older I2P clients and trackers.
{%- endtrans %}</p>
<p>{% trans -%}
This page specifies protocol details common to all clients and trackers.
Specific clients and trackers may implement other unique features or protocols.
{%- endtrans %}</p>
<p>{% trans -%}
We welcome additional ports of client and tracker software to I2P.
{%- endtrans %}</p>
<h2>{% trans %}Announces{% endtrans %}</h2>
<p>{% trans -%}
Clients generally include a fake port=6881 parameter in the announce, for compatibility with older trackers.
Trackers may ignore the port parameter, and should not require it.
{%- endtrans %}</p>
<p>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
The ip parameter is the base 64 of the client's
<a href="{{ commonstructures }}#struct_Destination">Destination</a>,
using the I2P Base 64 alphabet [A-Z][a-z][0-9]-~.
<a href="{{ commonstructures }}#struct_Destination">Destinations</a>
are 387+ bytes, so the Base 64 is 516+ bytes.
Clients generally append ".i2p" to the Base 64 Destination for compatibility with older trackers.
Trackers should not require an appended ".i2p".
{%- endtrans %}</p>
<p>{% trans -%}
Other parameters are the same as in standard bittorrent.
{%- endtrans %}</p>
<p>{% trans -%}
While all current Destinations for clients are exactly 387 bytes, a tracker should not
presume that will always be so. A reasonable maximum to assume, for now, is 475 bytes.
As the tracker must decode the Base64 to deliver compact responses (see below),
the tracker should probably decode and reject bad Base64 when announced.
{%- endtrans %}</p>
<p>{% trans -%}
The default response type is non-compact. Clients may request a compact response with
the parameter compact=1. A tracker may, but is not required to, return
a compact response when requested.
{%- endtrans %}</p>
<p>{% trans -%}
Developers of new I2P clients
are strongly encouraged to implemenent announces over their own tunnel rather than
the HTTP client proxy at port 4444. Doing so is both more efficient and it allows
destination enforcement by the tracker (see below).
{%- endtrans %}</p>
<p>{% trans -%}
There are no known I2P clients or trackers that currently support UDP announce/responses.
{%- endtrans %}</p>
<h2>{% trans %}Non-Compact Tracker Responses{% endtrans %}</h2>
<p>{% trans -%}
The non-compact response is just as in standard bittorrent, with an I2P "ip".
{%- endtrans %}</p>
<p>{% trans -%}
Trackers generally include a fake port key, or use the port from the announce, for compatibility with older clients.
Clients must ignore the port parameter, and should not require it.
{%- endtrans %}</p>
<p>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
The value of the ip key is the base 64 of the client's
<a href="{{ commonstructures }}#struct_Destination">Destination</a>, as described above.
Trackers generally append ".i2p" to the Base 64 Destination if it wasn't in the announce ip, for compatibility with older clients.
Clients should not require an appended ".i2p" in the responses.
{%- endtrans %}</p>
<p>{% trans -%}
Other response keys and values are the same as in standard bittorrent.
{%- endtrans %}</p>
<h2>{% trans %}Compact Tracker Responses{% endtrans %}</h2>
<p>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
In the compact response, the value of the "peers" dictionary key is a single byte string,
whose length is a multiple of 32 bytes.
This string contains the concatenated
<a href="{{ commonstructures }}#type_Hash">32-byte SHA-256 Hashes</a>
of the binary
<a href="{{ commonstructures }}#struct_Destination">Destinations</a>
of the peers.
This hash must be computed by the tracker, unless destination enforcement
(see below) is used, in which case the hash delivered in the X-I2P-DestHash
or X-I2P-DestB32 HTTP headers may be converted to binary and stored.
The peers key may be absent, or the peers value may be zero-length.
{%- endtrans %}</p>
<p>{% trans -%}
While compact response support is optional for both clients and trackers, it is highly
recommended as it reduces the nominal response size by over 90&#37;.
{%- endtrans %}</p>
<h2>{% trans %}Destination Enforcement{% endtrans %}</h2>
<p>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
Some, but not all, I2P bittorrent clients announce over their own tunnels.
Trackers may choose to prevent spoofing by requiring this, and verifying the
client's
<a href="{{ commonstructures }}#struct_Destination">Destination</a>
using HTTP headers added by the I2PTunnel HTTP Server tunnel.
The headers are X-I2P-DestHash, X-I2P-DestB64, and X-I2P-DestB32, which are
different formats for the same information.
These headers cannot be spoofed by the client.
A tracker enforcing destinations need not require the ip announce parameter at all.
{%- endtrans %}</p>
<p>{% trans -%}
As several clients use the HTTP proxy instead of their own tunnel for announces,
destination enforcement will prevent usage by those clients unless or until
those clients are converted to announcing over their own tunnel.
{%- endtrans %}</p>
<p>{% trans -%}
Unfortunately, as the network grows, so will the amount of maliciousness,
so we expect that all trackers will eventually enforce destinations.
Both tracker and client developers should anticipate it.
{%- endtrans %}</p>
<h2>{% trans %}Announce Host Names{% endtrans %}</h2>
<p>{% trans naming=site_url('docs/naming') -%}
Announce URL host names in torrent files generally follow the
<a href="{{ naming }}">I2P naming standards</a>.
In addition to host names from address books and ".b32.i2p" Base 32 hostnames,
the full Base 64 Destination (with [or without?] ".i2p" appended) should be supported.
Non-open trackers should recognize their own host name in any of these formats.
{%- endtrans %}</p>
<p>{% trans -%}
To preserve anonymity,
clients should generally ignore non-I2P announce URLs in torrent files.
{%- endtrans %}</p>
<h2>{% trans %}Client Connections{% endtrans %}</h2>
<p>{% trans -%}
Client-to-client connections use the standard protocol over TCP.
There are no known I2P clients that currently support uTP communication.
{%- endtrans %}</p>
<p>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
I2P uses 387+ byte <a href="{{ commonstructures }}#struct_Destination">Destinations</a>
for addresses, as explained above.
{%- endtrans %}</p>
<p>{% trans -%}
If the client has only the hash of the destination (such as from a compact response or PEX), it must perform a lookup
by encoding it with Base 32, appending ".b32.i2p", and querying the Naming Service,
which will return the full Destination if available.
{%- endtrans %}</p>
<p>{% trans -%}
If the client has a peer's full Destination it received in a non-compact response, it should use it
directly in the connection setup.
Do not convert a Destination back to a Base 32 hash for lookup, this is quite inefficient.
{%- endtrans %}</p>
<h2>{% trans %}Cross-Network Prevention{% endtrans %}</h2>
<p>{% trans -%}
To preserve anonymity,
I2P bittorrent clients generally do not support non-I2P announces or peer connections.
I2P HTTP outproxies often block announces.
There are no known SOCKS outproxies supporting bittorrent traffic.
{%- endtrans %}</p>
<p>{% trans -%}
To prevent usage by non-I2P clients via an HTTP inproxy, I2P trackers often
block accesses or announces that contain an X-Forwarded-For HTTP header.
Trackers should reject standard network announces with IPv4 or IPv6 IPs, and not deliver them in responses.
{%- endtrans %}</p>
<h2>PEX</h2>
<p>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
I2P PEX is based on ut_pex.
As there does not appear to be a formal specification of ut_pex available,
it may be necessary to review the libtorrent source for assistance.
It is an extension message, identified as "i2p_pex" in
<a href="http://www.bittorrent.org/beps/bep_0010.html">the extension handshake</a>.
It contains a bencoded dictionary with up to 3 keys, "added", "added.f", and "dropped".
The added and dropped values are each a single byte string, whose length is a multiple of 32 bytes.
These byte strings are the concatenated SHA-256 Hashes of the binary
<a href="{{ commonstructures }}#struct_Destination">Destinations</a>
of the peers.
This is the same format as the peers dictionary value in the i2p compact response format specified above.
The added.f value, if present, is the same as in ut_pex.
{%- endtrans %}</p>
<h2>DHT</h2>
<p>{% trans -%}
DHT support is included in the i2psnark client as of version 0.9.2.
Preliminary differences from
<a href="http://www.bittorrent.org/beps/bep_0005.html">BEP 5</a>
are described below, and are subject to change.
Contact the I2P developers if you wish to develop a client supporting DHT.
{%- endtrans %}</p>
<p>{% trans -%}
Unlike standard DHT, I2P DHT does not use a bit in the options handshake, or the PORT message.
It is advertised with an extension message, identified as "i2p_dht" in
<a href="http://www.bittorrent.org/beps/bep_0010.html">the extension handshake</a>.
It contains a bencoded dictionary with two keys, "port" and "rport", both integers.
{%- endtrans %}</p>
<p>{% trans -%}
The UDP (datagram) port listed in the compact node info is used
to receive repliable (signed) datagrams.
This is used for queries, except for announces.
We call this the "query port".
This is the "port" value from the extension message.
Queries use I2CP protocol number 17.
{%- endtrans %}</p>
<p>{% trans -%}
In addition to that UDP port, we use a second datagram
port equal to the query port + 1. This is used to receive
unsigned (raw) datagrams for replies, errors, and announces.
This port provides increased efficiency since replies
contain tokens sent in the query, and need not be signed.
We call this the "response port".
This is the "rport" value from the extension message.
It must be 1 + the query port.
Responses and announces use I2CP protocol number 18.
{%- endtrans %}</p>
<p>{% trans -%}
Compact peer info is 32 bytes (32 byte SHA256 Hash)
instead of 4 byte IP + 2 byte port. There is no peer port.
In a response, the "values" key is a list of strings, each containing a single compact peer info.
{%- endtrans %}</p>
<p>{% trans -%}
Compact node info is 54 bytes (20 byte SHA1 Hash + 32 byte SHA256 Hash + 2 byte port)
instead of 20 byte SHA1 Hash + 4 byte IP + 2 byte port.
In a response, the "nodes" key is a
single byte string with concatenated compact node info.
{%- endtrans %}</p>
<p>{% trans -%}
Secure node ID requirement: To make various DHT attacks more difficult,
the first 4 bytes of the Node ID must match the first 4 bytes of the destination Hash,
and the next two bytes of the Node ID must match the next two bytes of the
destination hash exclusive-ORed with the port.
{%- endtrans %}</p>
<p>{% trans -%}
In a torrent file,
the trackerless torrent dictionary "nodes" key is TBD.
It could be a list of
32 byte binary strings (SHA256 Hashes) instead of a list of lists
containing a host string and a port integer.
Alternatives: A single byte string with concatenated hashes,
or a list of strings alone.
{%- endtrans %}</p>
<h2>{% trans %}Additional Information{% endtrans %}</h2>
<ul>
<li>{% trans zzz=i2pconv('zzz.i2p') -%}
I2P bittorrent standards are generally discussed on <a href="http://{{ zzz }}/">{{ zzz }}</a>.
{%- endtrans %}</li>
<li>{% trans zzz=i2pconv('zzz.i2p') -%}
A chart of current tracker software capabilities is <a href="http://{{ zzz }}/files/trackers.html">also available there</a>.
{%- endtrans %}</li>
<li>{% trans forum=i2pconv('forum.i2p') -%}
The
<a href="http://{{ forum }}/viewtopic.php?t=2068">I2P bittorrent FAQ</a>
{%- endtrans %}</li>
<li>{% trans zzz=i2pconv('zzz.i2p') -%}
<a href="http://{{ zzz }}/topics/812">DHT on I2P discussion</a>
{%- endtrans %}</li>
</ul>
{% endblock %}

View File

@@ -0,0 +1,732 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Supported Applications{% endtrans %}{% endblock %}
{% block content %}
<h1 class="title">{% trans %}Supported Applications{% endtrans %}</h1>
<div id="TOC">
<ul>
<li><a href="#blogging-and-forums">{% trans %}Blogging, Forums, and Wikis{% endtrans %}</a></li>
<li><a href="#decentralized-file-storage">{% trans %}Decentralized File Storage{% endtrans %}</a></li>
<li>
<a href="#development-tools">{% trans %}Development Tools{% endtrans %}</a>
<ul>
<li><a href="#version-control">{% trans %}Version control{% endtrans %}</a></li>
</ul>
</li>
<li><a href="#domain-naming">{% trans %}Domain Naming{% endtrans %}</a></li>
<li><a href="#email">{% trans %}Email{% endtrans %}</a></li>
<li>
<a href="#file-sharing">{% trans %}File Sharing{% endtrans %}</a>
<ul>
<li><a href="#bittorrent-clients">{% trans %}BitTorrent clients{% endtrans %}</a></li>
<li><a href="#bittorrent-trackers-and-indexers">{% trans %}BitTorrent trackers and indexers{% endtrans %}</a></li>
<li><a href="#ed2k">ED2K</a></li>
<li><a href="#gnutella">Gnutella</a></li>
</ul>
</li>
<li>
<a href="#network-administration">{% trans %}Network Administration{% endtrans %}</a>
<ul>
<li><a href="#general-purpose-socket-utilities">{% trans %}General-purpose socket utilities{% endtrans %}</a></li>
<li><a href="#sshscpsftp">SSH/SCP/SFTP</a></li>
</ul>
</li>
<li>
<a href="#real-time-chat">{% trans %}Real-time Chat{% endtrans %}</a>
<ul>
<li><a href="#instant-messaging-clients">{% trans %}Instant messaging clients{% endtrans %}</a></li>
<li><a href="#irc-clients">{% trans %}IRC clients{% endtrans %}</a></li>
<li><a href="#irc-servers">{% trans %}IRC servers{% endtrans %}</a></li>
</ul>
</li>
<li>
<a href="#web-browsing">{% trans %}Web Browsing{% endtrans %}</a>
<ul>
<li><a href="#anonymous-websites">{% trans %}Anonymous websites{% endtrans %}</a></li>
<li><a href="#proxy-software">{% trans %}Proxy software{% endtrans %}</a></li>
<li><a href="#inproxies">{% trans %}Inproxies{% endtrans %}</a></li>
<li><a href="#outproxies">{% trans %}Outproxies{% endtrans %}</a></li>
</ul>
</li>
<li>
<a href="#website-hosting">{% trans %}Website Hosting{% endtrans %}</a>
<ul>
<li><a href="#web-servers">{% trans %}Web servers{% endtrans %}</a></li>
</ul>
</li>
</ul>
</div>
<p>{% trans trac=i2pconv('trac.i2p2.i2p') -%}
This is intended to be a comprehensive listing of applications used with
I2P. If you know of something that's missing please submit a ticket on
<a href="http://{{ trac }}/report/1/">Trac</a>, and be sure to select the
“www” component in the submission form.
{%- endtrans %}</p>
<p>{% trans %}
Supported applications are tagged with one or more of the following:
{%- endtrans %}</p>
<dl>
<dt><em>{{ _('bundled') }}</em></dt>
<dd>
<p>{% trans -%}
<em>Bundled application</em> — I2P ships with a few officially
supported applications that let new users take immediate advantage of
some of I2P's more useful capabilities.
{%- endtrans %}</p>
</dd>
<dt><em>{{ _('plugin') }}</em></dt>
<dd>
<p>{% trans plugins=i2pconv('plugins.i2p') -%}
<em>Third-party plugin</em> — I2P's plugin system provides convenient
deployment of I2P-enabled applications and allows tighter integration
with the router. Plugins are [reviewed by the community](<a href=
"http://{{ plugins }}">http://{{ plugins }}</a>) to identify security and
anonymity issues.
{%- endtrans %}</p>
</dd>
</dl>
<dl>
<dt><em>{{ _('standalone') }}, {{ _('standalone/mod') }}</em></dt>
<dd>
<p>{% trans -%}
<em>Third-party standalone application</em> — Many standard network
applications only require careful setup and configuration to communicate
anonymously over I2P. These are tagged with <em>standalone</em>. Some
applications, tagged with <em>standalone/mod</em>, require patching to
function properly over I2P or to prevent inadvertent disclosure of
identifying information such as the user's hostname or external IP
address.
{%- endtrans %}</p>
</dd>
<dt><em>{{ _('service') }}</em></dt>
<dd>
<p>{% trans -%}
<em>Third-party essential network service</em> — Services which on
the I2P network are analogous to those provided on the public Internet
by hosting providers, ISPs, and Google: eepsite indexes and jump
services, search engines, email, DNS-style name services, hosting,
proxies, etc. These services focus on boosting the usefulness of the
network as a whole, and making network content more discoverable.
{%- endtrans %}</p>
</dd>
<dt><em>{{ _('unmaintained') }}</em></dt>
<dd>
<p>{% trans -%}
<em>Unmaintained</em> — This is used to tag plugins, applications,
and services which appear to be unmaintained and may be removed from
this listing in the future.
{%- endtrans %}</p>
</dd>
</dl>
<p><strong>{% trans threatmodel=site_url('docs/how/threat-model') -%}
Warning: Using an application, plugin, or service with I2P
doesn't automatically protect your anonymity. I2P is merely a set of tools
which can help you mitigate certain <a href="{{ threatmodel }}">identified
threats to anonymity</a>. We do not and cannot make any guarantees about the
safety of the applications, plugins, and services listed below. Most
applications and plugins must be properly configured, and some will need to
be patched — and even then your anonymity might not be assured. Similarly,
services could put your anonymity at risk, either by design or through
carelessness on their part or your own.
{%- endtrans %}</strong></p>
<p><strong>{% trans -%}
If you have doubts about the suitability of an application,
plugin, or service for use with I2P, you are urged to inquire about privacy
issues with its maintainers, to search its mailing lists and bug tracker if
one exists, and consult trusted, knowledgeable members of the I2P
community.
{%- endtrans %}</strong></p>
<p><strong>{% trans -%}
Take responsibility for your own anonymity and safety — always
seek expert advice, educate yourself, practice good judgment, be mindful of
disclosing personally identifying information, and don't take
shortcuts.
{%- endtrans %}</strong></p>
<h3 id="blogging-and-forums"><a href="#TOC">{% trans %}Blogging, Forums, and Wikis{% endtrans %}</a></h3>
<ul>
<!-- let's disable this for now, at least, since it's nearly impossible to
find configuration instructions; plus, there certainly isn't a plugin
available for this.
<li>
<p><a href="http://www.blojsom.com/blog/"><strong>Blojsom</strong></a> —
Lightweight blogging platform.
<sup><em>[{{ _('plugin') }},&nbsp;{{ _('standalone/mod') }}]</em></sup></p>
</li>
-->
<li>
<p><a href="https://github.com/trevorturk/eldorado/"><strong>El Dorado</strong></a>
{% trans %}Lightweight forum software.{% endtrans %}
<sup><em>[{{ _('standalone/mod') }}]</em></sup></p>
</li>
<li>
<p><a href="http://pebble.sourceforge.net/"><strong>Pebble</strong></a>
{% trans %}Another lightweight blogging platform.{% endtrans %}
<sup><em>[{{ _('plugin') }},&nbsp;{{ _('standalone/mod') }}]</em></sup></p>
</li>
<li>
<p><a href="https://www.phpbb.com/"><strong>phpBB</strong></a>
{% trans %}Most popular open source forum software.{% endtrans %}
<sup><em>[{{ _('standalone/mod') }}]</em></sup></p>
</li>
<li>
<p><a href="http://syndie.i2p2.de/"><strong>Syndie</strong></a>
{% trans %}Distributed forums software, originally developed by jrandom.{% endtrans %}
<sup><em>[{{ _('plugin') }},&nbsp;{{ _('standalone') }},&nbsp;{{ _('unmaintained') }}]</em></sup></p>
</li>
<li>
<p><a href="http://jamwiki.org"><strong>JAMWiki</strong></a>
{% trans plugins=i2pconv('plugins.i2p') -%}
A Java-based MediaWiki clone. No external database needed.
Plugin available <a href="http://{{ plugins }}/plugins/jamwiki">here</a>.
{%- endtrans %}
<sup><em>[{{ _('standalone') }},&nbsp;{{ _('plugin') }}]</em></sup></p>
</li>
</ul>
<h3 id="decentralized-file-storage"><a href="#TOC">{% trans %}Decentralized File Storage{% endtrans %}</a></h3>
<ul>
<li><a href="http://{{ i2pconv('killyourtv.i2p') }}/tahoe-lafs/"><strong>Tahoe-LAFS-I2P</strong></a>
{% trans stats=i2pconv('stats.i2p') -%}
Port of the <a href="http://tahoe-lafs.org/"><strong>Tahoe-LAFS</strong></a>
distributed file system to the I2P network. Controller plugin <a href=
"http://{{ stats }}/i2p/plugins/">here</a>.
{%- endtrans %}
<sup><em>[{{ _('plugin') }},&nbsp;{{ _('standalone') }}]</em></sup></li>
</ul>
<h3 id="development-tools"><a href="#TOC">{% trans %}Development Tools{% endtrans %}</a></h3>
<h4 id="version-control"><a href="#TOC">{% trans %}Version control{% endtrans %}</a></h4>
<ul>
<li>
<p><a href="http://git-scm.com/"><strong>Git</strong></a>
{% trans %}Most popular distributed version control system.{% endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></p>
</li>
<li>
<p><a href="http://www.monotone.ca/"><strong>Monotone</strong></a>
{% trans monotone=site_url('get-involved/guides/monotone') -%}
Another distributed version control system. Currently
<a href="{{ monotone }}">used in I2P development</a>.
{%- endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></p>
</li>
</ul>
<h3 id="domain-naming"><a href="#TOC">{% trans %}Domain Naming{% endtrans %}</a></h3>
<ul>
<li><a href="http://127.0.0.1:7657/susidns/"><strong>susidns</strong></a>
{% trans naming=site_url('docs/naming') -%}
Provides management of addressbooks, which are part of a simple,
user-controlled <a href="{{ naming }}">I2P naming system</a> somewhat
analogous to the Internet's Domain Name System (DNS). Addressbooks map
Base64 destinations to short, usually human-readable “domain” names ending
with a .i2p suffix which the I2P router's HTTP client can resolve back to
Base64 addresses. (<em>Note:</em> While Base64 destinations are globally
unique, addressbook “domain” names only resolve to unique destinations
locally.)
{%- endtrans %}
<sup><em>[{{ _('bundled') }}]</em></sup>
</li>
</ul>
<h3 id="email"><a href="#TOC">{% trans %}Email{% endtrans %}</a></h3>
<ul>
<li>
<p><a href="http://{{ i2pconv('i2pbote.i2p') }}/"><strong>I2P-Bote</strong></a>
{% trans -%}
Serverless peer-to-peer email application using a distributed hash table
(DHT) for secure mail storage.
{%- endtrans %}
<sup><em>[{{ _('plugin') }}]</em></sup></p>
</li>
<li>
<p><a href="http://{{ i2pconv('hq.postman.i2p') }}/"><strong>Postman's anonymous email service</strong></a>
{% trans -%}
Provides email service within the I2P network via @mail.i2p addresses,
and email gateway service between the I2P network and the public Internet
via @i2pmail.org addresses. One of the oldest continuous services on I2P.
{%- endtrans %}
<sup><em>[{{ _('service') }}]</em></sup></p>
</li>
<li>
<p><a href="http://127.0.0.1:7657/susimail/susimail"><strong>susimail</strong></a>
{% trans -%}
Simple web browser-based email interface. Configured to use Postman's
email service by default.
{%- endtrans %}
<sup><em>[{{ _('bundled') }}]</em></sup></p>
</li>
<li>
<p><strong>Sylpheed Claws, Thunderbird, other MUAs</strong>
{% trans reviews='http://'+i2pconv('hq.postman.i2p')+'/?page_id=9',
smtp='http://'+i2pconv('hq.postman.i2p')+'/?page_id=10',
pop3='http://'+i2pconv('hq.postman.i2p')+'/?page_id=11' -%}
Can be configured to use Postman's email service. See
<a href="{{ reviews}}">this comparison of MUAs</a>,
and configuration settings for
<a href="{{ smtp }}">SMTP</a> and <a href="{{ pop3 }}">POP3</a>.
{%- endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></p>
</li>
</ul>
<h3 id="file-sharing"><a href="#TOC">{% trans %}File Sharing{% endtrans %}</a></h3>
<h4 id="bittorrent-clients"><a href="#TOC">{% trans %}BitTorrent clients{% endtrans %}</a></h4>
<ul>
<li>
<p><a href="http://127.0.0.1:7657/i2psnark/"><strong>I2PSnark</strong></a>
{% trans %}I2P's integrated BitTorrent client.{% endtrans %}
<sup><em>[{{ _('bundled') }}]</em></sup></p>
</li>
<li>
<p><a href="http://{{ i2pconv('forum.i2p') }}/viewtopic.php?t=4532"><strong>I2PSnarkXL</strong></a>
{% trans %}Modified version of I2PSnark.{% endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></p>
</li>
<li>
<p><a href="http://{{ i2pconv('bob.i2p') }}/Robert.html"><strong>Robert</strong></a>
{% trans %}
A fork of rufus that uses the Basic Open Bridge (BOB) and has many
improvements, including using the latest wxwidgets and python. It also
supports use of seedless if installed for trackerless torrents and
magnet-link like fetching of torrents within I2P.
{% endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></p>
</li>
<li>
<p><a href="http://www.transmissionbt.com/"><strong>Transmission</strong></a>
{% trans -%}
Clean, full-featured cross-platform BitTorrent client with official
ports for several GUI toolkits.
{%- endtrans %}
<sup><em>[{{ _('standalone/mod') }}]</em></sup></p>
</li>
<li>
<p><a href="http://www.vuze.com/"><strong>Azureus/Vuze</strong></a>
{% trans %}Has a plugin providing I2P support.{% endtrans %}
<sup><em>[{{ _('standalone') }},&nbsp;{{ _('unmaintained') }}]</em></sup></p>
</li>
</ul>
<h4 id="bittorrent-trackers-and-indexers"><a href="#TOC">{% trans %}BitTorrent trackers and indexers{% endtrans %}</a></h4>
<p>{% trans zzz=i2pconv('zzz.i2p') -%}
For a detailed feature comparison of I2P-enabled trackers/indexers, see
<a href="http://{{ zzz }}/files/trackers.html">here</a>.
{%- endtrans %}</p>
<ul>
<li>
<p><a href="http://{{ i2pconv('echelon.i2p') }}/tracker/"><strong>Bytemonsoon</strong></a>
{% trans -%}
The code that powered one of the first major tracker/indexer sites on the
Internet. Patched for I2P.
{%- endtrans %}
<sup><em>[{{ _('standalone/mod') }}]</em></sup></p>
</li>
<li>
<p><a href="http://erdgeist.org/arts/software/opentracker/"><strong>opentracker</strong></a>
{% trans newdevs=site_url('get-involved/guides/new-developers') -%}
Lightweight tracker/indexer. I2P mod available in the i2p.opentracker
branch of the <a href="{{ newdevs }}">I2P Monotone repository</a>.
{%- endtrans %}
<sup><em>[{{ _('standalone/mod') }}]</em></sup></p>
</li>
<li>
<p><a href="http://{{ i2pconv('stats.i2p') }}/i2p/plugins/"><strong>zzzot</strong></a>
{% trans zzz=i2pconv('zzz.i2p') -%}
<a href="http://{{ zzz }}/">zzz's</a> Java-based open tracker. More info
<a href="http://{{ zzz }}/topics/598?page=1#p2085">here</a>.
{%- endtrans %}
<sup><em>[{{ _('plugin') }}]</em></sup></p>
</li>
</ul>
<h4 id="ed2k"><a href="#TOC">ED2K</a></h4>
<ul>
<li>
<a href="http://{{ i2pconv('forum.i2p') }}/viewtopic.php?t=2213"><strong>iMule</strong></a>
{% trans %}I2P port of the aMule ED2K client.{% endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></li>
</ul>
<h4 id="gnutella"><a href="#TOC">Gnutella</a></h4>
<ul>
<li>
<p><a href="http://{{ i2pconv('forum.i2p') }}/viewforum.php?f=25"><strong>I2Phex</strong></a>
{% trans stats=i2pconv('stats.i2p') -%}
Port of the <a href="http://www.phex.org/mambo/">Phex</a> Gnutella client. Website
for plugin version <a href="http://{{ stats }}/i2p/plugins/">here</a>.
{%- endtrans %}
<sup><em>[{{ _('plugin') }},&nbsp;{{ _('standalone') }}]</em></sup></p>
</li>
<li>
<p><a href="http://{{ i2pconv('forum.i2p') }}/viewtopic.php?p=9486#9486"><strong>jwebcache</strong></a>
{% trans stats=i2pconv('stats.i2p') -%}
Cache for Gnutella peers on I2P. Website for plugin version
<a href="http://{{ stats }}/i2p/plugins/">here</a>.
{%- endtrans %}
<sup><em>[{{ _('plugin') }},&nbsp;{{ _('standalone') }}]</em></sup></p>
</li>
</ul>
<h3 id="network-administration"><a href="#TOC">{% trans %}Network Administration{% endtrans %}</a></h3>
<h4 id="general-purpose-socket-utilities"><a href="#TOC">{% trans %}General-purpose socket utilities{% endtrans %}</a></h4>
<ul>
<li>
<p><a href="http://nc110.sourceforge.net/"><strong>netcat</strong></a>
{% trans -%}
Unix standard tool for socket relaying. Several clones, ports, and forks
have appeared over the years.
{%- endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></p>
</li>
<li>
<p><a href="http://www.dest-unreach.org/socat/"><strong>socat</strong></a>
{% trans %}Like netcat but more powerful.{% endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></p>
</li>
<li>
<p><a href="http://tsocks.sourceforge.net/"><strong>tsocks</strong></a>
{% trans %}Proxy providing simple, transparent SOCKS-ification of network applications.{% endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></p>
</li>
</ul>
<h4 id="sshscpsftp"><a href="#TOC">SSH/SCP/SFTP</a></h4>
<ul>
<li>
<p><a href="http://www.openssh.com/"><strong>OpenSSH</strong></a>
{% trans %}Most popular implementation of the Secure Shell (SSH) protocol and related tools.{% endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></p>
</li>
<li>
<p><a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/"><strong>PuTTY</strong></a>
{% trans %}Open source Secure Shell (SSH) client for Windows.{% endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></p>
</li>
</ul>
<h3 id="real-time-chat"><a href="#TOC">{% trans %}Real-time Chat{% endtrans %}</a></h3>
<h4 id="instant-messaging-clients"><a href="#TOC">{% trans %}Instant messaging clients{% endtrans %}</a></h4>
<ul>
<li>
<a href="http://{{ i2pconv('forum.i2p') }}/viewtopic.php?t=2474"><strong>I2P Messenger</strong></a>
{% trans %}IM client with multiple incarnations.{% endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup>
</li>
</ul>
<h4 id="irc-clients"><a href="#TOC">{% trans %}IRC clients{% endtrans %}</a></h4>
<p>{% trans -%}
Many IRC clients leak identifying information to servers or other
clients, so I2P's IRC and SOCKS IRC client tunnels filter certain inbound
and outbound messages to scrub data such as LAN IP addresses, external IP
addresses, local hostnames, and the name and version of the IRC client. Two
message types in particular, DCC and CTCP, can't be sufficiently anonymized
without changes to the protocols or to IRC client/server code, so they are
completely blocked, except for CTCP ACTION (the message emitted by the
<code>/me</code> command) which isn't inherently dangerous.
{%- endtrans %}</p>
<p>{% trans -%}
I2P's IRC filtering may not cover every possible leak — users should also
check if their client is sending their real name or local username. Packet
sniffers such as <a href="http://www.wireshark.org/">Wireshark</a> are
useful here. Eliminating remaining leaks may be as simple as changing the
client's default configuration. If that doesn't help, inform the I2P
developers; they may be able to solve it via additional filtering.
{%- endtrans %}</p>
<ul>
<li>
<p><a href="http://www.oldschoolirc.com/"><strong>jIRCii</strong></a>
{% trans stats=i2pconv('stats.i2p') -%}
Small Java-based IRC client. Plugin available <a href=
"http://{{ stats }}/i2p/plugins/">here</a>.
{%- endtrans %}
<sup><em>[{{ _('plugin') }},&nbsp;{{ _('standalone') }}]</em></sup></p>
</li>
<li>
<p><a href="http://xchat.org/"><strong>XChat</strong></a>
{% trans %}Cross-platform graphical IRC client.{% endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></p>
</li>
<li>
<p><a href="http://www.irssi.org/"><strong>irssi</strong></a>
{% trans %}Unixy terminal-based IRC client.{% endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></p>
</li>
<li>
<p><a href="http://www.weechat.org/"><strong>WeeChat</strong></a>
{% trans %}Another Unixy terminal-based IRC client.{% endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></p>
</li>
</ul>
<h4 id="irc-servers"><a href="#TOC">{% trans %}IRC servers{% endtrans %}</a></h4>
<ul>
<li>
<p><a href="http://ngircd.barton.de/index.php.en"><strong>ngIRCd</strong></a>
{% trans %}IRC server developed from scratch.{% endtrans %}
<sup><em>[{{ _('standalone/mod') }}]</em></sup></p>
</li>
<li>
<p><a href="http://www.unrealircd.com/"><strong>UnrealIRCd</strong></a>
{% trans %}Most popular IRC server.{% endtrans %}
<sup><em>[{{ _('standalone/mod') }}]</em></sup></p>
</li>
</ul>
<h3 id="web-browsing"><a href="#TOC">{% trans %}Web Browsing{% endtrans %}</a></h3>
<h4 id="anonymous-websites"><a href="#TOC">{% trans %}Anonymous websites{% endtrans %}</a></h4>
<ul>
<li>
<p><strong>Eepsites</strong>
{% trans -%}
Any website hosted anonymously on I2P, reachable through the I2P router's HTTP proxy.
{%- endtrans %}
<sup><em>[{{ _('service') }}]</em></sup></p>
</li>
<li>
<p><strong>Deepsites</strong>
{% trans -%}
Distributed anonymous websites hosted
using Tahoe-LAFS-I2P, currently only reachable with Tahoe-LAFS-I2P
clients or through the Tahoe-LAFS-I2P HTTP proxy.
{%- endtrans %}
<sup><em>[{{ _('service') }}]</em></sup></p>
</li>
<li>
<p><a href="http://{{ i2pconv('i2host.i2p') }}/"><strong>{{ i2pconv('i2host.i2p') }}</strong></a>
{% trans sponge=i2pconv('sponge.i2p') -%}
Website for <a href="http://{{ sponge }}/">sponge's</a> jump service.
Source code available.
{%- endtrans %}
<sup><em>[{{ _('service') }}]</em></sup></p>
</li>
<li>
<p><a href="http://{{ i2pconv('i2jump.i2p') }}/"><strong>{{ i2pconv('i2jump.i2p') }}</strong></a>
{% trans %}Another jump service.{% endtrans %}
<sup><em>[{{ _('service') }}]</em></sup></p>
</li>
<li>
<p><a href="http://{{ i2pconv('identiguy.i2p') }}/"><strong>{{ i2pconv('identiguy.i2p') }}</strong></a>
{% trans %}Dynamically updated eepsite index.{% endtrans %}
<sup><em>[{{ _('service') }}]</em></sup></p>
</li>
<li>
<p><a href="http://{{ i2pconv('stats.i2p') }}/"><strong>{{ i2pconv('stats.i2p') }}</strong></a>
{% trans zzz=i2pconv('zzz.i2p') %}Website for <a href="http://{{ zzz }}/">zzz's</a> jump service.{% endtrans %}
<sup><em>[{{ _('service') }}]</em></sup></p>
</li>
</ul>
<h4 id="proxy-software"><a href="#TOC">{% trans %}Proxy software{% endtrans %}</a></h4>
<ul>
<li>
<p><a href="http://www.pps.jussieu.fr/~jch/software/polipo/"><strong>Polipo</strong></a>
{% trans %}SOCKS-enabled caching web proxy with basic filtering capabilities.{% endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></p>
</li>
<li>
<p><a href="http://www.privoxy.org/"><strong>Privoxy</strong></a>
{% trans -%}
Privacy-focused non-caching web proxy with advanced filtering
capabilities. Excels at removing ads and other junk.
{%- endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></p>
</li>
<li>
<p><a href="http://www.squid-cache.org/"><strong>Squid</strong></a>
{% trans %}Venerable caching web proxy.{% endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></p>
</li>
</ul>
<h4 id="inproxies"><a href="#TOC">{% trans %}Inproxies{% endtrans %}</a></h4>
<p>{% trans -%}
Gateways allowing users on the public Internet to access eepsites.
{%- endtrans %}</p>
<ul>
<li>
<a href="http://i2p.to/"><strong>i2p.to</strong></a>
{% trans tino=i2pconv('tino.i2p') -%}
<a href="http://{{ tino }}/">tino's</a> inproxy on the public Internet.
{%- endtrans %}
<sup><em>[{{ _('service') }}]</em></sup>
</li>
<li>
<a href="http://i2p.us/"><strong>i2p.us</strong></a>
{% trans -%}
Another inproxy on the public Internet.
{%- endtrans %}
<sup><em>[{{ _('service') }}]</em></sup>
</li>
<li>
<a href="http://i2p.me/"><strong>i2p.me</strong></a>
{% trans -%}
Another inproxy on the public Internet.
{%- endtrans %}
<sup><em>[{{ _('service') }}]</em></sup>
</li>
</ul>
<h4 id="outproxies"><a href="#TOC">{% trans %}Outproxies{% endtrans %}</a></h4>
<p>{% trans -%}
Gateways allowing I2P users to access content hosted on the public Internet.
{%- endtrans %}</p>
<ul>
<li>
<strong>false.i2p</strong>
{% trans %}Publicly advertised outproxy running Squid, located in Germany.{% endtrans %}
<sup><em>[{{ _('service') }}]</em></sup>
</li>
</ul>
<h3 id="website-hosting"><a href="#TOC">{% trans %}Website Hosting{% endtrans %}</a></h3>
<ul>
<li>
<a href="http://jetty.codehaus.org/jetty/"><strong>Jetty</strong></a>
{% trans -%}
Lightweight web server and Java servlet container. I2P is tightly
integrated with a bundled copy of Jetty which by default is configured to
host the <a href="http://127.0.0.1:7658/">user's eepsite</a>. The bundled
Jetty also serves the I2P router console and web applications bundled with
I2P.
{%- endtrans %}
<sup><em>[{{ _('bundled') }},&nbsp;{{ _('standalone') }}]</em></sup></li>
</ul>
<h4 id="web-servers"><a href="#TOC">{% trans %}Web servers{% endtrans %}</a></h4>
<p>{% trans -%}
In addition to Jetty, any web server should function over I2P without
modification so long as it's HTTP-compliant. Some web servers known to
currently serve content on the I2P network are:
{%- endtrans %}</p>
<ul>
<li>
<p><a href="http://httpd.apache.org/"><strong>Apache HTTP Server</strong></a>
{% trans %}Most popular web server on the public WWW.{% endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></p>
</li>
<li>
<p><a href="http://tomcat.apache.org/"><strong>Apache Tomcat</strong></a>
{% trans %}Web server and Java servlet container. More features than Jetty.{% endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></p>
</li>
<li>
<p><a href="http://www.lighttpd.net/"><strong>lighttpd</strong></a>
{% trans %}Fast lightweight web server.{% endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></p>
</li>
<li>
<p><a href="http://nginx.org/"><strong>nginx</strong></a>
{% trans %}High-performance lightweight web server.{% endtrans %}
<sup><em>[{{ _('standalone') }}]</em></sup></p>
</li>
</ul>
<!-- vim: set noai nosi ft=html tw=79 et sw=4 ts=4 spell spelllang=en: -->
{% endblock %}

View File

@@ -0,0 +1,292 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Naming discussion{% endtrans %}{% endblock %}
{% block content %}
<p>{% trans naming=site_url('docs/naming') -%}
NOTE: The following is a discussion of the reasons behind the I2P naming system,
common arguments and possible alternatives.
See <a href="{{ naming }}">the naming page</a> for current documentation.
{%- endtrans %}</p>
<h2>{% trans %}Discarded alternatives{% endtrans %}</h2>
<p>{% trans -%}
Naming within I2P has been an oft-debated topic since the very beginning with
advocates across the spectrum of possibilities. However, given I2P's inherent
demand for secure communication and decentralized operation, the traditional
DNS-style naming system is clearly out, as are "majority rules" voting systems.
{%- endtrans %}</p>
<p>{% trans -%}
I2P does not promote the use of DNS-like services though, as the damage done
by hijacking a site can be tremendous - and insecure destinations have no
value. DNSsec itself still falls back on registrars and certificate authorities,
while with I2P, requests sent to a destination cannot be intercepted or the reply
spoofed, as they are encrypted to the destination's public keys, and a destination
itself is just a pair of public keys and a certificate. DNS-style systems on the
other hand allow any of the name servers on the lookup path to mount simple denial
of service and spoofing attacks. Adding on a certificate authenticating the
responses as signed by some centralized certificate authority would address many of
the hostile nameserver issues but would leave open replay attacks as well as
hostile certificate authority attacks.
{%- endtrans %}</p>
<p>{% trans -%}
Voting style naming is dangerous as well, especially given the effectiveness of
Sybil attacks in anonymous systems - the attacker can simply create an arbitrarily
high number of peers and "vote" with each to take over a given name. Proof-of-work
methods can be used to make identity non-free, but as the network grows the load
required to contact everyone to conduct online voting is implausible, or if the
full network is not queried, different sets of answers may be reachable.
{%- endtrans %}</p>
<p>{% trans -%}
As with the Internet however, I2P is keeping the design and operation of a
naming system out of the (IP-like) communication layer. The bundled naming library
includes a simple service provider interface which <a href="#alternatives">alternate naming systems</a> can
plug into, allowing end users to drive what sort of naming tradeoffs they prefer.
{%- endtrans %}</p>
<h2>Discussion</h2>
<p>{% trans -%}
See also <a href="https://zooko.com/distnames.html">Names: Decentralized, Secure, Human-Meaningful: Choose Two</a>.
{%- endtrans %}</p>
<h3>Comments by jrandom</h3>
<p>{% trans -%}
(adapted from a post in the old Syndie, November 26, 2005)
{%- endtrans %}</p>
<p>{% trans -%}
Q:
What to do if some hosts
do not agree on one address and if some addresses are working, others are not?
Who is the right source of a name?
{%- endtrans %}</p>
<p>{% trans -%}
A:
You don't. This is actually a critical difference between names on I2P and how
DNS works - names in I2P are human readable, secure, but <b>not globally
unique</b>. This is by design, and an inherent part of our need for security.
{%- endtrans %}</p>
<p>{% trans -%}
If I could somehow convince you to change the destination associated with some
name, I'd successfully "take over" the site, and under no circumstances is that
acceptable. Instead, what we do is make names <b>locally unique</b>: they are
what <i>you</i> use to call a site, just as how you can call things whatever
you want when you add them to your browser's bookmarks, or your IM client's
buddy list. Who you call "Boss" may be who someone else calls "Sally".
{%- endtrans %}</p>
<p>{% trans -%}
Names will not, ever, be securely human readable and globally unique.
{%- endtrans %}</p>
<h3>Comments by zzz</h3>
<p>{% trans -%}
The following from zzz is a review of several common
complaints about I2P's naming system.
{%- endtrans %}</p>
<ul>
<li>
<p>{% trans -%}
<b>Inefficiency:</b>
The whole hosts.txt is downloaded (if it has changed, since eepget uses the etag and last-modified headers).
It's about 400K right now for almost 800 hosts.
{%- endtrans %}</p>
<p>{% trans -%}
True, but this isn't a lot of traffic in the context of i2p, which is itself wildly inefficient
(floodfill databases, huge encryption overhead and padding, garlic routing, etc.).
If you downloaded a hosts.txt file from someone every 12 hours it averages out to about 10 bytes/sec.
{%- endtrans %}</p>
<p>{% trans -%}
As is usually the case in i2p, there is a fundamental tradeoff here between anonymity and efficiency.
Some would say that using the etag and last-modified headers is hazardous because it exposes when you
last requested the data.
Others have suggested asking for specific keys only (similar to what jump services do, but
in a more automated fashion), possibly at a further cost in anonymity.
{%- endtrans %}</p>
<p>{% trans i2host=i2pconv('i2host.i2p') -%}
Possible improvements would be a replacement or supplement to addressbook (see <a href="http://{{ i2host }}/">{{ i2host }}p</a>),
or something simple like subscribing to http://example.i2p/cgi-bin/recenthosts.cgi rather than http://example.i2p/hosts.txt.
If a hypothetical recenthosts.cgi distributed all hosts from the last 24 hours, for example,
that could be both more efficient and more anonymous than the current hosts.txt with last-modified and etag.
{%- endtrans %}</p>
<p>{% trans url='http://'+i2pconv('stats.i2p')+'/cgi-bin/newhosts.txt' -%}
A sample implementation is on stats.i2p at
<a href="{{ url }}">{{ url }}</a>.
This script returns an Etag with a timestamp.
When a request comes in with the If-None-Match etag,
the script ONLY returns new hosts since that timestamp, or 304 Not Modified if there are none.
In this way, the script efficiently returns only the hosts the subscriber
does not know about, in an addressbook-compatible manner.
{%- endtrans %}</p>
<p>{% trans -%}
So the inefficiency is not a big issue and there are several ways to improve things without
radical change.
{%- endtrans %}</p>
<li>
<p>{% trans -%}
<b>Not Scalable:</b>
The 400K hosts.txt (with linear search) isn't that big at the moment and
we can probably grow by 10x or 100x before it's a problem.
{%- endtrans %}</p>
<p>{% trans -%}
As far as network traffic see above.
But unless you're going to do a slow real-time query over the network for
a key, you need to have the whole set of keys stored locally, at a cost of about 500 bytes per key.
{%- endtrans %}</p>
<li>
<p>{% trans -%}
<b>Requires configuration and "trust":</b>
Out-of-the-box addressbook is only subscribed to http://www.i2p2.i2p/hosts.txt, which is rarely updated,
leading to poor new-user experience.
{%- endtrans %}</p>
<p>{% trans -%}
This is very much intentional. jrandom wants a user to "trust" a hosts.txt
provider, and as he likes to say, "trust is not a boolean".
The configuration step attempts to force users to think about issues of trust in an anonymous network.
{%- endtrans %}</p>
<p>{% trans -%}
As another example, the "Eepsite Unknown" error page in the HTTP Proxy
lists some jump services, but doesn't "recommend" any one in particular,
and it's up to the user to pick one (or not).
jrandom would say we trust the listed providers enough to list them but not enough to
automatically go fetch the key from them.
{%- endtrans %}</p>
<p>{% trans -%}
How successful this is, I'm not sure.
But there must be some sort of hierarchy of trust for the naming system.
To treat everyone equally may increase the risk of hijacking.
{%- endtrans %}</p>
<li>
<p>{% trans -%}
<b>It isn't DNS</b>
{%- endtrans %}</p>
<p>{% trans -%}
Unfortunately real-time lookups over i2p would significantly slow down web browsing.
{%- endtrans %}</p>
<p>{% trans -%}
Also, DNS is based on lookups with limited caching and time-to-live, while i2p
keys are permanent.
{%- endtrans %}</p>
<p>{% trans -%}
Sure, we could make it work, but why? It's a bad fit.
{%- endtrans %}</p>
<li>
<p>{% trans -%}
<b>Not reliable:</b>
It depends on specific servers for addressbook subscriptions.
{%- endtrans %}</p>
<p>{% trans -%}
Yes it depends on a few servers that you have configured.
Within i2p, servers and services come and go.
Any other centralized system (for example DNS root servers) would
have the same problem. A completely decentralized system (everybody is authoritative)
is possible by implementing an "everybody is a root DNS server" solution, or by
something even simpler, like a script that adds everybody in your hosts.txt to your addressbook.
{%- endtrans %}</p>
<p>{% trans -%}
People advocating all-authoritative solutions generally haven't thought through
the issues of conflicts and hijacking, however.
{%- endtrans %}</p>
<li>
<p>{% trans -%}
<b>Awkward, not real-time:</b>
It's a patchwork of hosts.txt providers, key-add web form providers, jump service providers,
eepsite status reporters.
Jump servers and subscriptions are a pain, it should just work like DNS.
{%- endtrans %}</p>
<p>{% trans -%}
See the reliability and trust sections.
{%- endtrans %}</p>
</li>
</ul>
<p>{% trans -%}
So, in summary, the current system is not horribly broken, inefficient, or un-scalable,
and proposals to "just use DNS" aren't well thought-through.
{%- endtrans %}</p>
<h2 id="alternatives">{% trans %}Alternatives{% endtrans %}</h2>
<p>{% trans -%}
The I2P source contains several pluggable naming systems and supports configuration options
to enable experimentation with naming systems.
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
<b>Meta</b> - calls two or more other naming systems in order.
By default, calls PetName then HostsTxt.
{%- endtrans %}</li>
<li>{% trans -%}
<b>PetName</b> - Looks up in a petnames.txt file.
The format for this file is NOT the same as hosts.txt.
{%- endtrans %}</li>
<li>{% trans -%}
<b>HostsTxt</b> - Looks up in the following files, in order:
{%- endtrans %}</li>
<ol>
<li>privatehosts.txt
<li>userhosts.txt
<li>hosts.txt
</ol>
<li>{% trans -%}
<b>AddressDB</b> - Each host is listed in a separate file in a addressDb/ directory.
{%- endtrans %}</li>
<li>{% trans -%}
<b>Eepget</b> - does an HTTP lookup request from an external
server - must be stacked after the HostsTxt lookup with Meta.
This could augment or replace the jump system.
Includes in-memory caching.
{%- endtrans %}</li>
<li>{% trans -%}
<b>Exec</b> - calls an external program for lookup, allows
additional experimentation in lookup schemes, independent of java.
Can be used after HostsTxt or as the sole naming system.
Includes in-memory caching.
{%- endtrans %}</li>
<li>{% trans -%}
<b>Dummy</b> - used as a fallback for Base64 names, otherwise fails.
{%- endtrans %}</li>
</ul>
<p>{% trans -%}
The current naming system can be changed with the advanced config option 'i2p.naming.impl'
(restart required).
See core/java/src/net/i2p/client/naming for details.
{%- endtrans %}</p>
<p>{% trans -%}
Any new system should be stacked with HostsTxt, or should
implement local storage and/or the addressbook subscription functions, since addressbook
only knows about the hosts.txt files and format.
{%- endtrans %}</p>
<h2 id="certificates">{% trans %}Certificates{% endtrans %}</h2>
<p>{% trans -%}
I2P destinations contain a certificate, however at the moment that certificate
is always null.
With a null certificate, base64 destinations are always 516 bytes ending in "AAAA",
and this is checked in the addressbook merge mechanism, and possibly other places.
Also, there is no method available to generate a certificate or add it to a
destination. So these will have to be updated to implement certificates.
{%- endtrans %}</p>
<p>{% trans todo=site_url('get-involved/todo') -%}
One possible use of certificates is for <a href="{{ todo }}#hashcash">proof of work</a>.
{%- endtrans %}</p>
<p>{% trans -%}
Another is for "subdomains" (in quotes because there is really no such thing,
i2p uses a flat naming system) to be signed by the 2nd level domain's keys.
{%- endtrans %}</p>
<p>{% trans -%}
With any certificate implementation must come the method for verifying the
certificates.
Presumably this would happen in the addressbook merge code.
Is there a method for multiple types of certificates, or multiple certificates?
{%- endtrans %}</p>
<p>{% trans -%}
Adding on a certificate authenticating the
responses as signed by some centralized certificate authority would address many of
the hostile nameserver issues but would leave open replay attacks as well as
hostile certificate authority attacks.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,428 @@
{% extends "global/layout.html" %}
{% block title %}Network Database Discussion{% endblock %}
{% block content %}
<p>
NOTE: The following is a discussion of the history of netdb implementation and is not current information.
See <a href="{{ site_url('docs/how/network-database') }}">the main netdb page</a> for current documentation</a>.
<h2><a name="status">History</a></h2>
<p>
The netDb is distributed with a simple technique called "floodfill".
Long ago, the netDb also used the Kademlia DHT as a fallback algorithm. However,
it did not work well in our application, and it was completely disabled
in release 0.6.1.20.
<p>
(Adapted from a post by jrandom in the old Syndie, Nov. 26, 2005)
<br />
The floodfill netDb is really just a simple and perhaps temporary measure,
using the simplest possible algorithm - send the data to a peer in the
floodfill netDb, wait 10 seconds, pick a random peer in the netDb and ask them
for the entry to be sent, verifying its proper insertion / distribution. If the
verification peer doesn't reply, or they don't have the entry, the sender
repeats the process. When the peer in the floodfill netDb receives a netDb
store from a peer not in the floodfill netDb, they send it to all of the peers
in the floodfill netDb.
</p><p>
At one point, the Kademlia
search/store functionality was still in place. The peers
considered the floodfill peers as always being 'closer' to every key than any
peer not participating in the netDb. We fell back on the Kademlia
netDb if the floodfill peers fail for some reason or another.
However, Kademlia was then disabled completely (see below).
<p>
More recently, Kademlia was partially reintroduced in late 2009, as a way
to limit the size of the netdb each floodfill router must store.
<h3>The Introduction of the Floodfill Algorithm</h3>
<p>
Floodfill was introduced in release 0.6.0.4, keeping Kademlia as a backup algorithm.
</p>
<p>
(Adapted from posts by jrandom in the old Syndie, Nov. 26, 2005)
<br />
As I've often said, I'm not particularly bound to any specific technology -
what matters to me is what will get results. While I've been working through
various netDb ideas over the last few years, the issues we've faced in the last
few weeks have brought some of them to a head. On the live net,
with the netDb redundancy factor set to 4 peers (meaning we keep sending an
entry to new peers until 4 of them confirm that they've got it) and the
per-peer timeout set to 4 times that peer's average reply time, we're
<b>still</b> getting an average of 40-60 peers sent to before 4 ACK the store.
That means sending 36-56 times as many messages as should go out, each using
tunnels and thereby crossing 2-4 links. Even further, that value is heavily
skewed, as the average number of peers sent to in a 'failed' store (meaning
less than 4 people ACKed the message after 60 seconds of sending messages out)
was in the 130-160 peers range.
</p><p>
This is insane, especially for a network with only perhaps 250 peers on it.
</p><p>
The simplest answer is to say "well, duh jrandom, it's broken. fix it", but
that doesn't quite get to the core of the issue. In line with another current
effort, it's likely that we have a substantial number of network issues due to
restricted routes - peers who cannot talk with some other peers, often due to
NAT or firewall issues. If, say, the K peers closest to a particular netDb
entry are behind a 'restricted route' such that the netDb store message could
reach them but some other peer's netDb lookup message could not, that entry
would be essentially unreachable. Following down those lines a bit further and
taking into consideration the fact that some restricted routes will be created
with hostile intent, its clear that we're going to have to look closer into a
long term netDb solution.
</p><p>
There are a few alternatives, but two worth mentioning in particular. The
first is to simply run the netDb as a Kademlia DHT using a subset of the full
network, where all of those peers are externally reachable. Peers who are not
participating in the netDb still query those peers but they don't receive
unsolicited netDb store or lookup messages. Participation in the netDb would
be both self-selecting and user-eliminating - routers would choose whether to
publish a flag in their routerInfo stating whether they want to participate
while each router chooses which peers it wants to treat as part of the netDb
(peers who publish that flag but who never give any useful data would be
ignored, essentially eliminating them from the netDb).
</p><p>
Another alternative is a blast from the past, going back to the DTSTTCPW
(Do The Simplest Thing That Could Possibly Work)
mentality - a floodfill netDb, but like the alternative above, using only a
subset of the full network. When a user wants to publish an entry into the
floodfill netDb, they simply send it to one of the participating routers, wait
for an ACK, and then 30 seconds later, query another random participant in the
floodfill netDb to verify that it was properly distributed. If it was, great,
and if it wasn't, just repeat the process. When a floodfill router receives a
netDb store, they ACK immediately and queue off the netDb store to all of its
known netDb peers. When a floodfill router receives a netDb lookup, if they
have the data, they reply with it, but if they don't, they reply with the
hashes for, say, 20 other peers in the floodfill netDb.
</p><p>
Looking at it from a network economics perspective, the floodfill netDb is
quite similar to the original broadcast netDb, except the cost for publishing
an entry is borne mostly by peers in the netDb, rather than by the publisher.
Fleshing this out a bit further and treating the netDb like a blackbox, we can
see the total bandwidth required by the netDb to be:<pre>
recvKBps = N * (L + 1) * (1 + F) * (1 + R) * S / T
</pre>where<pre>
N = number of routers in the entire network
L = average number of client destinations on each router
(+1 for the routerInfo)
F = tunnel failure percentage
R = tunnel rebuild period, as a fraction of the tunnel lifetime
S = average netDb entry size
T = tunnel lifetime
</pre>Plugging in a few values:<pre>
recvKBps = 1000 * (5 + 1) * (1 + 0.05) * (1 + 0.2) * 2KB / 10m
= 25.2KBps
</pre>That, in turn, scales linearly with N (at 100,000 peers, the netDb must
be able to handle netDb store messages totaling 2.5MBps, or, at 300 peers,
7.6KBps).
</p><p>
While the floodfill netDb would have each netDb participant receiving only a
small fraction of the client generated netDb stores directly, they would all
receive all entries eventually, so all of their links should be capable of
handling the full recvKBps. In turn, they'll all need to send
<tt>(recvKBps/sizeof(netDb)) * (sizeof(netDb)-1)</tt> to keep the other
peers in sync.
</p><p>
A floodfill netDb would not require either tunnel routing for netDb operation
or any special selection as to which entries it can answer 'safely', as the
basic assumption is that they are all storing everything. Oh, and with regards
to the netDb disk usage required, its still fairly trivial for any modern
machine, requiring around 11MB for every 1000 peers <tt>(N * (L + 1) *
S)</tt>.
</p><p>
The Kademlia netDb would cut down on these numbers, ideally bringing them to K
over M times their value, with K = the redundancy factor and M being the number
of routers in the netDb (e.g. 5/100, giving a recvKBps of 126KBps and 536MB at
100,000 routers). The downside of the Kademlia netDb though is the increased
complexity of safe operation in a hostile environment.
</p><p>
What I'm thinking about now is to simply implement and deploy a floodfill netDb
in our existing live network, letting peers who want to use it pick out other
peers who are flagged as members and query them instead of querying the
traditional Kademlia netDb peers. The bandwidth and disk requirements at this
stage are trivial enough (7.6KBps and 3MB disk space) and it will remove the
netDb entirely from the debugging plan - issues that remain to be addressed
will be caused by something unrelated to the netDb.
</p><p>
How would peers be chosen to publish that flag saying they are a part of the
floodfill netDb? At the beginning, it could be done manually as an advanced
config option (ignored if the router is not able to verify its external
reachability). If too many peers set that flag, how do the netDb participants
pick which ones to eject? Again, at the beginning it could be done manually as
an advanced config option (after dropping peers which are unreachable). How do
we avoid netDb partitioning? By having the routers verify that the netDb is
doing the flood fill properly by querying K random netDb peers. How do routers
not participating in the netDb discover new routers to tunnel through? Perhaps
this could be done by sending a particular netDb lookup so that the netDb
router would respond not with peers in the netDb, but with random peers outside
the netDb.
</p><p>
I2P's netDb is very different from traditional load bearing DHTs - it only
carries network metadata, not any actual payload, which is why even a netDb
using a floodfill algorithm will be able to sustain an arbitrary amount of
eepsite/IRC/bt/mail/syndie/etc data. We can even do some optimizations as I2P
grows to distribute that load a bit further (perhaps passing bloom filters
between the netDb participants to see what they need to share), but it seems we
can get by with a much simpler solution for now.
</p><p>
One fact may be worth digging
into - not all leaseSets need to be published in the netDb! In fact, most
don't need to be - only those for destinations which will be receiving
unsolicited messages (aka servers). This is because the garlic wrapped
messages sent from one destination to another already bundles the sender's
leaseSet so that any subsequent send/recv between those two destinations
(within a short period of time) work without any netDb activity.
</p><p>
So, back at those equations, we can change L from 5 to something like 0.1
(assuming only 1 out of every 50 destinations is a server). The previous
equations also brushed over the network load required to answer queries from
clients, but while that is highly variable (based on the user activity), it's
also very likely to be quite insignificant as compared to the publishing
frequency.
</p><p>
Anyway, still no magic, but a nice reduction of nearly 1/5th the bandwidth/disk
space required (perhaps more later, depending upon whether the routerInfo
distribution goes directly as part of the peer establishment or only through
the netDb).
</p>
<h3>The Disabling of the Kademlia Algorithm</h3>
<p>
Kademlia was completely disabled in release 0.6.1.20.
</p><p>
(this is adapted from an IRC conversation with jrandom 11/07)
<br />
Kademlia requires a minimum level of service that the baseline could not offer (bandwidth, cpu),
even after adding in tiers (pure kad is absurd on that point).
Kademlia just wouldn't work. It was a nice idea, but not for a hostile and fluid environment.
</p>
<h3>Current Status</h3>
<p>The netDb plays a very specific role in the I2P network, and the algorithms
have been tuned towards our needs. This also means that it hasn't been tuned
to address the needs we have yet to run into. I2P is currently
fairly small (a few hundred routers).
There were some calculations that 3-5 floodfill routers should be able to handle
10,000 nodes in the network.
The netDb implementation more than adequately meets our
needs at the moment, but there will likely be further tuning and bugfixing as
the network grows.</p>
<h3>Update of Calculations 03-2008</h3>
<p>Current numbers:
<pre>
recvKBps = N * (L + 1) * (1 + F) * (1 + R) * S / T
</pre>where<pre>
N = number of routers in the entire network
L = average number of client destinations on each router
(+1 for the routerInfo)
F = tunnel failure percentage
R = tunnel rebuild period, as a fraction of the tunnel lifetime
S = average netDb entry size
T = tunnel lifetime
</pre>
Changes in assumptions:
<ul>
<li>L is now about .5, compared to .1 above, due to the popularity of i2psnark
and other apps.
<li>F is about .33, but bugs in tunnel testing are fixed in 0.6.1.33, so it will get much better.
<li>Since netDb is about 2/3 5K routerInfos and 1/3 2K leaseSets, S = 4K.
RouterInfo size is shrinking in 0.6.1.32 and 0.6.1.33 as we remove unnecessary stats.
<li>R = tunnel build period: 0.2 was a very low - it was maybe 0.7 -
but build algorithm improvements in 0.6.1.32 should bring it down to about 0.2
as the network upgrades. Call it 0.5 now with half the network at .30 or earlier.
</ul>
<pre> recvKBps = 700 * (0.5 + 1) * (1 + 0.33) * (1 + 0.5) * 4KB / 10m
~= 28KBps
</pre>
This just accounts for the stores - what about the queries?
<h3>The Return of the Kademlia Algorithm?</h3>
<p>
(this is adapted from <a href="{{ get_url('meetings_show', id=195) }}">the I2P meeting Jan. 2, 2007</a>)
<br />
The Kademlia netDb just wasn't working properly.
Is it dead forever or will it be coming back?
If it comes back, the peers in the Kademlia netDb would be a very limited subset
of the routers in the network (basically an expanded number of floodfill peers, if/when the floodfill peers
cannot handle the load).
But until the floodfill peers cannot handle the load (and other peers cannot be added that can), it's unnecessary.
</p>
<h3>The Future of Floodfill</h3>
<p>
(this is adapted from an IRC conversation with jrandom 11/07)
<br />
Here's a proposal: Capacity class O is automatically floodfill.
Hmm.
Unless we're sure, we might end up with a fancy way of DDoS'ing all O class routers.
This is quite the case: we want to make sure the number of floodfill is as small as possible while providing sufficient reachability.
If/when netDb requests fail, then we need to increase the number of floodfill peers, but atm, I'm not aware of a netDb fetch problem.
There are 33 "O" class peers according to my records.
33 is a /lot/ to floodfill to.
</p><p>
So floodfill works best when the number of peers in that pool is firmly limited?
And the size of the floodfill pool shouldn't grow much, even if the network itself gradually would?
3-5 floodfill peers can handle 10K routers iirc (I posted a bunch of numbers on that explaining the details in the old syndie).
Sounds like a difficult requirement to fill with automatic opt-in,
especially if nodes opting in cannot trust data from others.
e.g. "let's see if I'm among the top 5",
and can only trust data about themselves (e.g. "I am definitely O class, and moving 150 KB/s, and up for 123 days").
And top 5 is hostile as well. Basically, it's the same as the tor directory servers - chosen by trusted people (aka devs).
Yeah, right now it could be exploited by opt-in, but that'd be trivial to detect and deal with.
Seems like in the end, we might need something more useful than Kademlia, and have only reasonably capable peers join that scheme.
N class and above should be a big enough quantity to suppress risk of an adversary causing denial of service, I'd hope.
But it would have to be different from floodfill then, in the sense that it wouldn't cause humongous traffic.
Large quantity? For a DHT based netDb?
Not necessarily DHT-based.
</p>
<h3 id="todo">Floodfill TODO List</h3>
<p>
NOTE: The following is not current information.
See <a href="{{ site_url('docs/how/network-database') }}">the main netdb page</a> for the current status and a list of future work</a>.
<p>
The network was down to only one floodfill for a couple of hours on March 13, 2008
(approx. 18:00 - 20:00 UTC),
and it caused a lot of trouble.
<p>
Two changes implemented in 0.6.1.33 should reduce the disruption caused
by floodfill peer removal or churn:
<ol>
<li>Randomize the floodfill peers used for search each time.
This will get you past the failing ones eventually.
This change also fixed a nasty bug that would sometimes drive the ff search code insane.
<li>Prefer the floodfill peers that are up.
The code now avoids peers that are shitlisted, failing, or not heard from in
half an hour, if possible.
</ol>
<p>
One benefit is faster first contact to an eepsite (i.e. when you had to fetch
the leaseset first). The lookup timeout is 10s, so if you don't start out by
asking a peer that is down, you can save 10s.
<p>
There <i>may</i> be anonymity implications in these changes.
For example, in the floodfill <b>store</b> code, there are comments that
shitlisted peers are not avoided, since a peer could be "shitty" and then
see what happens.
Searches are much less vulnerable than stores -
they're much less frequent, and give less away.
So maybe we don't think we need to worry about it?
But if we want to tweak the changes, it would be easy to
send to a peer listed as "down" or shitlisted anyway, just not
count it as part of the 2 we are sending to
(since we don't really expect a reply).
<p>
There are several places where a floodfill peer is selected - this fix addresses only one -
who a regular peer searches from [2 at a time].
Other places where better floodfill selection should be implemented:
<ol>
<li>Who a regular peer stores to [1 at a time]
(random - need to add qualification, because timeouts are long)
<li>Who a regular peer searches to verify a store [1 at a time]
(random - need to add qualification, because timeouts are long)
<li>Who a ff peer sends in reply to a failed search (3 closest to the search)
<li>Who a ff peer floods to (all other ff peers)
<li>The list of ff peers sent in the NTCP every-6-hour "whisper"
(although this may not longer be necessary due to other ff improvements)
</ol>
<p>
Lots more that could and should be done -
<ul>
<li>
Use the "dbHistory" stats to better rate a floodfill peer's integration
<li>
Use the "dbHistory" stats to immediately react to floodfill peers that don't respond
<li>
Be smarter on retries - retries are handled by an upper layer, not in
FloodOnlySearchJob, so it does another random sort and tries again,
rather than purposefully skipping the ff peers we just tried.
<li>
Improve integration stats more
<li>
Actually use integration stats rather than just floodfill indication in netDb
<li>
Use latency stats too?
<li>
More improvement on recognizing failing floodfill peers
</ul>
<p>
Recently completed -
<ul>
<li>
[In Release 0.6.3]
Implement automatic opt-in
to floodfill for some percentage of class O peers, based on analysis of the network.
<li>
[In Release 0.6.3]
Continue to reduce netDb entry size to reduce floodfill traffic -
we are now at the minimum number of stats required to monitor the network.
<li>
[In Release 0.6.3]
Manual list of floodfill peers to exclude?
(<a href="{{ site_url('docs/how/threat-model') }}#blocklist">blocklists</a> by router ident)
<li>
[In Release 0.6.3]
Better floodfill peer selection for stores:
Avoid peers whose netDb is old, or have a recent failed store,
or are forever-shitlisted.
<li>
[In Release 0.6.4]
Prefer already-connected floodfill peers for RouterInfo stores, to
reduce number of direct connections to floodfill peers.
<li>
[In Release 0.6.5]
Peers who are no longer floodfill send their routerInfo in response
to a query, so that the router doing the query will know he
is no longer floodfill.
<li>
[In Release 0.6.5]
Further tuning of the requirements to automatically become floodfill
<li>
[In Release 0.6.5]
Fix response time profiling in preparation for favoring fast floodfills
<li>
[In Release 0.6.5]
Improve blocklisting
<li>
[In Release 0.7]
Fix netDb exploration
<li>
[In Release 0.7]
Turn blocklisting on by default, block the known troublemakers
<li>
[Several improvements in recent releases, a continuing effort]
Reduce the resource demands on high-bandwidth and floodfill routers
</ul>
<p>
That's a long list but it will take that much work to
have a network that's resistant to DOS from lots of peers turning the floodfill switch on and off.
Or pretending to be a floodfill router.
None of this was a problem when we had only two ff routers, and they were both up
24/7. Again, jrandom's absence has pointed us to places that need improvement.
</p><p>
To assist in this effort, additional profile data for floodfill peers are
now (as of release 0.6.1.33) displayed on the "Profiles" page in
the router console.
We will use this to analyze which data are appropriate for
rating floodfill peers.
</p>
<p>
The network is currently quite resilient, however
we will continue to enhance our algorithms for measuring and reacting to the performance and reliability
of floodfill peers. While we are not, at the moment, fully hardened to the potential threats of
malicious floodfills or a floodfill DDOS, most of the infrastructure is in place,
and we are well-positioned to react quickly
should the need arise.
</p>
{% endblock %}

View File

@@ -0,0 +1,559 @@
{% extends "global/layout.html" %}
{% block title %}NTCP Discussion{% endblock %}
{% block content %}
Following is a discussion about NTCP that took place in March 2007.
It has not been updated to reflect current implementation.
For the current NTCP specification see <a href="{{ site_url('docs/transport/ntcp') }}">the main NTCP page</a>.
<h2>NTCP vs. SSU Discussion, March 2007</h2>
<h3>NTCP questions</h3>
(adapted from an IRC discussion between zzz and cervantes)
<br />
Why is NTCP preferred over SSU, doesn't NTCP have higher overhead and latency?
It has better reliability.
<br />
Doesn't streaming lib over NTCP suffer from classic TCP-over-TCP issues?
What if we had a really simple UDP transport for streaming-lib-originated traffic?
I think SSU was meant to be the so-called really simple UDP transport - but it just proved too unreliable.
<h3>"NTCP Considered Harmful" Analysis by zzz</h3>
Posted to new Syndie, 2007-03-25.
This was posted to stimulate discussion, don't take it too seriously.
<p>
Summary: NTCP has higher latency and overhead than SSU, and is more likely to
collapse when used with the streaming lib. However, traffic is routed with a
preference for NTCP over SSU and this is currently hardcoded.
</p>
<h4>Discussion</h4>
<p>
We currently have two transports, NTCP and SSU. As currently implemented, NTCP
has lower "bids" than SSU so it is preferred, except for the case where there
is an established SSU connection but no established NTCP connection for a peer.
</p><p>
SSU is similar to NTCP in that it implements acknowledgments, timeouts, and
retransmissions. However SSU is I2P code with tight constraints on the
timeouts and available statistics on round trip times, retransmissions, etc.
NTCP is based on Java NIO TCP, which is a black box and presumably implements
RFC standards, including very long maximum timeouts.
</p><p>
The majority of traffic within I2P is streaming-lib originated (HTTP, IRC,
Bittorrent) which is our implementation of TCP. As the lower-level transport is
generally NTCP due to the lower bids, the system is subject to the well-known
and dreaded problem of TCP-over-TCP
http://sites.inka.de/~W1011/devel/tcp-tcp.html , where both the higher and
lower layers of TCP are doing retransmissions at once, leading to collapse.
</p><p>
Unlike in the PPP over SSH scenario described in the link above, we have
several hops for the lower layer, each covered by a NTCP link. So each NTCP
latency is generally much less than the higher-layer streaming lib latency.
This lessens the chance of collapse.
</p><p>
Also, the probabilities of collapse are lessened when the lower-layer TCP is
tightly constrained with low timeouts and number of retransmissions compared to
the higher layer.
</p><p>
The .28 release increased the maximum streaming lib timeout from 10 sec to 45
sec which greatly improved things. The SSU max timeout is 3 sec. The NTCP max
timeout is presumably at least 60 sec, which is the RFC recommendation. There
is no way to change NTCP parameters or monitor performance. Collapse of the
NTCP layer is [editor: text lost]. Perhaps an external tool like tcpdump would help.
</p><p>
However, running .28, the i2psnark reported upstream does not generally stay at
a high level. It often goes down to 3-4 KBps before climbing back up. This is a
signal that there are still collapses.
</p><p>
SSU is also more efficient. NTCP has higher overhead and probably higher round
trip times. when using NTCP the ratio of (tunnel output) / (i2psnark data
output) is at least 3.5 : 1. Running an experiment where the code was modified
to prefer SSU (the config option i2np.udp.alwaysPreferred has no effect in the
current code), the ratio reduced to about 3 : 1, indicating better efficiency.
</p><p>
As reported by streaming lib stats, things were much improved - lifetime window
size up from 6.3 to 7.5, RTT down from 11.5s to 10s, sends per ack down from
1.11 to 1.07.
</p><p>
That this was quite effective was surprising, given that we were only changing
the transport for the first of 3 to 5 total hops the outbound messages would
take.
</p><p>
The effect on outbound i2psnark speeds wasn't clear due to normal variations.
Also for the experiment, inbound NTCP was disabled. The effect on inbound
speeds on i2psnark was not clear.
</p>
<h4>Proposals</h4>
<ul>
<li>
1A)
This is easy -
We should flip the bid priorities so that SSU is preferred for all traffic, if
we can do this without causing all sorts of other trouble. This will fix the
i2np.udp.alwaysPreferred configuration option so that it works (either as true
or false).
<li>
1B)
Alternative to 1A), not so easy -
If we can mark traffic without adversely affecting our anonymity goals, we
should identify streaming-lib generated traffic and have SSU generate a low bid
for that traffic. This tag will have to go with the message through each hop
so that the forwarding routers also honor the SSU preference.
<li>
2)
Bounding SSU even further (reducing maximum retransmissions from the current
10) is probably wise to reduce the chance of collapse.
<li>
3)
We need further study on the benefits vs. harm of a semi-reliable protocol
underneath the streaming lib. Are retransmissions over a single hop beneficial
and a big win or are they worse than useless?
We could do a new SUU (secure unreliable UDP) but probably not worth it. We
could perhaps add a no-ack-required message type in SSU if we don't want any
retransmissions at all of streaming-lib traffic. Are tightly bounded
retransmissions desirable?
<li>
4)
The priority sending code in .28 is only for NTCP. So far my testing hasn't
shown much use for SSU priority as the messages don't queue up long enough for
priorities to do any good. But more testing needed.
<li>
5)
The new streaming lib max timeout of 45s is probably still too low.
The TCP RFC says 60s. It probably shouldn't be shorter than the underlying NTCP max timeout (presumably 60s).
</ul>
<h3>Response by jrandom</h3>
Posted to new Syndie, 2007-03-27
<p>
On the whole, I'm open to experimenting with this, though remember why NTCP is
there in the first place - SSU failed in a congestion collapse. NTCP "just
works", and while 2-10&#37; retransmission rates can be handled in normal
single-hop networks, that gives us a 40&#37; retransmission rate with 2 hop
tunnels. If you loop in some of the measured SSU retransmission rates we saw
back before NTCP was implemented (10-30+&#37;), that gives us an 83&#37; retransmission
rate. Perhaps those rates were caused by the low 10 second timeout, but
increasing that much would bite us (remember, multiply by 5 and you've got half
the journey).
</p><p>
Unlike TCP, we have no feedback from the tunnel to know whether the message
made it - there are no tunnel level acks. We do have end to end ACKs, but only
on a small number of messages (whenever we distribute new session tags) - out
of the 1,553,591 client messages my router sent, we only attempted to ACK
145,207 of them. The others may have failed silently or succeeded perfectly.
</p><p>
I'm not convinced by the TCP-over-TCP argument for us, especially split across
the various paths we transfer down. Measurements on I2P can convince me
otherwise, of course.
</p><p>
<i>
The NTCP max timeout is presumably at least 60 sec, which is the RFC
recommendation. There is no way to change NTCP parameters or monitor
performance.
</i>
</p><p>
True, but net connections only get up to that level when something really bad
is going on - the retransmission timeout on TCP is often on the order of tens
or hundreds of milliseconds. As foofighter points out, they've got 20+ years
experience and bugfixing in their TCP stacks, plus a billion dollar industry
optimizing hardware and software to perform well according to whatever it is
they do.
</p><p>
<i>
NTCP has higher overhead and probably higher round trip times. when using NTCP
the ratio of (tunnel output) / (i2psnark data output) is at least 3.5 : 1.
Running an experiment where the code was modified to prefer SSU (the config
option i2np.udp.alwaysPreferred has no effect in the current code), the ratio
reduced to about 3 : 1, indicating better efficiency.
</i>
</p><p>
This is very interesting data, though more as a matter of router congestion
than bandwidth efficiency - you'd have to compare 3.5*$n*$NTCPRetransmissionPct
./. 3.0*$n*$SSURetransmissionPct. This data point suggests there's something in
the router that leads to excess local queuing of messages already being
transferred.
</p><p>
<i>
lifetime window size up from 6.3 to 7.5, RTT down from 11.5s to 10s, sends per
ACK down from 1.11 to 1.07.
</i>
</p><p>
Remember that the sends-per-ACK is only a sample not a full count (as we don't
try to ACK every send). Its not a random sample either, but instead samples
more heavily periods of inactivity or the initiation of a burst of activity -
sustained load won't require many ACKs.
</p><p>
Window sizes in that range are still woefully low to get the real benefit of
AIMD, and still too low to transmit a single 32KB BT chunk (increasing the
floor to 10 or 12 would cover that).
</p><p>
Still, the wsize stat looks promising - over how long was that maintained?
</p><p>
Actually, for testing purposes, you may want to look at
StreamSinkClient/StreamSinkServer or even TestSwarm in
apps/ministreaming/java/src/net/i2p/client/streaming/ - StreamSinkClient is a
CLI app that sends a selected file to a selected destination and
StreamSinkServer creates a destination and writes out any data sent to it
(displaying size and transfer time). TestSwarm combines the two - flooding
random data to whomever it connects to. That should give you the tools to
measure sustained throughput capacity over the streaming lib, as opposed to BT
choke/send.
</p><p>
<i>
1A)
This is easy -
We should flip the bid priorities so that SSU is preferred for all traffic, if
we can do this without causing all sorts of other trouble. This will fix the
i2np.udp.alwaysPreferred configuration option so that it works (either as true
or false).
</i>
</p><p>
Honoring i2np.udp.alwaysPreferred is a good idea in any case - please feel free
to commit that change. Lets gather a bit more data though before switching the
preferences, as NTCP was added to deal with an SSU-created congestion collapse.
</p><p>
<i>
1B)
Alternative to 1A), not so easy -
If we can mark traffic without adversely affecting our anonymity goals, we
should identify streaming-lib generated traffic
and have SSU generate a low bid for that traffic. This tag will have to go with
the message through each hop
so that the forwarding routers also honor the SSU preference.
</i>
</p><p>
In practice, there are three types of traffic - tunnel building/testing, netDb
query/response, and streaming lib traffic. The network has been designed to
make differentiating those three very hard.
</p><p>
<i>
2)
Bounding SSU even further (reducing maximum retransmissions from the current
10) is probably wise to reduce the chance of collapse.
</i>
</p><p>
At 10 retransmissions, we're up shit creek already, I agree. One, maybe two
retransmissions is reasonable, from a transport layer, but if the other side is
too congested to ACK in time (even with the implemented SACK/NACK capability),
there's not much we can do.
</p><p>
In my view, to really address the core issue we need to address why the router
gets so congested to ACK in time (which, from what I've found, is due to CPU
contention). Maybe we can juggle some things in the router's processing to make
the transmission of an already existing tunnel higher CPU priority than
decrypting a new tunnel request? Though we've got to be careful to avoid
starvation.
</p><p>
<i>
3)
We need further study on the benefits vs. harm of a semi-reliable protocol
underneath the streaming lib. Are retransmissions over a single hop beneficial
and a big win or are they worse than useless?
We could do a new SUU (secure unreliable UDP) but probably not worth it. We
could perhaps add a no-ACK-required message type in SSU if we don't want any
retransmissions at all of streaming-lib traffic. Are tightly bounded
retransmissions desirable?
</i>
</p><p>
Worth looking into - what if we just disabled SSU's retransmissions? It'd
probably lead to much higher streaming lib resend rates, but maybe not.
</p><p>
<i>
4)
The priority sending code in .28 is only for NTCP. So far my testing hasn't
shown much use for SSU priority as the messages don't queue up long enough for
priorities to do any good. But more testing needed.
</i>
</p><p>
There's UDPTransport.PRIORITY_LIMITS and UDPTransport.PRIORITY_WEIGHT (honored
by TimedWeightedPriorityMessageQueue), but currently the weights are almost all
equal, so there's no effect. That could be adjusted, of course (but as you
mention, if there's no queuing, it doesn't matter).
</p><p>
<i>
5)
The new streaming lib max timeout of 45s is probably still too low. The TCP RFC
says 60s. It probably shouldn't be shorter than the underlying NTCP max timeout
(presumably 60s).
</i>
</p><p>
That 45s is the max retransmission timeout of the streaming lib though, not the
stream timeout. TCP in practice has retransmission timeouts orders of magnitude
less, though yes, can get to 60s on links running through exposed wires or
satellite transmissions ;) If we increase the streaming lib retransmission
timeout to e.g. 75 seconds, we could go get a beer before a web page loads
(especially assuming less than a 98&#37; reliable transport). That's one reason we
prefer NTCP.
</p>
<h3>Response by zzz</h3>
Posted to new Syndie, 2007-03-31
<p>
<i>
At 10 retransmissions, we're up shit creek already, I agree. One, maybe two
retransmissions is reasonable, from a transport layer, but if the other side is
too congested to ACK in time (even with the implemented SACK/NACK capability),
there's not much we can do.
<br>
In my view, to really address the core issue we need to address why the
router gets so congested to ACK in time (which, from what I've found, is due to
CPU contention). Maybe we can juggle some things in the router's processing to
make the transmission of an already existing tunnel higher CPU priority than
decrypting a new tunnel request? Though we've got to be careful to avoid
starvation.
</i>
</p><p>
One of my main stats-gathering techniques is turning on
net.i2p.client.streaming.ConnectionPacketHandler=DEBUG and watching the RTT
times and window sizes as they go by. To overgeneralize for a moment, it's
common to see 3 types of connections: ~4s RTT, ~10s RTT, and ~30s RTT. Trying
to knock down the 30s RTT connections is the goal. If CPU contention is the
cause then maybe some juggling will do it.
</p><p>
Reducing the SSU max retrans from 10 is really just a stab in the dark as we
don't have good data on whether we are collapsing, having TCP-over-TCP issues,
or what, so more data is needed.
</p><p>
<i>
Worth looking into - what if we just disabled SSU's retransmissions? It'd
probably lead to much higher streaming lib resend rates, but maybe not.
</i>
</p><p>
What I don't understand, if you could elaborate, are the benefits of SSU
retransmissions for non-streaming-lib traffic. Do we need tunnel messages (for
example) to use a semi-reliable transport or can they use an unreliable or
kinda-sorta-reliable transport (1 or 2 retransmissions max, for example)? In
other words, why semi-reliability?
</p><p>
<i>
(but as you mention, if there's no queuing, it doesn't matter).
</i>
</p><p>
I implemented priority sending for UDP but it kicked in about 100,000 times
less often than the code on the NTCP side. Maybe that's a clue for further
investigation or a hint - I don't understand why it would back up that much
more often on NTCP, but maybe that's a hint on why NTCP performs worse.
</p>
<h3>Question answered by jrandom</h3>
Posted to new Syndie, 2007-03-31
<p>
measured SSU retransmission rates we saw back before NTCP was implemented
(10-30+&#37;)
</p><p>
Can the router itself measure this? If so, could a transport be selected based
on measured performance? (i.e. if an SSU connection to a peer is dropping an
unreasonable number of messages, prefer NTCP when sending to that peer)
</p><p>
Yeah, it currently uses that stat right now as a poor-man's MTU detection (if
the retransmission rate is high, it uses the small packet size, but if its low,
it uses the large packet size). We tried a few things when first introducing
NTCP (and when first moving away from the original TCP transport) that would
prefer SSU but fail that transport for a peer easily, causing it to fall back
on NTCP. However, there's certainly more that could be done in that regard,
though it gets complicated quickly (how/when to adjust/reset the bids, whether
to share these preferences across multiple peers or not, whether to share it
across multiple sessions with the same peer (and for how long), etc).
<h3>Response by foofighter</h3>
Posted to new Syndie, 2007-03-26
<p>
If I've understood things right, the primary reason in favor of TCP (in
general, both the old and new variety) was that you needn't worry about coding
a good TCP stack. Which ain't impossibly hard to get right... just that
existing TCP stacks have a 20 year lead.
</p><p>
AFAIK, there hasn't been much deep theory behind the preference of TCP versus
UDP, except the following considerations:
<ul>
<li>
A TCP-only network is very dependent on reachable peers (those who can forward
incoming connections through their NAT)
<li>
Still even if reachable peers are rare, having them be high capacity somewhat
alleviates the topological scarcity issues
<li>
UDP allows for "NAT hole punching" which lets people be "kind of
pseudo-reachable" (with the help of introducers) who could otherwise only
connect out
<li>
The "old" TCP transport implementation required lots of threads, which was a
performance killer, while the "new" TCP transport does well with few threads
<li>
Routers of set A crap out when saturated with UDP. Routers of set B crap out
when saturated with TCP.
<li>
It "feels" (as in, there are some indications but no scientific data or
quality statistics) that A is more widely deployed than B
<li>
Some networks carry non-DNS UDP datagrams with an outright shitty quality,
while still somewhat bothering to carry TCP streams.
</ul>
</p><p>
On that background, a small diversity of transports (as many as needed, but not
more) appears sensible in either case. Which should be the main transport,
depends on their performance-wise. I've seen nasty stuff on my line when I
tried to use its full capacity with UDP. Packet losses on the level of 35&#37;.
</p><p>
We could definitely try playing with UDP versus TCP priorities, but I'd urge
caution in that. I would urge that they not be changed too radically all at
once, or it might break things.
</p>
<h3>Response by zzz</h3>
Posted to new Syndie, 2007-03-27
<p>
<i>
AFAIK, there hasn't been much deep theory behind the preference of TCP versus
UDP, except the following considerations:
</i>
</p><p>
These are all valid issues. However you are considering the two protocols in
isolation, whether than thinking about what transport protocol is best for a
particular higher-level protocol (i.e. streaming lib or not).
</p><p>
What I'm saying is you have to take the streaming lib into consideration.
So either shift the preferences for everybody or treat streaming lib traffic
differently.
That's what my proposal 1B) is talking about - have a different preference for
streaming-lib traffic than for non streaming-lib traffic (for example tunnel
build messages).
</p><p>
<i>
On that background, a small diversity of transports (as many as needed, but
not more) appears sensible in either case. Which should be the main transport,
depends on their performance-wise. I've seen nasty stuff on my line when I
tried to use its full capacity with UDP. Packet losses on the level of 35&#37;.
</i>
</p><p>
Agreed. The new .28 may have made things better for packet loss over UDP, or
maybe not.
One important point - the transport code does remember failures of a transport.
So if UDP is the preferred transport, it will try it first, but if it fails for
a particular destination, the next attempt for that destination it will try
NTCP rather than trying UDP again.
</p><p>
<i>
We could definitely try playing with UDP versus TCP priorities, but I'd urge
caution in that. I would urge that they not be changed too radically all at
once, or it might break things.
</i>
</p><p>
We have four tuning knobs - the four bid values (SSU and NTCP, for
already-connected and not-already-connected).
We could make SSU be preferred over NTCP only if both are connected, for
example, but try NTCP first if neither transport is connected.
</p><p>
The other way to do it gradually is only shifting the streaming lib traffic
(the 1B proposal) however that could be hard and may have anonymity
implications, I don't know. Or maybe shift the traffic only for the first
outbound hop (i.e. don't propagate the flag to the next router), which gives
you only partial benefit but might be more anonymous and easier.
</p>
<h3>Results of the Discussion</h3>
... and other related changes in the same timeframe (2007):
<ul>
<li>
Significant tuning of the streaming lib parameters,
greatly increasing outbound performance, was implemented in 0.6.1.28
<li>
Priority sending for NTCP was implemented in 0.6.1.28
<li>
Priority sending for SSU was implemented by zzz but was never checked in
<li>
The advanced transport bid control
i2np.udp.preferred was implemented in 0.6.1.29.
<li>
Pushback for NTCP was implemented in 0.6.1.30, disabled in 0.6.1.31 due to anonymity concerns,
and re-enabled with improvements to address those concerns in 0.6.1.32.
<li>
None of zzz's proposals 1-5 have been implemented.
</ul>
{% endblock %}

View File

@@ -0,0 +1,245 @@
{% extends "global/layout.html" %}
{% block title %}Tunnel Discussion{% endblock %}
{% block content %}
Note: This document contains older information about alternatives to the
current tunnel implementation in I2P,
and speculation on future possibilities. For current information see
<a href="{{ site_url('docs/tunnels/implementation') }}">the tunnel page</a>.
<p>
That page documents the current tunnel build implementation as of release 0.6.1.10.
The older tunnel build method, used prior to release 0.6.1.10, is documented on
<a href="{{ site_url('docs/tunnels/old-implementation') }}">the old tunnel page</a>.
<h3 id="config">Configuration Alternatives</h3>
<p>Beyond their length, there may be additional configurable parameters
for each tunnel that can be used, such as a throttle on the frequency of
messages delivered, how padding should be used, how long a tunnel should be
in operation, whether to inject chaff messages, and what, if any, batching
strategies should be employed.
None of these are currently implemented.
</p>
<h3><a name="tunnel.padding">Padding Alternatives</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>These padding strategies can be used on a variety of levels, addressing the
exposure of message size information to different adversaries. After gathering
and reviewing some <a href="http://web.archive.org/web/20050413140457/http://dev.i2p.net/~jrandom/messageSizes/">statistics</a>
from the 0.4 network, as well as exploring the anonymity tradeoffs, we're starting
with a fixed tunnel message size of 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><a name="tunnel.fragmentation">Fragmentation Alternatives</a></h3>
<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>Routers have a lot of leeway as to how the fragments are arranged, whether
they are stuffed inefficiently as discrete units, batched for a brief period to
fit more payload into the 1024 byte tunnel messages, or opportunistically padded
with other messages that the gateway wanted to send out.</p>
<h3><a name="tunnel.alternatives">More Alternatives</a></h3>
<h4><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>Have a peer other than the endpoint temporarily act as the termination
point for a tunnel by adjusting the encryption used at the gateway to give them
the plaintext of the preprocessed I2NP messages. Each peer could check to see
whether they had the plaintext, processing the message when received as if they
did.</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.</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><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><a name="tunnel.backchannel">Backchannel communication</a></h4>
<p>At the moment, the IV values used are random values. However, it is
possible for that 16 byte value to be used to send control messages from the
gateway to the endpoint, or on outbound tunnels, from the gateway to any of the
peers. The inbound gateway could encode certain values in the IV once, which
the endpoint would be able to recover (since it knows the endpoint is also the
creator). For outbound tunnels, the creator could deliver certain values to the
participants during the tunnel creation (e.g. "if you see 0x0 as the IV, that
means X", "0x1 means Y", etc). Since the gateway on the outbound tunnel is also
the creator, they can build a IV so that any of the peers will receive the
correct value. The tunnel creator could even give the inbound tunnel gateway
a series of IV values which that gateway could use to communicate with
individual participants exactly one time (though this would have issues regarding
collusion detection)</p>
<p>This technique could later be used deliver message mid stream, or to allow the
inbound gateway to tell the endpoint that it is being DoS'ed or otherwise soon
to fail. At the moment, there are no plans to exploit this backchannel.</p>
<h4><a name="tunnel.variablesize">Variable size tunnel messages</a></h4>
<p>While the transport layer may have its own fixed or variable message size,
using its own fragmentation, the tunnel layer may instead use variable size
tunnel messages. The difference is an issue of threat models - a fixed size
at the transport layer helps reduce the information exposed to external
adversaries (though overall flow analysis still works), but for internal
adversaries (aka tunnel participants) the message size is exposed. Fixed size
tunnel messages help reduce the information exposed to tunnel participants, but
does not hide the information exposed to tunnel endpoints and gateways. Fixed
size end to end messages hide the information exposed to all peers in the
network.</p>
<p>As always, its a question of who I2P is trying to protect against. Variable
sized tunnel messages are dangerous, as they allow participants to use the
message size itself as a backchannel to other participants - e.g. if you see a
1337 byte message, you're on the same tunnel as another colluding peer. Even
with a fixed set of allowable sizes (1024, 2048, 4096, etc), that backchannel
still exists as peers could use the frequency of each size as the carrier (e.g.
two 1024 byte messages followed by an 8192). Smaller messages do incur the
overhead of the headers (IV, tunnel ID, hash portion, etc), but larger fixed size
messages either increase latency (due to batching) or dramatically increase
overhead (due to padding). Fragmentation helps amortize the overhead, at the
cost of potential message loss due to lost fragments.</p>
<p>Timing attacks are also relevant when reviewing the effectiveness of fixed
size messages, though they require a substantial view of network activity
patterns to be effective. Excessive artificial delays in the tunnel will be
detected by the tunnel's creator, due to periodic testing, causing that entire
tunnel to be scrapped and the profiles for peers within it to be adjusted.</p>
<h3><a name="tunnel.building.alternatives">Alternatives</a></h3>
Reference:
<a href="http://www-users.cs.umn.edu/~hopper/hashing_it_out.pdf">Hashing it out in Public</a>
<h4 id="tunnel.building.old">Old tunnel build method</h4>
The old tunnel build method, used prior to release 0.6.1.10, is documented on
<a href="{{ site_url('docs/tunnels/old-implementation') }}">the old tunnel page</a>.
This was an "all at once" or "parallel" method,
where messages were sent in parallel to each of the participants.
<h4><a name="tunnel.building.telescoping">One-Shot Telescopic building</a></h4>
NOTE: This is the current method.
<p>One question that arose 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="https://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 <a
href="http://dev.i2p.net/pipermail/2005-October/001057.html">packet count</a> as
the tunnel is built.</p>
<h4><a name="tunnel.building.telescoping">"Interactive" Telescopic building</a></h4>
Build the hops one at a time with a message through the existing part of the tunnel for each.
Has major issues as the peers can count the messages to determine their location in the tunnel.
<h4><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>
<h4><a name="tunnel.building.exploratory">Exploratory request delivery</a></h4>
<p>A third alternative, used until I2P 0.6.1.10, garlic encrypts individual tunnel
request messages and delivers them to the hops individually, transmitting them
through exploratory tunnels with their reply coming back in a separate
exploratory tunnel. This strategy has been dropped in favor of the one outlined
above.</p>
<h4 id="history">More History and Discussion</a></h4>
Before the introduction of the Variable Tunnel Build Message,
there were at least two problems:
<ol>
<li>
The size of the messages (caused by an 8-hop maximum, when the typical tunnel length is 2 or 3 hops...
and current research indicates that more than 3 hops does not enhance anonymity);
<li>
The high build failure rate, especially for long (and exploratory) tunnels, since all hops must agree or the tunnel is discarded.
</ol>
The VTBM has fixed #1 and improved #2.
<p>
Welterde has proposed modifications to the parallel method to allow for reconfiguration.
Sponge has proposed using 'tokens' of some sort.
<p>
Any students of tunnel building must study the historical record leading up to the current method,
especially the various anonymity vulnerabilities that may exist in various methods.
The mail archives from October 2005 at <a href="http://{{ i2pconv('zzz.i2p') }}/archives/2005-10/">zzz.i2p</a> or
<a href="http://osdir.com/ml/network.i2p/2005-10/">osdir.com</a> are particularly helpful.
As stated on <a href="{{ site_url('docs/spec/tunnel-creation') }}">the tunnel creation specification</a>,
the current strategy came about during a discussion on the I2P mailing list between
Michael Rogers, Matthew Toseland (toad), and jrandom regarding the predecessor attack.
See:<a href="http://osdir.com/ml/network.i2p/2005-10/msg00138.html">Summary</a> and
<a href="http://osdir.com/ml/network.i2p/2005-10/msg00129.html">Reasoning</a>.
<p>
The build changes in 0.6.1.10, released February 2006, were the last incompatible change in i2p;
i.e., all releases since 0.6.1.10 are backward compatible. Any tunnel build change would cause a similar 'flag day',
unless we implemented code so that the build originator would only use the new method if all participants
(and build/reply endpoints/gateways) supported it.
<h4><a name="ordering">Peer ordering alternatives</a></h4>
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>
<h2><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="{{ site_url('get-involved/roadmap') }}#v3.0">I2P 3.0</a></p>
{% endblock %}

View File

@@ -0,0 +1,463 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Low-level Cryptography Details{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}March 2012{% endtrans %}{% endblock %}
{% block accuratefor %}0.8.13{% endblock %}
{% block content %}
<p>{% trans -%}
This page specifies the low-level details of the cryptography in I2P.
{%- endtrans %}</p>
<p>{% trans elgamalaes=site_url('docs/how/elgamal-aes') -%}
There are a handful of cryptographic algorithms in use within I2P, but we have
reduced them to a bare minimum to deal with our needs - one symmetric algorithm
one asymmetric algorithm, one signing algorithm, and one hashing algorithm. However,
we do combine them in some particular ways to provide message integrity (rather than
relying on a MAC). In addition, as much as we hate doing anything new in regards to
cryptography, we can't seem to find a reference discussing (or even naming) the
technique used in <a href="{{ elgamalaes }}">ElGamal/AES+SessionTag</a> (but we're sure others have done it).
{%- endtrans %}</p>
<h2><a name="elgamal">{% trans %}ElGamal encryption{% endtrans %}</a></h2>
<p>{% trans %}
ElGamal is used for asymmetric encryption.
ElGamal is used in several places in I2P:
{%- endtrans %}</p>
<ul>
<li>{% trans tunnelcreation=site_url('docs/spec/tunnel-creation') -%}
To encrypt router-to-router <a href="{{ tunnelcreation }}">Tunnel Build Messages</a>
{%- endtrans %}</li>
<li>{% trans elgamalaes=site_url('docs/how/elgamal-aes'), commonstructures=site_url('docs/spec/common-structures') -%}
For end-to-end (destination-to-destination) encryption as a part of <a href="{{ elgamalaes }}">ElGamal/AES+SessionTag</a>
using the encryption key in the <a href="{{ commonstructures }}#struct_LeaseSet">LeaseSet</a>
{%- endtrans %}</li>
<li>{% trans netdb=site_url('docs/how/network-database'), elgamalaes=site_url('docs/how/elgamal-aes') -%}
For encryption of some <a href="{{ netdb }}#delivery">netDb stores and queries sent to floodfill routers</a>
as a part of <a href="{{ elgamalaes }}">ElGamal/AES+SessionTag</a>
(destination-to-router or router-to-router).
{%- endtrans %}</li>
</ul>
<p>{% trans -%}
We use common primes for 2048 ElGamal encryption and decryption, as given by <a href="http://tools.ietf.org/html/rfc3526">IETF RFC-3526</a>.
We currently only use ElGamal to encrypt the IV and session key in a single block, followed by the
AES encrypted payload using that key and IV.
{%- endtrans %}</p>
<p>{% trans -%}
The unencrypted ElGamal contains:
{%- endtrans %}</p>
<pre>
+----+----+----+----+----+----+----+----+
|nonz| H(data) |
+----+ +
| |
+ +
| |
+ +
| |
+ +----+----+----+----+----+----+----+
| | data...
+----+----+----+--//
</pre>
<p>{% trans -%}
The H(data) is the SHA256 of the data that is encrypted in the ElGamal block,
and is preceded by a nonzero byte.
This byte could be random, but as implemented it is always 0xFF.
It could possibly be used for flags in the future.
The data encrypted in the block may be up to 222 bytes long.
As the encrypted data may contain a substantial number of zeros if the
cleartext is smaller than 222 bytes, it is recommended that higher layers pad
the cleartext to 222 bytes with random data.
Total length: typically 255 bytes.
{%- endtrans %}</p>
<p>{% trans -%}
The encrypted ElGamal contains:
{%- endtrans %}</p>
</p>
<pre>
+----+----+----+----+----+----+----+----+
| zero padding... | |
+----+----+----+--// ----+ +
| |
+ +
| ElG encrypted part 1 |
~ ~
| |
+ +----+----+----+----+----+----+----+
| | zero padding... | |
+----+----+----+----+--// ----+ +
| |
+ +
| ElG encrypted part 2 |
~ ~
| |
+ +----+----+----+----+----+----+
| +
+----+----+
</pre>
<p>{% trans -%}
Each encrypted part is prepended with zeros to a size of exactly 257 bytes.
Total length: 514 bytes.
In typical usage, higher layers pad the cleartext data to 222 bytes,
resulting in an unencrypted block of 255 bytes.
This is encoded as two 256-byte encrypted parts,
and there is a single byte of zero padding before each part at this layer.
{%- endtrans %}</p>
<p>{% trans url='http://'+i2pconv('trac.i2p2.i2p')+'/browser/core/java/src/net/i2p/crypto/ElGamalEngine.java?rev=85a542c53d910dffbf34cdcefb8a2faeee96adc4' -%}
See <a href="{{ url }}">the ElGamal code</a>.
{%- endtrans %}</p>
<p>{% trans -%}
The shared prime is the
<a href="http://tools.ietf.org/html/rfc3526#section-3">[Oakley prime for 2048 bit keys]</a>
{%- endtrans %}</p>
<pre>
2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 }
</pre>
<p>{% trans -%}
or as a hexadecimal value:
{%- endtrans %}</p>
<pre>
FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D
C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F
83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B
E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9
DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510
15728E5A 8AACAA68 FFFFFFFF FFFFFFFF
</pre>
<p>{% trans -%}
Using 2 as the generator.
{%- endtrans %}</p>
<h3>{% trans %}Short Exponent{% endtrans %}</h3>
<p>{% trans commonstructures=site_url('docs/spec/common-structures'),
pdf='http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.14.5952&amp;rep=rep1&amp;type=pdf',
benchmarks=site_url('misc/benchmarks'),
oldbenchmarks='http://www.eskimo.com/~weidai/benchmarks.html' -%}
While the standard exponent size is 2048 bits (256 bytes) and the I2P
<a href="{{ commonstructures }}#type_PrivateKey">PrivateKey</a>
is a full 256 bytes,
we use the short exponent size of 226 bits (28.25 bytes).
This should be safe for use with the Oakley primes, per
<a href="{{ pdf }}">On Diffie-Hellman Key Agreement with Short Exponents - van Oorschot, Weiner</a>
at EuroCrypt 96, and <a href="{{ benchmarks }}">crypto++'s benchmarks</a>.
Benchmarks originally at <code>{{ oldbenchmarks }}</code> (now dead),
rescued from <a href="http://www.archive.org/">the wayback machine</a>, dated Apr 23, 2008.
{%- endtrans %}</p>
<p>{% trans book='http://www.springerlink.com/content/2jry7cftp5bpdghm/',
fulltext='http://books.google.com/books?id=cXyiNZ2_Pa0C&amp;lpg=PA173&amp;ots=PNIz3dWe4g&amp;pg=PA173#v=onepage&amp;q&amp;f=false',
thread='http://groups.google.com/group/sci.crypt/browse_thread/thread/1855a5efa7416677/339fa2f945cc9ba0#339fa2f945cc9ba0' -%}
Also, <a href="{{ book }}">Koshiba &amp; Kurosawa: Short Exponent Diffie-Hellman Problems</a> (PKC 2004, LNCS 2947, pp. 173-186)
<a href="{{ fulltext }}">(full text on Google Books)</a> apparently supports this, according to
<a href="{{ thread }}">this sci.crypt thread</a>.
The remainder of the PrivateKey is padded with zeroes.
{%- endtrans %}</p>
<h4>{% trans %}Obsolescence{% endtrans %}</h4>
<p>{% trans -%}
The vulnerability of the network to an ElGamal attack and the impact of transitioning to a longer bit length is to be studied.
It may be quite difficult to make any change backward-compatible.
{%- endtrans %}</p>
<h2><a name="AES">AES</a></h2>
<p>{% trans -%}
AES is used for symmetric encryption, in several cases:
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
For <a href="#transports">transport encryption</a> after DH key exchange
{%- endtrans %}</li>
<li>{% trans elgamalaes=site_url('docs/how/elgamal-aes') -%}
For end-to-end (destination-to-destination) encryption as a part of <a href="{{ elgamalaes }}">ElGamal/AES+SessionTag</a>
{%- endtrans %}</li>
<li>{% trans netdb=site_url('docs/how/network-database'), elgamalaes=site_url('docs/how/elgamal-aes') -%}
For encryption of some <a href="{{ netdb }}#delivery">netDb stores and queries sent to floodfill routers</a>
as a part of <a href="{{ elgamalaes }}">ElGamal/AES+SessionTag</a>
(destination-to-router or router-to-router).
{%- endtrans %}</li>
<li>{% trans tunnelrouting=site_url('docs/how/tunnel-routing') -%}
For encryption of <a href="{{ tunnelrouting }}#testing">periodic tunnel test messages</a> sent from the router to itself, through its own tunnels.
{%- endtrans %}</li>
</ul>
<p>{% trans rfc2313='http://tools.ietf.org/html/rfc2313',
code1='http://'+i2pconv('trac.i2p2.i2p')+'/browser/core/java/src/net/i2p/crypto/CryptixAESEngine.java?rev=85a542c53d910dffbf34cdcefb8a2faeee96adc4',
code2='http://'+i2pconv('trac.i2p2.i2p')+'/browser/core/java/src/net/i2p/crypto/CryptixRijndael_Algorithm.java?rev=85a542c53d910dffbf34cdcefb8a2faeee96adc4',
code3='http://'+i2pconv('trac.i2p2.i2p')+'/browser/core/java/src/net/i2p/crypto/ElGamalAESEngine.java?rev=85a542c53d910dffbf34cdcefb8a2faeee96adc4' -%}
We use AES with 256 bit keys and 128 bit blocks in CBC mode.
The padding used is specified in <a href="{{ rfc2313 }}">IETF RFC-2313 (PKCS#5 1.5, section 8.1 (for block type 02))</a>.
In this case, padding exists of pseudorandomly generated octets to match 16 byte blocks.
Specifically, see <a href="{{ code1 }}">[the CBC code]</a> and the Cryptix AES
<a href="{{ code2 }}">[implementation]</a>, as well as the padding, found in the
<a href="{{ code3 }}">ElGamalAESEngine.getPadding</a> function.
{%- endtrans %}</p>
<!-- *********************************************************************************
Believe it or not, we don't do this any more. If we ever did. safeEncode() and safeDecode() are unused.
<p>
In all cases, we know the size of the data to be sent, and we AES encrypt the following:
<p>
<pre>
+----+----+----+----+----+----+----+----+
| H(data) |
+ +
| |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| size | data ... |
+----+----+----+----+ +
| |
~ ~
| |
+ +
| |
+ +----//---+----+
| | |
+----+----+----//---+----+ +
| Padding to 16 bytes |
+----+----+----+----+----+----+----+----+
H(data): 32-byte SHA-256 Hash of the data
size: 4-byte Integer, number of data bytes to follow
data: payload
padding: random data, to a multiple of 16 bytes
</pre>
<p>
After the data comes an application-specified number of randomly generated padding bytes.
This application-specified number is rounded up to a multiple of 16.
The entire segment (from H(data) through the end of the random bytes) is AES encrypted
(256 bit CBC w/ PKCS#5).
<p>
This code is implemented in the safeEncrypt and safeDecrypt methods of
AESEngine but it is unused.
</p>
*************************************************************** -->
<h4>{% trans %}Obsolescence{% endtrans %}</h4>
<p>{% trans -%}
The vulnerability of the network to an AES attack and the impact of transitioning to a longer bit length is to be studied.
It may be quite difficult to make any change backward-compatible.
{%- endtrans %}</p>
<h4>{% trans %}References{% endtrans %}</h4>
<ul>
<li>
<a href="{{ get_url('blog_post', slug='2006/02/07/status') }}">{% trans %}Feb. 7, 2006 Status Notes{% endtrans %}</a>
</li>
</ul>
<h2><a name="DSA">DSA</a></h2>
<p>{% trans code='http://'+i2pconv('trac.i2p2.i2p')+'/browser/core/java/src/net/i2p/crypto/DSAEngine.java?rev=85a542c53d910dffbf34cdcefb8a2faeee96adc4' -%}
Signatures are generated and verified with 1024 bit DSA (L=1024, N=160), as implemented in
<a href="{{ code }}">[DSAEngine]</a>.
DSA was chosen because it is much faster for signatures than ElGamal.
{%- endtrans %}</p>
<h3>{% trans %}The DSA constants{% endtrans %}</h3>
<h4>SEED</h4>
<p>160 bit</p>
<pre>
86108236b8526e296e923a4015b4282845b572cc
</pre>
<h4>Counter</h4>
<pre>
33
</pre>
<p>
<H4>DSA prime (p)</H4>
<p>1024 bit</p>
<p>
<pre>
9C05B2AA 960D9B97 B8931963 C9CC9E8C 3026E9B8 ED92FAD0
A69CC886 D5BF8015 FCADAE31 A0AD18FA B3F01B00 A358DE23
7655C496 4AFAA2B3 37E96AD3 16B9FB1C C564B5AE C5B69A9F
F6C3E454 8707FEF8 503D91DD 8602E867 E6D35D22 35C1869C
E2479C3B 9D5401DE 04E0727F B33D6511 285D4CF2 9538D9E3
B6051F5B 22CC1C93
</pre>
<p>
<H4>DSA quotient (q)</H4>
<p>
<pre>
A5DFC28F EF4CA1E2 86744CD8 EED9D29D 684046B7
</pre>
<p>
<H4>DSA generator (g)</H4>
<p>1024 bit</p>
<p>
<pre>
C1F4D27D 40093B42 9E962D72 23824E0B BC47E7C8 32A39236
FC683AF8 48895810 75FF9082 ED32353D 4374D730 1CDA1D23
C431F469 8599DDA0 2451824F F3697525 93647CC3 DDC197DE
985E43D1 36CDCFC6 BD5409CD 2F450821 142A5E6F 8EB1C3AB
5D0484B8 129FCF17 BCE4F7F3 3321C3CB 3DBB14A9 05E7B2B3
E93BE470 8CBCC82
</pre>
<p>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
The <a href="{{ commonstructures }}#type_SigningPublicKey">Signing Public Key</a> is 1024 bits.
The <a href="{{ commonstructures }}#type_SigningPrivateKey">Signing Private Key</a> is 160 bits.
{%- endtrans %}</p>
<h4>{% trans %}Obsolescence{% endtrans %}</h4>
<p>{% trans pdf='http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57-Part1-revised2_Mar08-2007.pdf' -%}
<a href="{{ pdf }}">NIST 800-57</a>
recommends a minimum of (L=2048, N=224) for usage beyond 2010.
This may be mitigated somewhat by the "cryptoperiod", or lifespan of a given key.
{%- endtrans %}</p>
<p>{% trans -%}
The prime number was chosen <a href="#choosing_constants">in 2003</a>,
and the person that chose the number (TheCrypto) is currently no longer an I2P developer.
As such, we do not know if the prime chosen is a 'strong prime'.
If a larger prime is chosen for future purposes, this should be a strong prime, and we will document the construction process.
{%- endtrans %}</p>
<p>{% trans -%}
The vulnerability of the network to a DSA attack and the impact of transitioning to longer keys is to be studied.
It may be quite difficult to make any change backward-compatible.
{%- endtrans %}</p>
<h4>{% trans %}References{% endtrans %}</h4>
<ul>
<li>
<a href="{{ get_url('meetings_show', id=51) }}">{% trans num=51 %}Meeting {{ num }}{% endtrans %}</a>
<li>
<a href="{{ get_url('meetings_show', id=52) }}">{% trans num=52 %}Meeting {{ num }}{% endtrans %}</a>
<li>
<a name="choosing_constants" href="http://article.gmane.org/gmane.comp.security.invisiblenet.iip.devel/343">{% trans %}Choosing the constants{% endtrans %}</a>
<li>
<a href="http://en.wikipedia.org/wiki/Digital_Signature_Algorithm">DSA</a>
</ul>
<H2><a name="SHA256">SHA256</a></H2>
<p>{% trans code='http://'+i2pconv('trac.i2p2.i2p')+'/browser/core/java/src/net/i2p/crypto/SHA256Generator.java?rev=85a542c53d910dffbf34cdcefb8a2faeee96adc4' -%}
Hashes within I2P are plain old SHA256, as implemented in
<a href="{{ code }}">[SHA256Generator]</a>
{%- endtrans %}</p>
<h4>{% trans %}Obsolescence{% endtrans %}</h4>
<p>{% trans -%}
The vulnerability of the network to a SHA-256 attack and the impact of transitioning to a longer hash is to be studied.
It may be quite difficult to make any change backward-compatible.
{%- endtrans %}</p>
<h4>{% trans %}References{% endtrans %}</h4>
<ul>
<li>
<a href="http://en.wikipedia.org/wiki/SHA-2">SHA-2</a>
</ul>
<h2 id="transports">{% trans %}Transports{% endtrans %}</h2>
<p>{% trans -%}
At the lowest protocol layer,
point-to-point inter-router communication is protected by the transport layer security.
Both transports use 256 byte (2048 bit) Diffie-Hellman key exchange
using
<a href="#elgamal">the same shared prime and generator as specified above for ElGamal</a>,
followed by symmetric AES encryption as described above.
This provides
<a href="http://en.wikipedia.org/wiki/Perfect_forward_secrecy">perfect forward secrecy</a>
on the transport links.
{%- endtrans %}</p>
<h3><a name="tcp">{% trans %}NTCP connections{% endtrans %}</a></h3>
<p>{% trans elgamalaes=site_url('docs/how/elgamal-aes') -%}
NTCP connections are negotiated with a 2048 Diffie-Hellman implementation,
using the router's identity to proceed with a station to station agreement, followed by
some encrypted protocol specific fields, with all subsequent data encrypted with AES
(as above).
The primary reason to do the DH negotiation instead of using <a href="{{ elgamalaes }}">ElGamalAES+SessionTag</a> is that it provides '<a href="http://en.wikipedia.org/wiki/Perfect_forward_secrecy">(perfect) forward secrecy</a>', while <a href="{{ elgamalaes }}">ElGamalAES+SessionTag</a> does not.
{%- endtrans %}</p>
<p>{% trans -%}
In order to migrate to a more standardized implementation (TLS/SSL or even SSH), the following issues must be addressed:
{%- endtrans %}</p>
<ol>
<li>{% trans -%}
Can we somehow reestablish sessions securely (ala session tags) or do we need to do full negotiation each time?
{%- endtrans %}</li>
<li>{% trans -%}
Can we simplify/avoid the x509 or other certificate formats and use our own RouterInfo structure (which
contains the ElGamal and DSA keys)?
{%- endtrans %}</li>
</ol>
<p>{% trans ntcp=site_url('docs/transport/ntcp') -%}
See <a href="{{ ntcp }}">the NTCP specification</a> for details.
{%- endtrans %}</p>
<h3><a name="udp">{% trans %}UDP connections{% endtrans %}</a></h3>
<p>{% trans -%}
SSU (the UDP transport) encrypts each packet with AES256/CBC with both an explicit IV and MAC
(HMAC-MD5-128) after agreeing upon an ephemeral session key through a 2048 bit
Diffie-Hellman exchange, station-to-station authentication with the other
router's DSA key, plus each network message has their own hash for local integrity
checking.
{%- endtrans %}</p>
<p>{% trans ssu=site_url('docs/transport/ssu') -%}
See <a href="{{ ssu }}#keys">the SSU specification</a> for details.
{%- endtrans %}</p>
<p>{% trans statusnotes=get_url('blog_post', slug='2005/07/05/status') -%}
WARNING - I2P's HMAC-MD5-128 used in SSU is apparently non-standard.
Apparently, an early version of SSU used HMAC-SHA256, and then it was switched
to MD5-128 for performance reasons, but left the 32-byte buffer size intact.
See HMACGenerator.java and
<a href="{{ statusnotes }}">the 2005-07-05 status notes</a>
for details.
{%- endtrans %}</p>
<h2>{% trans %}References{% endtrans %}</h2>
<ul>
<li>
<a href="http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57-Part1-revised2_Mar08-2007.pdf">NIST 800-57</a>
</li>
</ul>
{% endblock %}

View File

@@ -0,0 +1,407 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}ElGamal/AES + SessionTag Encryption{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}February 2011{% endtrans %}{% endblock %}
{% block accuratefor %}0.8.3{% endblock %}
{% block content %}
<h2>{% trans %}Overview{% endtrans %}</h2>
<p>{% trans -%}
ElGamal/AES+SessionTags is used for end-to-end encryption.
{%- endtrans %}</p>
<p>{% trans -%}
As an unreliable, unordered, message based system, I2P uses a simple combination
of asymmetric and symmetric encryption algorithms to provide data confidentiality
and integrity to garlic messages. As a whole, the combination is referred
to as ElGamal/AES+SessionTags, but that is an excessively verbose way to describe
the use of 2048bit ElGamal, AES256, SHA256, and 32 byte nonces.
{%- endtrans %}</p>
<p>{% trans -%}
The first time a router wants to encrypt a garlic message to another router,
they encrypt the keying material for an AES256 session key with ElGamal and
append the AES256/CBC encrypted payload after that encrypted ElGamal block.
In addition to the encrypted payload, the AES encrypted section contains the
payload length, the SHA256 hash of the unencrypted payload, as well as a number
of "session tags" - random 32 byte nonces. The next time the sender wants
to encrypt a garlic message to another router, rather than ElGamal encrypt
a new session key they simply pick one of the previously delivered session
tags and AES encrypt the payload like before, using the session key used with
that session tag, prepended with the session tag itself. When a router receives
a garlic encrypted message, they check the first 32 bytes to see if it matches
an available session tag - if it does, they simply AES decrypt the message,
but if it does not, they ElGamal decrypt the first block.
{%- endtrans %}</p>
<p>{% trans -%}
Each session tag can be used only once so as to prevent internal adversaries
from unnecessarily correlating different messages as being between the same
routers. The sender of an ElGamal/AES+SessionTag encrypted message chooses
when and how many tags to deliver, prestocking the recipient with enough tags
to cover a volley of messages. Garlic messages may detect the successful tag
delivery by bundling a small additional message as a clove (a "delivery status
message") - when the garlic message arrives at the intended recipient and
is decrypted successfully, this small delivery status message is one of the
cloves exposed and has instructions for the recipient to send the clove back
to the original sender (through an inbound tunnel, of course). When the original
sender receives this delivery status message, they know that the session tags
bundled in the garlic message were successfully delivered.
{%- endtrans %}</p>
<p>{% trans -%}
Session tags themselves have a short lifetime, after which they are
discarded if not used. In addition, the quantity stored for each key is limited,
as are the number of keys themselves - if too many arrive, either new or old
messages may be dropped. The sender keeps track whether messages using session
tags are getting through, and if there isn't sufficient communication it may
drop the ones previously assumed to be properly delivered, reverting back
to the full expensive ElGamal encryption.
A session will continue to exist until all its tags are exhausted or expire.
{%- endtrans %}</p>
<p>{% trans -%}
Sessions are unidirectional. Tags are delivered from Alice to Bob,
and Alice then uses the tags, one by one, in subsequent messages to Bob.
{%- endtrans %}</p>
<p>{% trans -%}
Sessions may be established between Destinations, between Routers, or
between a Router and a Destination.
Each Router and Destination maintains its own Session Key Manager to
keep track of Session Keys and Session Tags.
Separate Session Key Managers prevents correlation of multiple Destinations
to each other or a Router by adversaries.
{%- endtrans %}</p>
<h2>{% trans %}Message Reception{% endtrans %}</h2>
<p>{% trans -%}
Each message received has one of two
the two possible conditions:</p>
{%- endtrans %}</p>
<ol>
<li>{% trans %}It is part of an existing session and contains a Session Tag and an AES encrypted block{% endtrans %}</li>
<li>{% trans %}It is for a new session and contains both ElGamal and AES encrypted blocks{% endtrans %}</li>
</ol>
<p>{% trans -%}
When a router receives a message, it will first assume it is from
an existing session and attempt to look up the Session Tag and decrypt the following data using AES.
If that fails, it will assume it is for a new session and attempt to
decrypt it using ElGamal.
{%- endtrans %}</p>
<h2 id="new">{% trans %}New Session Message Specification{% endtrans %}</h2>
<p>{% trans -%}
A New Session ElGamal Message contains two parts, an encrypted ElGamal block
and an encrypted AES block.
{%- endtrans %}</p>
<p>{% trans -%}
The encrypted message contains:
{%- endtrans %}</p>
<pre>
+----+----+----+----+----+----+----+----+
| |
+ +
| ElGamal Encrypted Block |
~ ~
| |
+ +----+----+----+----+----+----+
| | |
+----+----+ +
| |
+ +
| AES Encrypted Block |
~ ~
| |
+ +----+----+----+----+----+----+
| +
+----+----+
</pre>
<h3>{% trans %}ElGamal Block{% endtrans %}</h3>
<p>{% trans -%}
The encrypted ElGamal Block is always 514 bytes long.
{%- endtrans %}</p>
<p>{% trans -%}
The unencrypted ElGamal data is 222 bytes long, containing:
{%- endtrans %}</p>
<pre>
+----+----+----+----+----+----+----+----+
| |
+ +
| Session Key |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| |
+ +
| Pre-IV |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
+ +
| |
+ +
| 158 bytes random padding |
~ ~
| |
+ +----+----+
| |
+----+----+----+----+----+----+
</pre>
<p>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
The 32-byte
<a href="{{ commonstructures }}#type_SessionKey">Session Key</a>
is the identifier for the session.
The 32-byte Pre-IV will be used to generate the IV for the AES block that follows;
the IV is the first 16 bytes of the SHA-256 Hash of the Pre-IV.
{%- endtrans %}</p>
<p>{% trans cryptography=site_url('docs/how/cryptography') -%}
The 222 byte payload is encrypted
<a href="{{ cryptography }}#elgamal">using ElGamal</a>
and the encrypted block is 514 bytes long.
</p>
{%- endtrans %}</p>
<h3 id="aes">{% trans %}AES Block{% endtrans %}</h3>
<p>{% trans -%}
The unencrypted data in the AES block contains the following:
{%- endtrans %}</p>
<pre>
+----+----+----+----+----+----+----+----+
|tag count| |
+----+----+ +
| |
+ +
| Session Tags |
~ ~
| |
+ +
| |
+ +----+----+----+----+----+----+
| | payload size | |
+----+----+----+----+----+----+ +
| |
+ +
| Payload Hash |
+ +
| |
+ +----+----+
| |flag| |
+----+----+----+----+----+----+----+ +
| |
+ +
| New Session Key (opt.) |
+ +
| |
+ +----+
| | |
+----+----+----+----+----+----+----+ +
| |
+ +
| Payload |
~ ~
| |
+ +----//---+----+
| | |
+----+----+----//---+----+ +
| Padding to 16 bytes |
+----+----+----+----+----+----+----+----+
tag count: {% trans commonstructures=site_url('docs/spec/common-structures') -%}
2-byte <a href="{{ commonstructures }}#type_Integer">Integer</a>, 0-200
{%- endtrans %}
Session Tags: {% trans commonstructures=site_url('docs/spec/common-structures') -%}
That many 32-byte <a href="{{ commonstructures }}#type_SessionTag">Session Tags</a>
{%- endtrans %}
payload size: {% trans commonstructures=site_url('docs/spec/common-structures') -%}
4-byte <a href="{{ commonstructures }}#type_Integer">Integer</a>
{%- endtrans %}
Payload Hash: {% trans commonstructures=site_url('docs/spec/common-structures') -%}
The 32-byte <a href="{{ commonstructures }}#type_Hash">SHA256 Hash</a> of the payload
{%- endtrans %}
flag: {% trans -%}
A one-byte value. Normally == 0. If == 0x01, a Session Key follows
{%- endtrans %}
New Session Key: {% trans commonstructures=site_url('docs/spec/common-structures') -%}
A 32-byte <a href="{{ commonstructures }}#type_SessionKey">Session Key</a>,
to replace the old key, and is only present if preceding flag is 0x01
{%- endtrans %}
Payload: {% trans %}the data{% endtrans %}
Padding: {% trans -%}
Random data to a multiple of 16 bytes for the total length.
May contain more than the minimum required padding.
{%- endtrans %}
{% trans %}Minimum length: 48 bytes{% endtrans %}
</pre>
<p>{% trans cryptography=site_url('docs/how/cryptography') -%}
The data is then <a href="{{ cryptography }}">AES Encrypted</a>,
using the session key and IV (calculated from the pre-IV) from the ElGamal section.
The encrypted AES Block length is variable but is always a multiple of 16 bytes.
</p>
{%- endtrans %}</p>
<h4>{% trans %}Notes{% endtrans %}</h4>
<ul>
<li>{% trans i2np=site_url('docs/protocol/i2np') -%}
Actual max payload length, and max block length, is less than 64 KB; see the <a href="{{ i2np }}">I2NP Overview</a>.
{%- endtrans %}</li>
<li>{% trans %}New Session Key is currently unused and is never present.{% endtrans %}</li>
</ul>
<h2 id="existing">{% trans %}Existing Session Message Specification{% endtrans %}</h2>
<p>{% trans -%}
The session tags delivered successfully are remembered for a
brief period (15 minutes currently) until they are used or discarded.
A tag is used by packaging one in an Existing Session Message that
contains only an AES encrypted block, and is not preceded by an
ElGamal block.
{%- endtrans %}</p>
<p>{% trans -%}
The existing session message is
as follows:
{%- endtrans %}</p>
<pre>
+----+----+----+----+----+----+----+----+
| |
+ +
| Session Tag |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| |
+ +
| AES Encrypted Block |
~ ~
| |
+ +
| |
+----+----+----+----+----+----+----+----+
Session Tag: {% trans commonstructures=site_url('docs/spec/common-structures') -%}
A 32-byte <a href="{{ commonstructures }}#type_SessionTag">Session Tag</a>
previously delivered in an AES block
{%- endtrans %}
AES Encrypyted Block: {% trans %}As specified <a href="#aes">above</a>.{% endtrans %}
</pre>
<p>{% trans -%}
The session tag also serves as
the pre-IV. The IV is the first 16 bytes of the SHA-256 Hash of the sessionTag.
{%- endtrans %}</p>
<p>{% trans -%}
To decode a message from an existing session, a router looks up the Session Tag to find an
associated Session Key. If the Session Tag is found, the AES block is decrypted using the associated Session Key.
If the tag is not found, the message is assumed to be a <a href="#new">New Session Message</a>.
{%- endtrans %}</p>
<h2 id="future">{% trans %}Future Work{% endtrans %}</h2>
<p>{% trans -%}
There are many possible areas to tune the Session Key Manager's algorithms;
some may interact with the streaming library behavior, or have significant
impact on overall performance.
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
Delivery of too many tags at one time may impose substantial overhead for brief streaming connections
or datagrams, and increase the chance of message loss.
We currently deliver 40 tags at a time (1280 bytes).
32 (1024 bytes) may be better for tunnel fragmentation.
{%- endtrans %}</li>
<li>{% trans -%}
A few tags could be delivered in each of several messages, or lots of tags all at once.
{%- endtrans %}</li>
<li>{% trans -%}
It is also important to study and tune
the low-tag thresholds at which more tags are sent.
{%- endtrans %}</li>
<li>{% trans -%}
The number of tags delivered could depend on message size, keeping in mind
the eventual padding to 1KB at the tunnel message layer.
{%- endtrans %}</li>
<li>{% trans -%}
Clients could send an estimate of session lifetime to the router, as an advisory
on the number of tags required.
{%- endtrans %}</li>
<li>{% trans -%}
Delivery of too few tags causes the router to fall back to an expensive ElGamal encryption.
{%- endtrans %}</li>
<li>{% trans -%}
The router may assume delivery of Session Tags, or await acknowledgement before using them;
there are tradeoffs for each strategy.
{%- endtrans %}</li>
<li>{% trans -%}
For very brief messages, almost the full 222 bytes of the pre-IV and padding fields in the ElGamal block
could be used for the entire message, instead of establishing a session.
{%- endtrans %}</li>
<li>{% trans -%}
Evaluate padding strategy; currently we pad to a minimum of 128 bytes.
Would be better to add a few tags to small messages than pad.
{%- endtrans %}</li>
<li>{% trans -%}
Perhaps things could be more efficient if the Session Tag system was bidirectional,
so tags delivered in the 'forward' path could be used in the 'reverse' path,
thus avoiding ElGamal in the initial response.
The router currently plays some tricks like this when sending
tunnel test messages to itself.
{%- endtrans %}</li>
<li>{% trans futureperf=site_url('about/performance/future') -%}
Change from Session Tags to
<a href="{{ futureperf }}#prng">a synchronized PRNG</a>.
{%- endtrans %}</li>
<li>{% trans tunnelmessage=site_url('docs/spec/tunnel-message') -%}
Several of these ideas may require a new I2NP message type, or
set a flag in the
<a href="{{ tunnelmessage }}#delivery">Delivery Instructions</a>,
or set a magic number in the first few bytes of the Session Key field
and accept a small risk of the random Session Key matching the magic number.
{%- endtrans %}</li>
</ul>
{% endblock %}

View File

@@ -0,0 +1,310 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Garlic Routing{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}August 2010{% endtrans %}{% endblock %}
{% block accuratefor %}0.8{% endblock %}
{% block content %}
<h2>{% trans %}Garlic Routing and "Garlic" Terminology{% endtrans %}</h2>
<p>{% trans -%}
The terms "garlic routing" and "garlic encryption" are often used rather loosely when referring to I2P's technology.
Here, we explain the history of the terms, the various meanings, and
the usage of "garlic" methods in I2P.
{%- endtrans %}</p>
<p>{% trans -%}
"Garlic routing" was first coined by
<a href="http://www.cs.princeton.edu/~mfreed/">Michael J. Freedman</a>
in Roger Dingledine's Free Haven
<a href="http://www.freehaven.net/papers.html">Master's thesis</a> Section 8.1.1 (June 2000), as derived from
<a href="http://www.onion-router.net/">Onion Routing</a>.
{%- endtrans %}</p>
<p>{% trans -%}
"Garlic" may have been used originally by I2P developers because I2P implements a form of
bundling as Freedman describes, or simply to emphasize general differences from Tor.
The specific reasoning may be lost to history.
Generally, when referring to I2P, the term "garlic" may mean one of three things:
{%- endtrans %}</p>
<ol>
<li>{% trans %}Layered Encryption{% endtrans %}</li>
<li>{% trans %}Bundling multiple messages together{% endtrans %}</li>
<li>{% trans %}ElGamal/AES Encryption{% endtrans %}</li>
</ol>
<p>{% trans -%}
Unfortunately, I2P's usage of "garlic" terminology over the past seven years has not always been precise; therefore the reader is
cautioned when encountering the term.
Hopefully, the explanation below will make things clear.
{%- endtrans %}</p>
<h3>{% trans %}Layered Encryption{% endtrans %}</h3>
<p>{% trans -%}
Onion routing is a technique for building paths, or tunnels, through a series of peers,
and then using that tunnel.
Messages are repeatedly encrypted by the originator, and then decrypted by each hop.
During the building phase, only the routing instructions for the next hop are exposed to each peer.
During the operating phase, messages are passed through the tunnel, and the
message and its routing instructions are only exposed to the endpoint of the tunnel.
{%- endtrans %}</p>
<p>{% trans comparisons=site_url('comparison') -%}
This is similar to the way Mixmaster
(see <a href="{{ comparisons }}">network comparisons</a>) sends messages - taking a message, encrypting it
to the recipient's public key, taking that encrypted message and encrypting
it (along with instructions specifying the next hop), and then taking that
resulting encrypted message and so on, until it has one layer of encryption
per hop along the path.
{%- endtrans %}</p>
<p>{% trans -%}
In this sense, "garlic routing" as a general concept is identical to "onion routing".
As implemented in I2P, of course, there are several differences from the implementation in Tor; see below.
Even so, there are substantial similarities such that I2P benefits from a
<a href="http://www.onion-router.net/Publications.html">large amount of academic research on onion routing</a>,
<a href="http://freehaven.net/anonbib/topic.html">Tor, and similar mixnets</a>.
{%- endtrans %}</p>
<h3>{% trans %}Bundling Multiple Messages{% endtrans %}</h3>
<p>{% trans -%}
Michael Freedman defined "garlic routing" as an extension to onion routing,
in which multiple messages are bundled together.
He called each message a "bulb".
All the messages, each with its own delivery instructions, are exposed at the
endpoint.
This allows the efficient bundling of an onion routing "reply block" with the original message.
{%- endtrans %}</p>
<p>{% trans -%}
This concept is implemented in I2P, as described below.
Our term for garlic "bulbs" is "cloves".
Any number of messages can be
contained, instead of just a single message.
This is a significant distinction from the onion routing implemented in Tor.
However, it is only one of many major architectural differences between I2P and Tor;
perhaps it is not, by itself, enough to justify a change in terminology.
{%- endtrans %}</p>
<p>{% trans -%}
Another difference
from the method described by Freedman
is that the path is unidirectional - there is no "turning point" as seen in onion routing
or mixmaster reply blocks, which greatly simplifies the algorithm and allows for more flexible
and reliable delivery.
{%- endtrans %}</p>
<h3>{% trans %}ElGamal/AES Encryption{% endtrans %}</h3>
<p>{% trans elgamalaes=site_url('docs/how/elgamal-aes') -%}
In some cases, "garlic encryption" may simply mean
<a href="{{ elgamalaes }}">ElGamal/AES+SessionTag</a> encryption
(without multiple layers).
{%- endtrans %}</p>
<h2>{% trans %}"Garlic" Methods in I2P{% endtrans %}</h2>
<p>{% trans -%}
Now that we've defined various "garlic" terms, we can say that
I2P uses garlic routing, bundling and encryption in three places:
{%- endtrans %}</p>
<ol>
<li>{% trans %}For building and routing through tunnels (layered encryption){% endtrans %}
<li>{% trans %}For determining the success or failure of end to end message delivery (bundling){% endtrans %}
<li>{% trans %}For publishing some network database entries (dampening the probability of a successful traffic analysis attack) (ElGamal/AES){% endtrans %}
</ol>
<p>{% trans -%}
There are also significant ways that this technique can be used to improve the performance of the network,
exploiting transport latency/throughput tradeoffs, and branching data through redundant paths to increase reliability.
{%- endtrans %}</p>
<h3>{% trans %}Tunnel Building and Routing{% endtrans %}</h3>
<p>{% trans -%}
In I2P, tunnels are unidirectional. Each party builds two tunnels,
one for outbound and one for inbound traffic.
Therefore, four tunnels are required for a single round-trip message and reply.
{%- endtrans %}</p>
<p>{% trans tunnelimpl=site_url('docs/tunnels/implementation'),
tunnelcreation=site_url('docs/spec/tunnel-creation'),
elgamalaes=site_url('docs/how/elgamal-aes') -%}
Tunnels are built, and then used, with layered encryption.
This is described on the
<a href="{{ tunnelimpl }}">tunnel implementation page</a>.
Tunnel building details are defined on
<a href="{{ tunnelcreation }}">this page</a>.
We use
<a href="{{ elgamalaes }}">ElGamal/AES+SessionTag</a> for the encryption.
{%- endtrans %}</p>
<p>{% trans i2np=site_url('docs/protocol/i2np'), i2npspec=site_url('docs/spec/i2np') -%}
Tunnels are a general-purpose mechanism to transport all
<a href="{{ i2np }}">I2NP messages</a>, and
<a href="{{ i2npspec }}#msg_Garlic">Garlic Messages</a> are not used to build tunnels.
We do not bundle multiple
<a href="{{ i2np }}">I2NP messages</a> into a single
<a href="{{ i2npspec }}#msg_Garlic">Garlic Message</a> for unwrapping at the outbound tunnel endpoint;
the tunnel encryption is sufficient.
{%- endtrans %}</p>
<h3>{% trans %}End-to-End Message Bundling{% endtrans %}</h3>
<p>{% trans commonstructures=site_url('docs/spec/common-structures'),
elgamalaes=site_url('docs/how/elgamal-aes'),
i2cp=site_url('docs/protocol/i2cp'),
i2npspec=site_url('docs/spec/i2np'),
tunnelmessage=site_url('docs/spec/tunnel-message') -%}
At the layer above tunnels, I2P delivers end-to-end messages between
<a href="{{ commonstructures }}#struct_Destination">Destinations</a>.
Just as within a single tunnel, we use
<a href="{{ elgamalaes }}">ElGamal/AES+SessionTag</a> for the encryption.
Each client message as delivered to the router through the
<a href="{{ i2cp }}">I2CP interface</a> becomes a single
<a href="{{ i2npspec }}#struct_GarlicClove">Garlic Clove</a>
with its own
<a href="{{ tunnelmessage }}#delivery">Delivery Instructions</a>,
inside a
<a href="{{ i2npspec }}#msg_Garlic">Garlic Message</a>.
Delivery Instructions may specify a Destination, Router, or Tunnel.
{%- endtrans %}</p>
<p>{% trans -%}
Generally, a Garlic Message will contain only one clove.
However, the router will periodically bundle two additional
cloves in the Garlic Message:
{%- endtrans %}</p>
<img src="/_static/images/garliccloves.png" alt="{{ _('Garlic Message Cloves') }}" title="{{ _('Garlic Message Cloves') }}" style="text-align:center;"/>
<ol>
<li>{% trans i2npspec=site_url('docs/spec/i2np'),
tunnelmessage=site_url('docs/spec/tunnel-message') -%}
A
<a href="{{ i2npspec }}#msg_DeliveryStatus">Delivery Status Message</a>,
with
<a href="{{ tunnelmessage }}#delivery">Delivery Instructions</a>
specifying that it be sent back to the originating router as an acknowledgment.
This is similar to the "reply block" or "reply onion"
described in the references.
It is used for determining the success or failure of end to end message delivery.
The originating router may, upon failure to receive the Delivery Status Message
within the expected time period, modify the routing to the far-end Destination,
or take other actions.
{%- endtrans %}</li>
<li>{% trans i2npspec=site_url('docs/spec/i2np'),
commonstructures=site_url('docs/spec/common-structures'),
tunnelmessage=site_url('docs/spec/tunnel-message'),
netdb=site_url('docs/how/network-database') -%}
A
<a href="{{ i2npspec }}#msg_DatabaseStore">Database Store Message</a>,
containing a
<a href="{{ commonstructures }}#struct_LeaseSet">LeaseSet</a>
for the originating Destination, with
<a href="{{ tunnelmessage }}#delivery">Delivery Instructions</a>
specifying the far-end destination's router.
By periodically bundling a LeaseSet, the router ensures that the far-end will be able
to maintain communications.
Otherwise the far-end would have to query a floodfill router for the network database entry,
and all LeaseSets would have to be published to the network database, as explained on the
<a href="{{ netdb }}">network database page</a>.
{%- endtrans %}</li>
</ol>
<p>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
In the current implementation, the Delivery Status and Database Store Messages
are bundled when the local LeaseSet changes, when additional
<a href="{{ commonstructures }}#type_SessionTag">Session Tags</a>
are delivered, or if the messages have not been bundled in the previous minute.
{%- endtrans %}</p>
<p>{% trans -%}
Obviously, the additional messages are currently bundled for specific purposes,
and not part of a general-purpose routing scheme.
{%- endtrans %}</p>
<h3>{% trans %}Storage to the Floodfill Network Database{% endtrans %}</h3>
<p>{% trans netdb=site_url('docs/how/network-database'),
commonstructures=site_url('docs/spec/common-structures'),
i2npspec=site_url('docs/spec/i2np') -%}
As explained on the
<a href="{{ netdb }}#delivery">network database page</a>,
local
<a href="{{ commonstructures }}#struct_LeaseSet">LeaseSets</a>
are sent to floodfill routers in a
<a href="{{ i2npspec }}#msg_DatabaseStore">Database Store Message</a>
wrapped in a
<a href="{{ i2npspec }}#msg_Garlic">Garlic Message</a>
so it is not visible to the tunnel's outbound gateway.
{%- endtrans %}</p>
<h2>{% trans %}Future Work{% endtrans %}</h2>
<p>{% trans tunnelmessage=site_url('docs/spec/tunnel-message') -%}
The Garlic Message mechanism is very flexible and provides a structure for
implementing many types of mixnet delivery methods.
Together with the unused delay option in the
<a href="{{ tunnelmessage }}#delivery">tunnel message Delivery Instructions</a>,
a wide spectrum of batching, delay, mixing, and routing strategies are possible.
{%- endtrans %}</p>
<p>{% trans -%}
In particular, there is potential for much more flexibility at the outbound tunnel endpoint.
Messages could possibly be routed from there to one of several tunnels
(thus minimizing point-to-point connections), or multicast to several tunnels
for redundancy, or streaming audio and video.
{%- endtrans %}</p>
<p>{% trans -%}
Such experiments may conflict with the need to ensure security and anonymity, such
as limiting certain routing paths, restricting the types of I2NP messages that may
be forwarded along various paths, and enforcing certain message expiration times.
{%- endtrans %}</p>
<p>{% trans elgamalaes=site_url('docs/how/elgamal-aes') -%}
As a part of
<a href="{{ elgamalaes }}">ElGamal/AES encryption</a>,
a garlic message contains a sender
specified amount of padding data, allowing the sender to take active countermeasures
against traffic analysis.
This is not currently used, beyond the requirement to pad to a multiple of 16 bytes.
{%- endtrans %}</p>
<p>{% trans netdb=site_url('docs/how/network-database') -%}
Encryption of additional messages to and from the
<a href="{{ netdb }}#delivery">floodfill routers</a>.
{%- endtrans %}</p>
<h2>{% trans %}References{% endtrans %}</h2>
<ul>
<li>{% trans -%}
The term garlic routing was first coined in Roger Dingledine's Free Haven
<a href="http://www.freehaven.net/papers.html">Master's thesis</a> (June 2000),
see Section 8.1.1 authored by
<a href="http://www.cs.princeton.edu/~mfreed/">Michael J. Freedman</a>.
{%- endtrans %}</li>
<li>
<a href="http://www.onion-router.net/Publications.html">{% trans %}Onion router publications{% endtrans %}</a>
</li><li>
<a href="http://en.wikipedia.org/wiki/Onion_routing">{% trans %}Onion Routing on Wikipedia{% endtrans %}</a>
</li><li>
<a href="http://en.wikipedia.org/wiki/Garlic_routing">{% trans %}Garlic Routing on Wikipedia{% endtrans %}</a>
</li>
<li>{% trans meeting58=get_url('meetings_show', id=58) -%}
<a href="{{ meeting58 }}">I2P Meeting 58</a> (2003) discussing the implementation of garlic routing
{%- endtrans %}</li>
<li>
<a href="https://www.torproject.org/">Tor</a>
</li><li>
<a href="http://freehaven.net/anonbib/topic.html">{% trans %}Free Haven publications{% endtrans %}</a>
</li>
<li>{% trans -%}
Onion routing was first described in <a href="http://www.onion-router.net/Publications/IH-1996.pdf">Hiding Routing Information</a>
by David M. Goldschlag, Michael G. Reed, and Paul F. Syverson in 1996.
{%- endtrans %}</li>
</ul>
{% endblock %}

View File

@@ -0,0 +1,192 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}A Gentle Introduction{% endtrans %}{% endblock %}
{% block content %}
<h2>{% trans %}A Gentle Introduction to How I2P Works{% endtrans %}</h2>
<p>{% trans -%}
I2P is a project to build, deploy, and maintain a network supporting secure and anonymous
communication. People using I2P are in control of the tradeoffs between anonymity, reliability,
bandwidth usage, and latency. There is no central point in the network on which pressure can be
exerted to compromise the integrity, security, or anonymity of the system. The network supports
dynamic reconfiguration in response to various attacks, and has been designed to make use of
additional resources as they become available. Of course, all aspects of the network are open and
freely available.
{%- endtrans %}</p>
<p>{% trans -%}
Unlike many other anonymizing networks, I2P doesn't try to provide anonymity by hiding the
originator of some communication and not the recipient, or the other way around. I2P is designed to
allow peers using I2P to communicate with each other anonymously &mdash; both sender and recipient
are unidentifiable to each other as well as to third parties. For example, today there are both
in-I2P web sites (allowing anonymous publishing / hosting) as well as HTTP proxies to the normal web
(allowing anonymous web browsing). Having the ability to run servers within I2P is essential, as it
is quite likely that any outbound proxies to the normal Internet will be monitored, disabled, or
even taken over to attempt more malicious attacks.
{%- endtrans %}</p>
<p>{% trans i2ptunnel=site_url('docs/api/i2ptunnel') -%}
The network itself is message oriented - it is essentially a secure and anonymous IP layer, where
messages are addressed to cryptographic keys (Destinations) and can be significantly larger than IP
packets. Some example uses of the network include "eepsites" (webservers hosting normal web
applications within I2P), a BitTorrent client ("I2PSnark"), or a distributed data store. With the
help of the <a href="{{ i2ptunnel }}">I2PTunnel</a> application, we are able to stream traditional
TCP/IP applications over I2P, such as SSH, IRC, a squid proxy, and even streaming audio. Most people
will not use I2P directly, or even need to know they're using it. Instead their view will be of one
of the I2P enabled applications, or perhaps as a little controller app to turn on and off various
proxies to enable the anonymizing functionality.
{%- endtrans %}</p>
<p>{% trans threatmodel=site_url('docs/how/threat-model') -%}
An essential part of designing, developing, and testing an anonymizing network is to define the <a
href="{{ threatmodel }}">threat model</a>, since there is no such thing as "true" anonymity, just
increasingly expensive costs to identify someone. Briefly, I2P's intent is to allow people to
communicate in arbitrarily hostile environments by providing good anonymity, mixed in with
sufficient cover traffic provided by the activity of people who require less anonymity. This way,
some users can avoid detection by a very powerful adversary, while others will try to evade a weaker
entity, <i>all on the same network</i>, where each one's messages are essentially indistinguishable
from the others.
{%- endtrans %}</p>
<h2>{% trans %}Why?{% endtrans %}</h2>
<p>{% trans comparisons=site_url('comparison') -%}
There are a multitude of reasons why we need a system to support anonymous communication, and
everyone has their own personal rationale. There are many <a href="{{ comparisons }}">other
efforts</a> working on finding ways to provide varying degrees of anonymity to people through the
Internet, but we could not find any that met our needs or threat model.
{%- endtrans %}</p>
<h2>{% trans %}How?{% endtrans %}</h2>
<p>{% trans tunnelrouting=site_url('docs/how/tunnel-routing'), netdb=site_url('docs/how/network-database') -%}
The network at a glance is made up of a set of nodes ("routers") with a number of unidirectional
inbound and outbound virtual paths ("tunnels", as outlined on the <a href="{{ tunnelrouting
}}">tunnel routing</a> page). Each router is identified by a cryptographic RouterIdentity which is
typically long lived. These routers communicate with each other through existing transport
mechanisms (TCP, UDP, etc), passing various messages. Client applications have their own
cryptographic identifier ("Destination") which enables it to send and receive messages. These
clients can connect to any router and authorize the temporary allocation ("lease") of some tunnels
that will be used for sending and receiving messages through the network. I2P has its own internal
<a href="{{ netdb }}">network database</a> (using a modification of the Kademlia algorithm) for
distributing routing and contact information securely.
{%- endtrans %}</p>
<div class="box" style="text-align:center;"><img src="{{ url_for('static', filename='images/net.png') }}" alt="{% trans %}Network topology example{% endtrans %}" title="{% trans %}Network topology example{% endtrans %}" /></div>
<p>{% trans -%}
In the above, Alice, Bob, Charlie, and Dave are all running routers with a single Destination on
their local router. They each have a pair of 2-hop inbound tunnels per destination (labeled 1, 2, 3,
4, 5 and 6), and a small subset of each of those router's outbound tunnel pool is shown with 2-hop
outbound tunnels. For simplicity, Charlie's inbound tunnels and Dave's outbound tunnels are not
shown, nor are the rest of each router's outbound tunnel pool (typically stocked with a few tunnels
at a time). When Alice and Bob talk to each other, Alice sends a message out one of her (pink)
outbound tunnels targeting one of Bob's (green) inbound tunnels (tunnel 3 or 4). She knows to send
to those tunnels on the correct router by querying the network database, which is constantly updated
as new leases are authorized and old ones expire.
{%- endtrans %}</p>
<p>{% trans garlicrouting=site_url('docs/how/garlic-routing') -%}
If Bob wants to reply to Alice, he simply goes through the same process - send a message out one of
his outbound tunnels targeting one of Alice's inbound tunnels (tunnel 1 or 2). To make things
easier, most messages sent between Alice and Bob are <a href="{{ garlicrouting }}">garlic</a>
wrapped, bundling the sender's own current lease information so that the recipient can reply
immediately without having to look in the network database for the current data.
{%- endtrans %}</p>
<p>{% trans peerselection=site_url('docs/how/peer-selection') -%}
To deal with a wide range of attacks, I2P is fully distributed with no centralized resources - and
hence there are no directory servers keeping statistics regarding the performance and reliability of
routers within the network. As such, each router must keep and maintain profiles of various routers
and is responsible for selecting appropriate peers to meet the anonymity, performance, and
reliability needs of the users, as described in the <a href="{{ peerselection }}">peer selection</a>
page.
{%- endtrans %}</p>
<p>{% trans cryptography=site_url('docs/how/cryptography'), elgamalaes=site_url('docs/how/elgamal-aes') -%}
The network itself makes use of a significant number of <a href="{{ cryptography }}">cryptographic
techniques and algorithms</a> - a full laundry list includes 2048bit ElGamal encryption, 256bit AES
in CBC mode with PKCS#5 padding, 1024bit DSA signatures, SHA256 hashes, 2048bit Diffie-Hellman
negotiated connections with station to station authentication, and <a href="{{ elgamalaes
}}">ElGamal / AES+SessionTag</a>.
{%- endtrans %}</p>
<p>{% trans -%}
Content sent over I2P is encrypted through three layers garlic encryption (used to verify the
delivery of the message to the recipient), tunnel encryption (all messages passing through a tunnel
is encrypted by the tunnel gateway to the tunnel endpoint), and inter router transport layer
encryption (e.g. the TCP transport uses AES256 with ephemeral keys).
{%- endtrans %}</p>
<p>{% trans -%}
End-to-end (I2CP) encryption (client application to server application) was disabled in I2P release
0.6; end-to-end (garlic) encryption (I2P client router to I2P server router) from Alice's router "a"
to Bob's router "h" remains. Notice the different use of terms! All data from a to h is end-to-end
encrypted, but the I2CP connection between the I2P router and the applications is not end-to-end
encrypted! A and h are the routers of Alice and Bob, while Alice and Bob in following chart are the
applications running atop of I2P.
{%- endtrans %}</p>
<div class="box" style="text-align:center;"><img src="{{ url_for('static', filename='images/endToEndEncryption.png') }}" alt="{% trans %}End to end layered encryption{% endtrans %}" title="{% trans %}End to end layered encryption{% endtrans %}" /></div>
<p>{% trans cryptography=site_url('docs/how/cryptography') -%}
The specific use of these algorithms are outlined <a href="{{ cryptography }}">elsewhere</a>.
{%- endtrans %}</p>
<p>{% trans -%}
The two main mechanisms for allowing people who need strong anonymity to use the network are
explicitly delayed garlic routed messages and more comprehensive tunnels to include support for
pooling and mixing messages. These are currently planned for release 3.0, but garlic routed messages
with no delays and FIFO tunnels are currently in place. Additionally, the 2.0 release will allow
people to set up and operate behind restricted routes (perhaps with trusted peers), as well as the
deployment of more flexible and anonymous transports.
{%- endtrans %}</p>
<p>{% trans netdb=site_url('docs/how/network-database') -%}
Some questions have been raised with regards to the scalability of I2P, and reasonably so. There
will certainly be more analysis over time, but peer lookup and integration should be bounded by
<code>O(log(N))</code> due to the <a href="{{ netdb }}">network database</a>'s algorithm, while end
to end messages should be <code>O(1)</code> (scale free), since messages go out K hops through the
outbound tunnel and another K hops through the inbound tunnel, with K no longer than 3. The size of
the network (N) bears no impact.
{%- endtrans %}</p>
<h2>{% trans %}When?{% endtrans %}</h2>
<p>{% trans roadmap=site_url('get-involved/roadmap'),
jms='http://www.oracle.com/technetwork/java/jms/index.html' -%}
I2P initially began in Feb 2003 as a proposed modification to <a
href="http://freenetproject.org">Freenet</a> to allow it to use alternate transports, such as <a
href="{{ jms }}">JMS</a>, then grew into its own as an
'anonCommFramework' in April 2003, turning into I2P in July, with code being written in earnest
starting in August '03. I2P is currently under development, following the <a href="{{ roadmap
}}">roadmap</a>.
{%- endtrans %}</p>
<h2>{% trans %}Who?{% endtrans %}</h2>
<p>{% trans team=site_url('about/team') -%}
We have a small <a href="{{ team }}">team</a> spread around several continents, working to advance
different aspects of the project. We are very open to other developers who want to get involved and
anyone else who would like to contribute in other ways, such as critiques, peer review, testing,
writing I2P enabled applications, or documentation. The entire system is open source - the router
and most of the SDK are outright public domain with some BSD and Cryptix licensed code, while some
applications like I2PTunnel and I2PSnark are GPL. Almost everything is written in Java (1.5+),
though some third party applications are being written in Python and other languages. The code works
on <a href="http://java.com/en/">Sun Java SE</a> and other Java Virtual Machines.
{%- endtrans %}</p>
<h2>{% trans %}Where?{% endtrans %}</h2>
<p>{% trans meetings=get_url('meetings_index') -%}
Anyone interested should join us on the IRC channel #i2p (hosted concurrently on irc.freenode.net,
irc.postman.i2p, irc.freshcoffee.i2p, irc.welterde.i2p and irc.einirc.de). There are currently no
scheduled development meetings, however <a href="{{ meetings }}">archives are available</a>.
{%- endtrans %}</p>
<p>{% trans monotone=site_url('get-involved/guides/monotone') -%}
The current source is available in <a href="{{ monotone }}">monotone</a>.
{%- endtrans %}</p>
<h2>{% trans %}Additional Information{% endtrans %}</h2>
<p>{% trans docs=site_url('docs') -%}
See <a href="{{ docs }}">the Index to Technical Documentation</a>.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,837 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}The Network Database{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}June 2013{% endtrans %}{% endblock %}
{% block accuratefor %}0.9.6{% endblock %}
{% block content %}
<h2>{% trans %}Overview{% endtrans %}</h2>
<p>{% trans -%}
I2P's netDb is a specialized distributed database, containing
just two types of data - router contact information (<b>RouterInfos</b>) and destination contact
information (<b>LeaseSets</b>). Each piece of data is signed by the appropriate party and verified
by anyone who uses or stores it. In addition, the data has liveliness information
within it, allowing irrelevant entries to be dropped, newer entries to replace
older ones, and protection against certain classes of attack.
{%- endtrans %}</p>
<p>{% trans -%}
The netDb is distributed with a simple technique called "floodfill",
where a subset of all routers, called "floodfill routers", maintains the distributed database.
{%- endtrans %}</p>
<h2 id="routerInfo">RouterInfo</h2>
<p>{% trans -%}
When an I2P router wants to contact another router, they need to know some
key pieces of data - all of which are bundled up and signed by the router into
a structure called the "RouterInfo", which is distributed with the SHA256 of the router's identity
as the key. The structure itself contains:
{%- endtrans %}</p>
<ul>
<li>{% trans %}The router's identity (a 2048bit ElGamal encryption key, a 1024bit DSA signing key, and a certificate){% endtrans %}</li>
<li>{% trans %}The contact addresses at which it can be reached (e.g. TCP: example.org port 4108){% endtrans %}</li>
<li>{% trans %}When this was published{% endtrans %}</li>
<li>{% trans %}A set of arbitrary text options{% endtrans %}</li>
<li>{% trans %}The signature of the above, generated by the identity's DSA signing key{% endtrans %}</li>
</ul>
<p>{% trans -%}
The following text options, while not strictly required, are expected
to be present:
{%- endtrans %}</p>
<ul>
<li><b>caps</b>
({% trans %}Capabilities flags - used to indicate floodfill participation, approximate bandwidth, and perceived reachability{% endtrans %})
</li>
<li><b>coreVersion</b>
({% trans %}The core library version, always the same as the router version{% endtrans %})
</li>
<li><b>netId</b> = 2
({% trans %}Basic network compatibility - A router will refuse to communicate with a peer having a different netId{% endtrans %})
</li>
<li><b>router.version</b>
({% trans %}Used to determine compatibility with newer features and messages{% endtrans %})
</li>
<li><b>stat_uptime</b> = 90m
({% trans %}Always sent as 90m, for compatibility with an older scheme where routers published their actual uptime,
and only sent tunnel requests to peers whose was more than 60m{% endtrans %})
</li>
</ul>
<p>{% trans -%}
These values are used by other routers for basic decisions.
Should we connect to this router? Should we attempt to route a tunnel through this router?
The bandwidth capability flag, in particular, is used only to determine whether
the router meets a minimum threshold for routing tunnels.
Above the minimum threshold, the advertised bandwidth is not used or trusted anywhere
in the router, except for display in the user interface and for debugging and network analysis.
{%- endtrans %}</p>
<p>{% trans stats=i2pconv('stats.i2p') -%}
Additional text options include
a small number of statistics about the router's health, which are aggregated by
sites such as <a href="http://{{ stats }}/">{{ stats }}</a>
for network performance analysis and debugging.
These statistics were chosen to provide data crucial to the developers,
such as tunnel build success rates, while balancing the need for such data
with the side-effects that could result from revealing this data.
Current statistics are limited to:
{%- endtrans %}</p>
<ul>
<li>{% trans %}Client and exploratory tunnel build success, reject, and timeout rates{% endtrans %}
<li>{% trans %}1 hour average number of participating tunnels{% endtrans %}
</ul>
<p>{% trans -%}
The data published can be seen in the router's user interface,
but is not used or trusted within the router.
As the network has matured, we have gradually removed most of the published
statistics to improve anonymity, and we plan to remove more in future releases.
{%- endtrans %}</p>
<p>
<a href="{{ site_url('docs/spec/common-structures') }}#struct_RouterInfo">{% trans %}RouterInfo specification{% endtrans %}</a>
</p>
<p>
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/RouterInfo.html">{% trans %}RouterInfo Javadoc{% endtrans %}</a>
</p>
<h3>{% trans %}RouterInfo Expiration{% endtrans %}</h3>
<p>{% trans -%}
RouterInfos have no set expiration time.
Each router is free to maintain its own local policy to trade off the frequency of RouterInfo lookups
with memory or disk usage.
In the current implementation, there are the following general policies:
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
There is no expiration during the first hour of uptime, as the persistent stored data may be old.
{%- endtrans %}</li>
<li>{% trans -%}
There is no expiration if there are 25 or less RouterInfos.
{%- endtrans %}</li>
<li>{% trans -%}
As the number of local RouterInfos grows, the expiration time shrinks, in an attempt to maintain
a reasonable number RouterInfos. The expiration time with less than 120 routers is 72 hours,
while expiration time with 300 routers is around 30 hours.
{%- endtrans %}</li>
<li>{% trans ssu=site_url('docs/transport/ssu') -%}
RouterInfos containing <a href="{{ ssu }}">SSU</a> introducers expire in about an hour, as
the introducer list expires in about that time.
{%- endtrans %}</li>
<li>{% trans -%}
Floodfills use a short expiration time (1 hour) for all local RouterInfos, as valid RouterInfos will
be frequently republished to them.
{%- endtrans %}</li>
</ul>
<h3>{% trans %}RouterInfo Persistent Storage{% endtrans %}</h3>
<p>{% trans -%}
RouterInfos are periodically written to disk so that they are available after a restart.
{%- endtrans %}</p>
<h2 id="leaseSet">LeaseSet</h2>
<p>{% trans -%}
The second piece of data distributed in the netDb is a "LeaseSet" - documenting
a group of <b>tunnel entry points (leases)</b> for a particular client destination.
Each of these leases specify the following information:
{%- endtrans %}</p>
<ul>
<li>{% trans %}The tunnel gateway router (by specifying its identity){% endtrans %}</li>
<li>{% trans %}The tunnel ID on that router to send messages with (a 4 byte number){% endtrans %}</li>
<li>{% trans %}When that tunnel will expire.{% endtrans %}</li>
</ul>
<p>{% trans -%}
The LeaseSet itself is stored in the netDb under
the key derived from the SHA256 of the destination.
{%- endtrans %}</p>
<p>{% trans -%}
In addition to these leases, the LeaseSet includes:
{%- endtrans %}</p>
<ul>
<li>{% trans %}The destination itself (a 2048bit ElGamal encryption key, 1024bit DSA signing key and a certificate){% endtrans %}</li>
<li>{% trans %}Additional encryption public key: used for end-to-end encryption of garlic messages{% endtrans %}</li>
<li>{% trans %}Additional signing public key: intended for LeaseSet revocation, but is currently unused.{% endtrans %}</li>
<li>{% trans %}Signature of all the LeaseSet data, to make sure the Destination published the LeaseSet.{% endtrans %}</li>
</ul>
<p>
<a href="{{ site_url('docs/spec/common-structures') }}#struct_Lease">{% trans %}Lease specification{% endtrans %}</a>
<br />
<a href="{{ site_url('docs/spec/common-structures') }}#struct_LeaseSet">{% trans %}LeaseSet specification{% endtrans %}</a>
</p>
<p>
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/Lease.html">{% trans %}Lease Javadoc{% endtrans %}</a>
<br />
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/LeaseSet.html">{% trans %}LeaseSet Javadoc{% endtrans %}</a>
</p>
<h3 id="unpublished">{% trans %}Unpublished LeaseSets{% endtrans %}</h3>
<p>{% trans -%}
A LeaseSet for a destination used only for outgoing connections is <i>unpublished</i>.
It is never sent for publication to a floodfill router.
"Client" tunnels, such as those for web browsing and IRC clients, are unpublished.
Servers will still be able to send messages back to those unpublished destinations,
because of <a href="#leaseset_storage_peers">I2NP storage messages</a>.
{%- endtrans %}</p>
<h3 id="revoked">{% trans %}Revoked LeaseSets{% endtrans %}</h3>
<p>{% trans -%}
A LeaseSet may be <i>revoked</i> by publishing a new LeaseSet with zero leases.
Revocations must be signed by the additional signing key in the LeaseSet.
Revocations are not fully implemented, and it is unclear if they have any practical use.
This is the only planned use for that signing key, so it is currently unused.
{%- endtrans %}</p>
<h3 id="encrypted">{% trans %}Encrypted LeaseSets{% endtrans %}</h3>
<p>{% trans -%}
In an <i>encrypted</i> LeaseSet, all Leases are encrypted with a separate DSA key.
The leases may only be decoded, and thus the destination may only be contacted,
by those with the key.
There is no flag or other direct indication that the LeaseSet is encrypted.
Encrypted LeaseSets are not widely used, and it is a topic for future work to
research whether the user interface and implementation of encrypted LeaseSets could be improved.
{%- endtrans %}</p>
<h3>{% trans %}LeaseSet Expiration{% endtrans %}</h3>
<p>{% trans -%}
All Leases (tunnels) are valid for 10 minutes; therefore, a LeaseSet expires
10 minutes after the earliest creation time of all its Leases.
{%- endtrans %}</p>
<h3>{% trans %}LeaseSet Persistent Storage{% endtrans %}</h3>
<p>{% trans -%}
There is no persistent storage of LeaseSet data since they expire so quickly.
{%- endtrans %}</p>
<h2 id="bootstrap">{% trans %}Bootstrapping{% endtrans %}</h2>
<p>{% trans -%}
The netDb is decentralized, however you do need at
least one reference to a peer so that the integration process
ties you in. This is accomplished by "reseeding" your router with the RouterInfo
of an active peer - specifically, by retrieving their <code>routerInfo-$hash.dat</code>
file and storing it in your <code>netDb/</code> directory. Anyone can provide
you with those files - you can even provide them to others by exposing your own
netDb directory. To simplify the process,
volunteers publish their netDb directories (or a subset) on the regular (non-i2p) network,
and the URLs of these directories are hardcoded in I2P.
When the router starts up for the first time, it automatically fetches from
one of these URLs, selected at random.
{%- endtrans %}</p>
<h2 id="floodfill">{% trans %}Floodfill{% endtrans %}</h2>
<p>{% trans -%}
The floodfill netDb is a simple distributed storage mechanism.
The storage algorithm is simple: send the data to the closest peer that has advertised itself
as a floodfill router. Then wait 10 seconds, pick another floodfill router and ask them
for the entry to be sent, verifying its proper insertion / distribution. If the
verification peer doesn't reply, or they don't have the entry, the sender
repeats the process. When the peer in the floodfill netDb receives a netDb
store from a peer not in the floodfill netDb, they send it to a subset of the floodfill netDb-peers.
The peers selected are the ones closest (according to the <a href="#kademlia_closeness">XOR-metric</a>) to a specific key.
{%- endtrans %}</p>
<p>{% trans -%}
Determining who is part of the floodfill netDb is trivial - it is exposed in each
router's published routerInfo as a capability.
{%- endtrans %}</p>
<p>{% trans -%}
Floodfills have no central authority and do not form a "consensus" -
they only implement a simple DHT overlay.
{%- endtrans %}</p>
<h3 id="opt-in">{% trans %}Floodfill Router Opt-in{% endtrans %}</h3>
<p>{% trans -%}
Unlike Tor, where the directory servers are hardcoded and trusted,
and operated by known entities,
the members of the I2P floodfill peer set need not be trusted, and
change over time.
{%- endtrans %}</p>
<p>{% trans -%}
To increase reliability of the netDb, and minimize the impact
of netDb traffic on a router, floodfill is automatically enabled
only on routers that are configured with high bandwidth limits.
Routers with high bandwidth limits (which must be manually configured,
as the default is much lower) are presumed to be on lower-latency
connections, and are more likely to be available 24/7.
The current minimum share bandwidth for a floodfill router is 128 KBytes/sec.
{%- endtrans %}</p>
<p>{% trans -%}
In addition, a router must pass several additional tests for health
(outbound message queue time, job lag, etc.) before floodfill operation is
automatically enabled.
{%- endtrans %}</p>
<p>{% trans -%}
With the current rules for automatic opt-in, approximately 6&#37; of
the routers in the network are floodfill routers.
{%- endtrans %}</p>
<p>{% trans -%}
While some peers are manually configured to be floodfill,
others are simply high-bandwidth routers who automatically volunteer
when the number of floodfill peers drops below a threshold.
This prevents any long-term network damage from losing most or all
floodfills to an attack.
In turn, these peers will un-floodfill themselves when there are
too many floodfills outstanding.
{%- endtrans %}</p>
<h3>{% trans %}Floodfill Router Roles{% endtrans %}</h3>
<p>{% trans -%}
A floodfill router's only services that are in addition to those of non-floodfill routers
are in accepting netDb stores and responding to netDb queries.
Since they are generally high-bandwidth, they are more likely to participate in a high number of tunnels
(i.e. be a "relay" for others), but this is not directly related to their distributed database services.
{%- endtrans %}</p>
<a name="kademlia_closeness"><h2 id="kad">{% trans %}Kademlia Closeness Metric{% endtrans %}</h2></a>
<p>{% trans -%}
The netDb uses a simple Kademlia-style XOR metric to determine closeness.
The SHA256 hash of the key being looked up or stored is XOR-ed with
the hash of the router in question to determine closeness.
A modification to this algorithm is done to increase the costs of <a href="#sybil-partial">Sybil attacks</a>.
Instead of the SHA256 hash of the key being looked up of stored, the SHA256 hash is taken
of the 32-byte binary key appended with the UTC date represented as an 8-byte ASCII string yyyyMMdd, i.e. SHA256(key + yyyyMMdd).
This is called the "routing key", and it changes every day at midnight UTC.
The daily transformation of the DHT is sometimes called "keyspace rotation",
although it isn't strictly a rotation.
{%- endtrans %}</p>
<p>{% trans -%}
Routing keys are never sent on-the-wire in any I2NP message, they are only used locally for
determination of distance.
{%- endtrans %}</p>
<h2 id="delivery">{% trans %}Storage, Verification, and Lookup Mechanics{% endtrans %}</h2>
<h3>{% trans %}RouterInfo Storage to Peers{% endtrans %}</h3>
<p>{% trans i2np=site_url('docs/protocol/i2np'), ntcp=site_url('docs/transport/ntcp'), ssu=site_url('docs/transport/ssu') -%}
<a href="{{ i2np }}">I2NP</a> DatabaseStoreMessages containing the local RouterInfo are exchanged with peers
as a part of the initialization of a <a href="{{ ntcp }}">NTCP</a>
or <a href="{{ ssu }}">SSU</a> transport connection.
{%- endtrans %}</p>
<a name="leaseset_storage_peers"><h3>{% trans %}LeaseSet Storage to Peers{% endtrans %}</h3></a>
<p>{% trans i2np=site_url('docs/protocol/i2np') -%}
<a href="{{ i2np }}">I2NP</a> DatabaseStoreMessages containing the local LeaseSet are periodically exchanged with peers
by bundling them in a garlic message along with normal traffic from the related Destination.
This allows an initial response, and later responses, to be sent to an appropriate Lease,
without requiring any LeaseSet lookups, or requiring the communicating Destinations to have published LeaseSets at all.
{%- endtrans %}</p>
<h3>Floodfill Selection</h3>
<p>{% trans -%}
The DatabaseStoreMessage should be sent to the floodfill that is closest
to the current routing key for the RouterInfo or LeaseSet being stored.
Currently, the closest floodfill is found by a search in the local database.
Even if that floodfill is not actually closest, it will flood it "closer" by
sending it to multiple other floodfills.
This provides a high degree of fault-tolerance.
{%- endtrans %}</p>
<p>{% trans -%}
In traditional Kademlia, a peer would do a "find-closest" search before inserting
an item in the DHT to the closest target. As the verify operation will tend to
discover closer floodfills if they are present, a router will quickly improve
its knowledge of the DHT "neighborhood" for the RouterInfo and LeaseSets it regularly publishes.
While I2NP does not define a "find-closest" message, if it becomes necessary,
a router may simply do an iterative search for a key with the least significant bit flipped
(i.e. key ^ 0x01) until no closer peers are received in the DatabaseSearchReplyMessages.
This ensures that the true closest peer will be found even if a more-distant peer had
the netdb item.
{%- endtrans %}</p>
<h3>{% trans %}RouterInfo Storage to Floodfills{% endtrans %}</h3>
<p>{% trans i2np=site_url('docs/protocol/i2np') -%}
A router publishes its own RouterInfo by directly connecting to a floodfill router
and sending it a <a href="{{ i2np }}">I2NP</a> DatabaseStoreMessage
with a nonzero Reply Token. The message is not end-to-end garlic encrypted,
as this is a direct connection, so there are no intervening routers
(and no need to hide this data anyway).
The floodfill router replies with a
<a href="{{ i2np }}">I2NP</a> DeliveryStatusMessage,
with the Message ID set to the value of the Reply Token.
{%- endtrans %}</p>
<h3>{% trans %}LeaseSet Storage to Floodfills{% endtrans %}</h3>
<p>{% trans -%}
Storage of LeaseSets is much more sensitive than for RouterInfos, as a router
must take care that the LeaseSet cannot be associated with the router.
{%- endtrans %}</p>
<p>{% trans i2np=site_url('docs/protocol/i2np') -%}
A router publishes a local LeaseSet by
sending a <a href="{{ i2np }}">I2NP</a> DatabaseStoreMessage
with a nonzero Reply Token over an outbound client tunnel for that Destination.
The message is end-to-end garlic encrypted using the Destination's Session Key Manager,
to hide the message from the tunnel's outbound endpoint.
The floodfill router replies with a
<a href="{{ i2np }}">I2NP</a> DeliveryStatusMessage,
with the Message ID set to the value of the Reply Token.
This message is sent back to one of the client's inbound tunnels.
{%- endtrans %}</p>
<h3>{% trans %}Flooding{% endtrans %}</h3>
<p>{% trans -%}
After a floodfill router receives a DatabaseStoreMessage containing a
valid RouterInfo or LeaseSet which is newer than that previously stored in its
local NetDb, it "floods" it.
To flood a NetDb entry, it looks up several (currently 4) floodfill routers closest to the routing key
of the NetDb entry. (The routing key is the SHA256 Hash of the RouterIdentity or Destination with the date (yyyyMMdd) appended.)
By flooding to those closest to the key, not closest to itself, the floodfill ensures that the storage
gets to the right place, even if the storing router did not have good knowledge of the
DHT "neighborhood" for the routing key.
{%- endtrans %}</p>
<p>{% trans i2np=site_url('docs/protocol/i2np') -%}
The floodfill then directly connects to each of those peers
and sends it a <a href="{{ i2np }}">I2NP</a> DatabaseStoreMessage
with a zero Reply Token. The message is not end-to-end garlic encrypted,
as this is a direct connection, so there are no intervening routers
(and no need to hide this data anyway).
The other routers do not reply or re-flood, as the Reply Token is zero.
{%- endtrans %}</p>
<h3 id="lookup">{% trans %}RouterInfo and LeaseSet Lookup{% endtrans %}</h3>
<p>{% trans i2np=site_url('docs/protocol/i2np') -%}
The <a href="{{ i2np }}">I2NP</a> DatabaseLookupMessage is used to request a netdb entry from a floodfill router.
Lookups are sent out one of the router's outbound exploratory tunnels.
The replies are specified to return via one of the router's inbound exploratory tunnels.
{%- endtrans %}</p>
<p>{% trans -%}
Lookups are generally sent to the two "good" (the connection doesn't fail) floodfill routers closest to the requested key, in parallel.
{%- endtrans %}</p>
<p>{% trans i2np=site_url('docs/protocol/i2np') -%}
If the key is found locally by the floodfill router, it responds with a
<a href="{{ i2np }}">I2NP</a> DatabaseStoreMessage.
If the key is not found locally by the floodfill router, it responds with a
<a href="{{ i2np }}">I2NP</a> DatabaseSearchReplyMessage
containing a list of other floodfill routers close to the key.
{%- endtrans %}</p>
<p>{% trans -%}
LeaseSet lookups are garlic encrypted end-to-end as of release 0.9.5.
RouterInfo lookups are not encrypted and thus are vulnerable to snooping by the outbound endpoint
(OBEP) of the client tunnel. This is due to the expense of the ElGamal encryption.
RouterInfo lookup encryption may be enabled in a future release.
{%- endtrans %}</p>
<p>{% trans -%}
As of release 0.9.7, replies to a LeaseSet lookup (a DatabaseStoreMessage or a DatabaseSearchReplyMessage)
will be encrypted by including the session key and tag in the lookup.
This hides the reply from the inbound gateway (IBGW) of the reply tunnel.
Responses to RouterInfo lookups will be encrypted if we enable the lookup encryption.
{%- endtrans %}</p>
<p>{% trans pdf='http://www-users.cs.umn.edu/~hopper/hashing_it_out.pdf' -%}
(Reference: <a href="{{ pdf }}">Hashing it out in Public</a> Sections 2.2-2.3 for terms below in italics)
{%- endtrans %}</p>
<p>{% trans -%}
Due to the relatively small size of the network and the flooding redundancy of 8x,
lookups are usually O(1) rather than O(log n) --
a router is highly likely to know a floodfill router close enough to the key to get the answer on the first try.
In releases prior to 0.8.9, routers used a lookup redundancy of two
(that is, two lookups were performed in parallel to different peers), and
neither <i>recursive</i> nor <i>iterative</i> routing for lookups was implemented.
Queries were sent through <i>multiple routes simultaneously</i>
to <i>reduce the chance of query failure</i>.
{%- endtrans %}</p>
<p>{% trans -%}
As of release 0.8.9, <i>iterative lookups</i> are implemented with no lookup redundancy.
This is a more efficient and reliable lookup that will work much better
when not all floodfill peers are known, and it removes a serious
limitation to network growth. As the network grows and each router knows only a small
subset of the floodfill peers, lookups will become O(log n).
Even if the peer does not return references closer to the key, the lookup continues with
the next-closest peer, for added robustness, and to prevent a malicious floodfill from
black-holing a part of the key space. Lookups continue until a total lookup timeout is reached,
or the maximum number of peers is queried.
{%- endtrans %}</p>
<p>{% trans -%}
<i>Node IDs</i> are <i>verifiable</i> in that we use the router hash directly as both the node ID and the Kademlia key.
Incorrect responses that are not closer to the search key are generally ignored.
Given the current size of the network, a router has
<i>detailed knowledge of the neighborhood of the destination ID space</i>.
{%- endtrans %}</p>
<h3>{% trans %}RouterInfo Storage Verification{% endtrans %}</h3>
<p>{% trans -%}
To verify a storage was successful, a router simply waits about 10 seconds,
then sends a lookup to another floodfill router close to the key
(but not the one the store was sent to).
Lookups sent out one of the router's outbound exploratory tunnels.
Lookups are end-to-end garlic encrypted to prevent snooping by the outbound endpoint(OBEP).
{%- endtrans %}</p>
<h3>{% trans %}LeaseSet Storage Verification{% endtrans %}</h3>
<p>{% trans -%}
To verify a storage was successful, a router simply waits about 10 seconds,
then sends a lookup to another floodfill router close to the key
(but not the one the store was sent to).
Lookups sent out one of the outbound client tunnels for the destination of the LeaseSet being verified.
To prevent snooping by the OBEP of the outbound tunnel,
lookups are end-to-end garlic encrypted.
The replies are specified to return via one of the client's inbound tunnels.
{%- endtrans %}</p>
<p>{% trans -%}
As of release 0.9.7, replies for both RouterInfo and LeaseSet lookups (a DatabaseStoreMessage or a DatabaseSearchReplyMessage)
will be encrypted,
to hide the reply from the inbound gateway (IBGW) of the reply tunnel.
{%- endtrans %}</p>
<h3>{% trans %}Exploration{% endtrans %}</h3>
<p>{% trans i2np=site_url('docs/protocol/i2np') -%}
<i>Exploration</i> is a special form of netdb lookup, where a router attempts to learn about
new routers.
It does this by sending a floodfill router a <a href="{{ i2np }}">I2NP</a> DatabaseLookupMessage, looking for a random key.
As this lookup will fail, the floodfill would normally respond with a
<a href="{{ i2np }}">I2NP</a> DatabaseSearchReplyMessage containing hashes of floodfill routers close to the key.
This would not be helpful, as the requesting router probably already knows those floodfills,
and it would be impractical to add ALL floodfill routers to the "don't include" field of the lookup.
For an exploration query, the requesting router adds a router hash of all zeros to the
"don't include" field of the DatabaseLookupMessage.
The floodfill will then respond only with non-floodfill routers close to the requested key.
{%- endtrans %}</p>
<h3>{% trans %}Notes on Lookup Responses{% endtrans %}</h3>
<p>{% trans -%}
The response to a lookup request is either a Database Store Message (on success) or a
Database Search Reply Message (on failure). The DSRM contains a 'from' router hash field
to indicate the source of the reply; the DSM does not.
The DSRM 'from' field is unauthenticated and may be spoofed or invalid.
There are no other response tags. Therefore, when making multiple requests in parallel, it is
difficult to monitor the performance of the various floodfill routers.
{%- endtrans %}</p>
<h2 id="multihome">{% trans %}MultiHoming{% endtrans %}</h2>
<p>{% trans -%}
Destinations may be hosted on multiple routers simultaneously, by using the same
private and public keys (traditionally stored in eepPriv.dat files).
As both instances will periodically publish their signed LeaseSets to the floodfill peers,
the most recently published LeaseSet will be returned to a peer requesting a database lookup.
As LeaseSets have (at most) a 10 minute lifetime, should a particular instance go down,
the outage will be 10 minutes at most, and generally much less than that.
The multihoming function has been verified and is in use by several services on the network.
{%- endtrans %}</p>
<h2 id="threat">{% trans %}Threat Analysis{% endtrans %}</h2>
<p>{% trans threatmodel=site_url('docs/how/threat-model') -%}
Also discussed on <a href="{{ threatmodel }}#floodfill">the threat model page</a>.
{%- endtrans %}</p>
<p>{% trans -%}
A hostile user may attempt to harm the network by
creating one or more floodfill routers and crafting them to offer
bad, slow, or no responses.
Some scenarios are discussed below.
{%- endtrans %}</p>
<h3>{% trans %}General Mitigation Through Growth{% endtrans %}</h3>
<p>{% trans -%}
There are currently hundreds of floodfill routers in the network.
Most of the following attacks will become more difficult, or have less impact,
as the network size and number of floodfill routers increase.
{%- endtrans %}</p>
<h3>{% trans %}General Mitigation Through Redundancy{% endtrans %}</h3>
<p>{% trans -%}
Via flooding, all netdb entries are stored on the 8 floodfill routers closest to the key.
{%- endtrans %}</p>
<h3>{% trans %}Forgeries{% endtrans %}</h3>
<p>{% trans -%}
All netdb entries are signed by their creators, so no router may forge a
RouterInfo or LeaseSet.
{%- endtrans %}</p>
<h3>{% trans %}Slow or Unresponsive{% endtrans %}</h3>
<p>{% trans peerselection=site_url('docs/how/peer-selection') -%}
Each router maintains an expanded set of statistics in the
<a href="{{ peerselection }}">peer profile</a> for each floodfill router,
covering various quality metrics for that peer.
The set includes:
{%- endtrans %}</p>
<ul>
<li>{% trans %}Average response time{% endtrans %}</li>
<li>{% trans %}Percentage of queries answered with the data requested{% endtrans %}</li>
<li>{% trans %}Percentage of stores that were successfully verified{% endtrans %}</li>
<li>{% trans %}Last successful store{% endtrans %}</li>
<li>{% trans %}Last successful lookup{% endtrans %}</li>
<li>{% trans %}Last response{% endtrans %}</li>
</ul>
<p>{% trans -%}
Each time a router needs to make a determination on which floodfill router is closest to a key,
it uses these metrics to determine which floodfill routers are "good".
The methods, and thresholds, used to determine "goodness" are relatively new, and
are subject to further analysis and improvement.
While a completely unresponsive router will quickly be identified and avoided,
routers that are only sometimes malicious may be much harder to deal with.
{%- endtrans %}</p>
<h3 id="sybil">{% trans %}Sybil Attack (Full Keyspace){% endtrans %}</h3>
<p>{% trans url='http://citeseer.ist.psu.edu/douceur02sybil.html' -%}
An attacker may mount a <a href="{{ url }}">Sybil attack</a>
by creating a large number of floodfill routers spread throughout the keyspace.
{%- endtrans %}</p>
<p>{% trans url='http://blog.torproject.org/blog/june-2010-progress-report' -%}
(In a related example, a researcher recently created a
<a href="{{ url }}">large number of Tor relays</a>.)
If successful, this could be an effective DOS attack on the entire network.
{%- endtrans %}</p>
<p>{% trans -%}
If the floodfills are not sufficiently misbehaving to be marked as "bad" using the peer profile
metrics described above, this is a difficult scenario to handle.
Tor's response can be much more nimble in the relay case, as the suspicious relays
can be manually removed from the consensus.
Some possible responses for the I2P network are listed below, however none of them is completely satisfactory:
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
Compile a list of bad router hashes or IPs, and announce the list through various means
(console news, website, forum, etc.); users would have to manually download the list and
add it to their local "blacklist".
{%- endtrans %}</li>
<li>{% trans %}Ask everyone in the network to enable floodfill manually (fight Sybil with more Sybil){% endtrans %}</li>
<li>{% trans %}Release a new software version that includes the hardcoded "bad" list{% endtrans %}</li>
<li>{% trans -%}
Release a new software version that improves the peer profile metrics and thresholds,
in an attempt to automatically identify the "bad" peers.
{%- endtrans %}</li>
<li>{% trans %}Add software that disqualifies floodfills if too many of them are in a single IP block{% endtrans %}</li>
<li>{% trans -%}
Implement an automatic subscription-based blacklist controlled by a single individual or group.
This would essentially implement a portion of the Tor "consensus" model.
Unfortunately it would also give a single individual or group the power to
block participation of any particular router or IP in the network,
or even to completely shutdown or destroy the entire network.
{%- endtrans %}</li>
</ul>
<p>{% trans -%}
This attack becomes more difficult as the network size grows.
{%- endtrans %}</p>
<h3 id="sybil-partial">{% trans %}Sybil Attack (Partial Keyspace){% endtrans %}</h3>
<p>{% trans url='http://citeseer.ist.psu.edu/douceur02sybil.html' -%}
An attacker may mount a <a href="{{ url }}">Sybil attack</a>
by creating a small number (8-15) of floodfill routers clustered closely in the keyspace,
and distribute the RouterInfos for these routers widely.
Then, all lookups and stores for a key in that keyspace would be directed
to one of the attacker's routers.
If successful, this could be an effective DOS attack on a particular eepsite, for example.
{%- endtrans %}</p>
<p>{% trans -%}
As the keyspace is indexed by the cryptographic (SHA256) Hash of the key,
an attacker must use a brute-force method to repeatedly generate router hashes
until he has enough that are sufficiently close to the key.
The amount of computational power required for this, which is dependent on network
size, is unknown.
{%- endtrans %}</p>
<p>{% trans -%}
As a partial defense against this attack,
the algorithm used to determine Kademlia "closeness" varies over time.
Rather than using the Hash of the key (i.e. H(k)) to determine closeness,
we use the Hash of the key appended with the current date string, i.e. H(k + YYYYMMDD).
A function called the "routing key generator" does this, which transforms the original key into a "routing key".
In other words, the entire netdb keyspace "rotates" every day at UTC midnight.
Any partial-keyspace attack would have to be regenerated every day, for
after the rotation, the attacking routers would no longer be close
to the target key, or to each other.
{%- endtrans %}</p>
<p>{% trans -%}
This attack becomes more difficult as the network size grows.
However, recent research demonstrates that the keyspace rotation is not particularly effective.
An attacker can precompute numerous router hashes in advance,
and only a few routers are sufficient to "eclipse" a portion
of the keyspace within a half hour after rotation.
{%- endtrans %}</p>
<p>{% trans -%}
One consequence of daily keyspace rotation is that the distributed network database
may become unreliable for a few minutes after the rotation --
lookups will fail because the new "closest" router has not received a store yet.
The extent of the issue, and methods for mitigation
(for example netdb "handoffs" at midnight)
are a topic for further study.
{%- endtrans %}</p>
<h3>{% trans %}Bootstrap Attacks{% endtrans %}</h3>
<p>{% trans -%}
An attacker could attempt to boot new routers into an isolated
or majority-controlled network by taking over a reseed website,
or tricking the developers into adding his reseed website
to the hardcoded list in the router.
{%- endtrans %}</p>
<p>{% trans -%}
Several defenses are possible, and most of these are planned:
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
Disallow fallback from HTTPS to HTTP for reseeding.
A MITM attacker could simply block HTTPS, then respond to the HTTP.
{%- endtrans %}</li>
<li>{% trans -%}
Changing the reseed task to fetch a subset of RouterInfos from
each of several reseed sites rather than using only a single site
{%- endtrans %}</li>
<li>{% trans -%}
Creating an out-of-network reseed monitoring service that
periodically polls reseed websites and verifies that the
data are not stale or inconsistent with other views of the network
{%- endtrans %}</li>
<li>{% trans %}Bundling reseed data in the installer{% endtrans %}</li>
</ul>
<h3>{% trans %}Query Capture{% endtrans %}</h3>
<p>{% trans pdf='http://www-users.cs.umn.edu/~hopper/hashing_it_out.pdf' -%}
See also <a href="#lookup">lookup</a>
(Reference: <a href="{{ pdf }}">Hashing it out in Public</a> Sections 2.2-2.3 for terms below in italics)
{%- endtrans %}</p>
<p>{% trans -%}
Similar to a bootstrap attack, an attacker using a floodfill router could attempt to "steer"
peers to a subset of routers controlled by him by returning their references.
{%- endtrans %}</p>
<p>{% trans -%}
This is unlikely to work via exploration, because exploration is a low-frequency task.
Routers acquire a majority of their peer references through normal tunnel building activity.
Exploration results are generally limited to a few router hashes,
and each exploration query is directed to a random floodfill router.
{%- endtrans %}</p>
<p>{% trans i2np=site_url('docs/protocol/i2np'),
pdf='http://www-users.cs.umn.edu/~hopper/hashing_it_out.pdf' -%}
As of release 0.8.9, <i>iterative lookups</i> are implemented.
For floodfill router references returned in a
<a href="{{ i2np }}">I2NP</a> DatabaseSearchReplyMessage
response to a lookup,
these references are followed if they are closer (or the next closest) to the lookup key.
The requesting router does not trust that the references are
closer to the key (i.e. they are <i>verifiably correct</i>.
The lookup also does not stop when no closer key is found, but continues by querying the
next-closet node, until the timeout or maximum number of queries is reached.
This prevents a malicious floodfill from black-holing a part of the key space.
Also, the daily keyspace rotation requires an attacker to regenerate a router info
within the desired key space region.
This design ensures that the query capture attack described in
<a href="{{ pdf }}">Hashing it out in Public</a>
is much more difficult.
{%- endtrans %}</p>
<h3>{% trans %}DHT-Based Relay Selection{% endtrans %}</h3>
<p>{% trans pdf='http://www-users.cs.umn.edu/~hopper/hashing_it_out.pdf' -%}
(Reference: <a href="{{ pdf }}">Hashing it out in Public</a> Section 3)
{%- endtrans %}</p>
<p>{% trans peerselection=site_url('docs/how/peer-selection') -%}
This doesn't have much to do with floodfill, but see
the <a href="{{ peerselection }}">peer selection page</a>
for a discussion of the vulnerabilities of peer selection for tunnels.
{%- endtrans %}</p>
<h3>{% trans %}Information Leaks{% endtrans %}</h3>
<p>{% trans pdf='http://www.eecs.berkeley.edu/~pmittal/publications/nisan-torsk-ccs10.pdf' -%}
(Reference: <a href="{{ pdf }}">In Search of an Anonymous and Secure Lookup</a> Section 3)
{%- endtrans %}</p>
<p>{% trans peerselection=site_url('docs/how/peer-selection'),
tunnelrouting=site_url('docs/how/tunnel-routing') -%}
This paper addresses weaknesses in the "Finger Table" DHT lookups used by Torsk and NISAN.
At first glance, these do not appear to apply to I2P. First, the use of DHT by Torsk and NISAN
is significantly different from that in I2P. Second, I2P's network database lookups are only
loosely correlated to the <a href="{{ peerselection }}">peer selection</a> and
<a href="{{ tunnelrouting }}">tunnel building</a> processes; only previously-known peers
are used for tunnels.
Also, peer selection is unrelated to any notion of DHT key-closeness.
{%- endtrans %}</p>
<p>{% trans -%}
Some of this may actually be more interesting when the I2P network gets much larger.
Right now, each router knows a large proportion of the network, so looking up a particular
Router Info in the network database is not strongly indicative of a future intent to use
that router in a tunnel. Perhaps when the network is 100 times larger, the lookup may be
more correlative. Of course, a larger network makes a Sybil attack that much harder.
{%- endtrans %}</p>
<p>{% trans threatmodel=site_url('docs/how/threat-model') -%}
However, the general issue of DHT information leakage in I2P needs further investigation.
The floodfill routers are in a position to observe queries and gather information.
Certainly, at a level of <i>f</i> = 0.2 (20&#37; malicious nodes, as specifed in the paper)
we expect that many of the Sybil threats we describe
(<a href="{{ threatmodel }}#sybil">here</a>,
<a href="#sybil">here</a> and
<a href="#sybil-partial">here</a>)
become problematic for several reasons.
{%- endtrans %}</p>
<h2 id="history">{% trans %}History{% endtrans %}</h2>
<p>
<a href="{{ site_url('docs/discussions/netdb') }}">{% trans %}Moved to the netdb discussion page{% endtrans %}</a>.
</p>
<h2 id="future">{% trans %}Future Work{% endtrans %}</h2>
<p>{% trans -%}
End-to-end encryption of additional netDb lookups and responses.
{%- endtrans %}</p>
<p>{% trans -%}
Better methods for tracking lookup responses.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,312 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Peer Profiling and Selection{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}July 2010{% endtrans %}{% endblock %}
{% block accuratefor %}0.8{% endblock %}
{% block content %}
<h2>{% trans %}Overview{% endtrans %}</h2>
<h3>{% trans %}Peer Profiling{% endtrans %}</h3>
<p>{% trans netdb=site_url('docs/how/network-database') -%}
<b>Peer profiling</b> is the process of collecting data based on the <b>observed</b> performance
of other routers or peers, and classifying those peers into groups.
Profiling does <b>not</b> use any claimed performance data published by the peer itself
in the <a href="{{ netdb }}">network database</a>.
{%- endtrans %}</p>
<p>{% trans %}Profiles are used for two purposes:{% endtrans %}</p>
<ol>
<li>{% trans %}Selecting peers to relay our traffic through, which is discussed below{% endtrans %}</li>
<li>{% trans netdb=site_url('docs/how/network-database') -%}
Choosing peers from the set of floodfill routers to use for network database storage and queries,
which is discussed on the <a href="{{ netdb }}">network database</a> page
{%- endtrans %}</li>
</ol>
<h3>{% trans %}Peer Selection{% endtrans %}</h3>
<p>{% trans -%}
<b>Peer selection</b> is the process of choosing which routers
on the network we want to relay our messages to go through (which peers will we
ask to join our tunnels). To accomplish this, we keep track of how each
peer performs (the peer's "profile") and use that data to estimate how
fast they are, how often they will be able to accept our requests, and
whether they seem to be overloaded or otherwise unable to perform what
they agree to reliably.
{%- endtrans %}</p>
<p>{% trans threatmodel=site_url('docs/how/threat-model') -%}
Unlike some other anonymous networks, in I2P,
claimed bandwidth is untrusted and is <b>only</b> used to avoid those peers
advertising very low bandwidth insufficient for routing tunnels.
All peer selection is done through profiling.
This prevents simple attacks based on peers claiming high bandwidth
in order to capture large numbers of tunnels.
It also makes
<a href="{{ threatmodel }}#timing">timing attacks</a>
more difficult.
{%- endtrans %}</p>
<p>{% trans -%}
Peer selection is done quite frequently, as a router may maintain a large number
of client and exploratory tunnels, and a tunnel lifetime is only 10 minutes.
{%- endtrans %}</p>
<h3>{% trans %}Further Information{% endtrans %}</h3>
<p>{% trans pdf=url_for('static', filename='pdf/I2P-PET-CON-2009.1.pdf'),
url='http://web.archive.org/web/20100413184504/http://www.pet-con.org/index.php/PET_Convention_2009.1' -%}
For more information see the paper
<a href="{{ pdf }}">Peer Profiling and Selection in the I2P Anonymous Network</a>
presented at <a href="{{ url }}">PET-CON 2009.1</a>.
See <a href="#notes">below</a> for notes on minor changes since the paper was published.
{%- endtrans %}</p>
<h2>{% trans %}Profiles{% endtrans %}</h2>
<p>{% trans url='http://docs.i2p-projekt.de/javadoc/net/i2p/router/peermanager/PeerProfile.html' -%}
Each peer has a set of data points collected about them, including statistics
about how long it takes for them to reply to a network database query, how
often their tunnels fail, and how many new peers they are able to introduce
us to, as well as simple data points such as when we last heard from them or
when the last communication error occurred. The specific data points gathered
can be found in the <a href="{{ url }}">code</a>.
{%- endtrans %}</p>
<p>{% trans -%}
Profiles are fairly small, a few KB. To control memory usage, the profile expiration time
lessens as the number of profiles grows.
Profiles are kept in memory until router shutdown, when they are written to disk.
At startup, the profiles are read so the router need not reinitialize all profiles,
thus allowing a router to quickly re-integrate into the network after startup.
{%- endtrans %}</p>
<h2>{% trans %}Peer Summaries{% endtrans %}</h2>
<p>{% trans -%}
While the profiles themselves can be considered a summary of a peer's
performance, to allow for effective peer selection we break each summary down
into four simple values, representing the peer's speed, its capacity, how well
integrated into the network it is, and whether it is failing.
{%- endtrans %}</p>
<h3>{% trans %}Speed{% endtrans %}</h3>
<p>{% trans -%}
The speed calculation
simply goes through the profile and estimates how much data we can
send or receive on a single tunnel through the peer in a minute. For this estimate it just looks at
performance in the previous minute.
{%- endtrans %}</p>
<h3 id="capacity">{% trans %}Capacity{% endtrans %}</h3>
<p>{% trans -%}
The capacity calculation
simply goes through the profile and estimates how many tunnels the peer
would agree to participate in over a given time period. For this estimate it looks at
how many tunnel build requests
the peer has accepted, rejected, and dropped, and how many
of the agreed-to tunnels later failed.
While the calculation is time-weighted so that recent activity counts more than later activity,
statistics up to 48 hours old may be included.
{%- endtrans %}</p>
<p>{% trans -%}
Recognizing and avoiding unreliable and unreachable
peers is critically important.
Unfortunately, as the tunnel building and testing require the participation of several peers,
it is difficult to positively identify the cause of a dropped build request or test failure.
The router assigns a probability of failure to each of the
peers, and uses that probability in the capacity calculation.
Drops and test failures are weighted much higher than rejections.
{%- endtrans %}</p>
<h2>{% trans %}Peer organization{% endtrans %}</h2>
<p>{% trans -%}
As mentioned above, we drill through each peer's profile to come up with a
few key calculations, and based upon those, we organize each peer into three
groups - fast, high capacity, and standard.
{%- endtrans %}</p>
<p>{% trans -%}
The groupings are not mutually exclusive, nor are they unrelated:
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
A peer is considered "high capacity" if its capacity calculation meets or
exceeds the median of all peers.
{%- endtrans %}</li>
<li>{% trans -%}
A peer is considered "fast" if they are already "high capacity" and their
speed calculation meets or exceeds the median of all peers.
{%- endtrans %}</li>
<li>{% trans %}A peer is considered "standard" if it is not "high capacity"{% endtrans %}</li>
</ul>
<p>{% trans url='http://docs.i2p-projekt.de/javadoc/net/i2p/router/peermanager/ProfileOrganizer.html' -%}
These groupings are implemented in the router's
<a href="{{ url }}">ProfileOrganizer</a>.
{%- endtrans %}</p>
<h3>{% trans %}Group size limits{% endtrans %}</h3>
<p>{% trans -%}
The size of the groups may be limited.
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
The fast group is limited to 30 peers.
If there would be more, only the ones with the highest speed rating are placed in the group.
{%- endtrans %}</li>
<li>{% trans -%}
The high capacity group is limited to 75 peers (including the fast group)
If there would be more, only the ones with the highest capacity rating are placed in the group.
{%- endtrans %}</li>
<li>{% trans -%}
The standard group has no fixed limit, but is somewhat smaller than the number of RouterInfos
stored in the local network database.
On an active router in today's network, there may be about 1000 RouterInfos and 500 peer profiles
(including those in the fast and high capacity groups)
{%- endtrans %}</li>
</ul>
<h2>{% trans %}Recalculation and Stability{% endtrans %}</h2>
<p>{% trans -%}
Summaries are recalculated, and peers are resorted into groups, every 45 seconds.
{%- endtrans %}</p>
<p>{% trans -%}
The groups tend to be fairly stable, that is, there is not much "churn" in the rankings
at each recalculation.
Peers in the fast and high capacity groups get more tunnels build through them, which increases their speed and capacity ratings,
which reinforces their presence in the group.
{%- endtrans %}</p>
<h2>{% trans %}Peer Selection{% endtrans %}</h2>
<p>{% trans -%}
The router selects peers from the above groups to build tunnels through.
{%- endtrans %}</p>
<h3>{% trans %}Peer Selection for Client Tunnels{% endtrans %}</h3>
<p>{% trans -%}
Client tunnels are used for application traffic, such as for HTTP proxies and web servers.
{%- endtrans %}</p>
<p>{% trans -%}
To reduce the susceptibility to <a href="http://blog.torproject.org/blog/one-cell-enough">some attacks</a>,
and increase performance,
peers for building client tunnels are chosen randomly from the smallest group, which is the "fast" group.
There is no bias toward selecting peers that were previously participants in a tunnel for the same client.
{%- endtrans %}</p>
<h3>{% trans %}Peer Selection for Exploratory Tunnels{% endtrans %}</h3>
<p>{% trans -%}
Exploratory tunnels are used for router administrative purposes, such as network database traffic
and testing client tunnels.
Exploratory tunnels are also used to contact previously unconnected routers, which is why
they are called "exploratory".
These tunnels are usually low-bandwidth.
{%- endtrans %}</p>
<p>{% trans -%}
Peers for building exploratory tunnels are generally chosen randomly from the standard group.
If the success rate of these build attempts is low compared to the client tunnel build success rate,
the router will select a weighted average of peers randomly from the high capacity group instead.
This helps maintain a satisfactory build success rate even when network performance is poor.
There is no bias toward selecting peers that were previously participants in an exploratory tunnel.
{%- endtrans %}</p>
<p>{% trans -%}
As the standard group includes a very large subset of all peers the router knows about,
exploratory tunnels are essentially built through a random selection of all peers,
until the build success rate becomes too low.
{%- endtrans %}</p>
<h3>{% trans %}Restrictions{% endtrans %}</h3>
<p>{% trans -%}
To prevent some simple attacks, and for performance, there are the following restrictions:
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
Two peers from the same /16 IP space may not be in the same tunnel.
{%- endtrans %}</li>
<li>{% trans -%}
A peer may participate in a maximum of 33&#37; of all tunnels created by the router.
{%- endtrans %}</li>
<li>{% trans -%}
Peers with extremely low bandwidth are not used.
{%- endtrans %}</li>
<li>{% trans -%}
Peers for which a recent connection attempt failed are not used.
{%- endtrans %}</li>
</ul>
<h3>{% trans %}Peer Ordering in Tunnels{% endtrans %}</h3>
<p>{% trans pdf='http://forensics.umass.edu/pubs/wright-tissec.pdf',
pdf2008='http://forensics.umass.edu/pubs/wright.tissec.2008.pdf',
tunnelimpl=site_url('docs/tunnels/implementation') -%}
Peers are ordered within tunnels to
to deal with the <a href="{{ pdf }}">predecessor attack</a>
<a href="{{ pdf2008 }}">(2008 update)</a>.
More information is on the <a href="{{ tunnelimpl }}#ordering">tunnel page</a>.
{%- endtrans %}</p>
<h2>{% trans %}Future Work{% endtrans %}</h2>
<ul>
<li>{% trans -%}
Continue to analyze an tune speed and capacity calculations as necessary
{%- endtrans %}</li>
<li>{% trans -%}
Implement a more aggressive ejection strategy if necessary to control memory usage as the network grows
{%- endtrans %}</li>
<li>{% trans -%}
Evaluate group size limits
{%- endtrans %}</li>
<li>{% trans -%}
Use GeoIP data to include or exclude certain peers, if configured
{%- endtrans %}</li>
</ul>
<h2 id="notes">{% trans %}Notes{% endtrans %}</h2>
<p>{% trans pdf=url_for('static', filename='pdf/I2P-PET-CON-2009.1.pdf') -%}
For those reading the paper
<a href="{{ pdf }}">Peer Profiling and Selection in the I2P Anonymous Network</a>,
please keep in mind the following minor changes in I2P since the paper's publication:
{%- endtrans %}</p>
<ul>
<li>{% trans %}The Integration calculation is still not used{% endtrans %}</li>
<li>{% trans %}In the paper, "groups" are called "tiers"{% endtrans %}</li>
<li>{% trans %}The "Failing" tier is no longer used{% endtrans %}</li>
<li>{% trans %}The "Not Failing" tier is now named "Standard"{% endtrans %}</li>
</ul>
<h2>{% trans %}References{% endtrans %}</h2>
<ul>
<li>
<a href="{{ url_for('static', filename='pdf/I2P-PET-CON-2009.1.pdf') }}">{% trans %}Peer Profiling and Selection in the I2P Anonymous Network{% endtrans %}</a>
<li>
<a href="http://blog.torproject.org/blog/one-cell-enough">{% trans %}One Cell Enough{% endtrans %}</a>
<li>
<a href="https://wiki.torproject.org/noreply/TheOnionRouter/TorFAQ#EntryGuards">{% trans %}Tor Entry Guards{% endtrans %}</a>
<li>
<a href="http://freehaven.net/anonbib/#murdoch-pet2007">{% trans %}Murdoch 2007 Paper{% endtrans %}</a>
<li>
<a href="http://www.crhc.uiuc.edu/~nikita/papers/tuneup-cr.pdf">{% trans %}Tune-up for Tor{% endtrans %}</a>
<li>
<a href="http://cs.gmu.edu/~mccoy/papers/wpes25-bauer.pdf">{% trans %}Low-resource Routing Attacks Against Tor{% endtrans %}</a>
</ul>
{% endblock %}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,892 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}I2P's Threat Model{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}November 2010{% endtrans %}{% endblock %}
{% block accuratefor %}0.8.1{% endblock %}
{% block content %}
<h2>{% trans %}What do we mean by "anonymous"?{% endtrans %}</h2>
<p>{% trans -%}
Your level of anonymity can be described as "how hard it is for someone
to find out information you don't want them to know?" - who you are, where
you are located, who you communicate with, or even when you communicate.
"Perfect" anonymity is not a useful concept here - software will not make
you indistinguishable from people that don't use computers or who are not on
the Internet. Instead, we are working to provide sufficient anonymity to meet the
real needs of whomever we can - from those simply browsing websites, to those exchanging
data, to those fearful of discovery by powerful organizations or states.
{%- endtrans %}</p>
<p>{% trans -%}
The question of whether I2P provides sufficient anonymity for your
particular needs is a hard one, but this page will hopefully assist in
answering that question by exploring how I2P operates under various attacks
so that you may decide whether it meets your needs.
{%- endtrans %}</p>
<p>{% trans -%}
We welcome further research and analysis on I2P's resistance to the threats described below.
More review of existing literature (much of it focused on Tor) and original
work focused on I2P is needed.
{%- endtrans %}</p>
<h2>{% trans %}Network Topology Summary{% endtrans %}</h2>
<p>{% trans comparisons=site_url('comparison'), links=site_url('links') -%}
I2P builds off the ideas of many <a href="{{ comparisons }}">other</a>
<a href="{{ links }}">systems</a>, but a few key points should be kept in mind when
reviewing related literature:
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
<b>I2P is a free route mixnet</b> - the message creator explicitly defines the
path that messages will be sent out (the outbound tunnel), and the message
recipient explicitly defines the path that messages will be received on (the
inbound tunnel).
{%- endtrans %}</li>
<li>{% trans -%}
<b>I2P has no official entry and exit points</b> - all peers fully participate in the
mix, and there are no network layer in- or out-proxies (however, at the
application layer, a few proxies do exist)
{%- endtrans %}</li>
<li>{% trans -%}
<b>I2P is fully distributed</b> - there are no central controls or authorities.
One could modify some routers to operate mix cascades (building tunnels and giving
out the keys necessary to control the forwarding at the tunnel endpoint) or directory
based profiling and selection, all without breaking compatibility with the rest of
the network, but doing so is of course not necessary (and may even harm one's
anonymity).
{%- endtrans %}</li>
</ul>
<p>{% trans todo=site_url('get-involved/todo') -%}
We have documented plans to implement <a href="{{ todo }}#stop">nontrivial delays</a>
and <a href="{{ todo }}#batching">batching strategies</a>
whose existence is only known to the particular hop or tunnel gateway that
receives the message, allowing a mostly low latency mixnet to provide cover
traffic for higher latency communication (e.g. email).
However we are aware that significant delays are required to provide meaningful
protection, and that implementation of such delays will be a significant challenge.
It is not clear at this time whether we will actually implement these delay features.
{%- endtrans %}</p>
<p>{% trans -%}
In theory, routers along the message path may inject an
arbitrary number of hops before forwarding the message to the next peer, though
the current implementation does not.
{%- endtrans %}</p>
<h2>{% trans %}The Threat Model (Attacks){% endtrans %}</h2>
<p>{% trans -%}
I2P design started in 2003, not long after the advent of
<a href="http://www.onion-router.net">[Onion Routing]</a>,
<a href="http://freenetproject.org/">[Freenet]</a>, and
<a href="https://www.torproject.org/">[Tor]</a>.
Our design benefits substantially from the research published around that time.
I2P uses several onion routing techniques, so we continue to benefit
from the significant academic interest in Tor.
{%- endtrans %}</p>
<p>{% trans -%}
Taking from the attacks and analysis put forth in the
<a href="http://freehaven.net/anonbib/topic.html">anonymity literature</a> (largely
<a href="http://citeseer.ist.psu.edu/454354.html">Traffic Analysis: Protocols, Attacks, Design
Issues and Open Problems</a>), the following briefly describes a wide variety
of attacks as well as many of I2Ps defenses. We update
this list to include new attacks as they are identified.
{%- endtrans %}</p>
<p>{% trans -%}
Included are some attacks that may be unique to I2P.
We do not have good answers for all these attacks, however
we continue to do research and improve our defenses.
{%- endtrans %}</p>
<p>{% trans -%}
In addition, many of these attacks are significantly easier than
they should be, due to the modest size of the current network.
While we are aware of some limitations that need to be addressed,
I2P is designed to support hundreds of thousands, or millions, of
participants.
As we continue to spread the word and grow the network,
these attacks will become much harder.
{%- endtrans %}</p>
<p>{% trans comparisons=site_url('comparison'), garlicrouting=site_url('docs/how/garlic-routing') -%}
The
<a href="{{ comparisons }}">network comparisons</a> and
<a href="{{ garlicrouting }}">"garlic" terminology</a> pages may also be helpful
to review.
{%- endtrans %}</p>
<h3 id="index">{% trans %}Index{% endtrans %}</h3>
<ul>
<li><a href="#bruteforce">{% trans %}Brute force attacks{% endtrans %}</a></li>
<li><a href="#timing">{% trans %}Timing attacks{% endtrans %}</a></li>
<li><a href="#intersection">{% trans %}Intersection attacks{% endtrans %}</a></li>
<li><a href="#dos">{% trans %}Denial of service attacks{% endtrans %}</a></li>
<li><a href="#tagging">{% trans %}Tagging attacks{% endtrans %}</a></li>
<li><a href="#partitioning">{% trans %}Partitioning attacks{% endtrans %}</a></li>
<li><a href="#predecessor">{% trans %}Predecessor attacks{% endtrans %}</a></li>
<li><a href="#harvesting">{% trans %}Harvesting attacks{% endtrans %}</a></li>
<li><a href="#traffic">{% trans %}Identification Through Traffic Analysis{% endtrans %}</a></li>
<li><a href="#sybil">{% trans %}Sybil attacks{% endtrans %}</a></li>
<li><a href="#buddy">{% trans %}Buddy Exhaustion attacks{% endtrans %}</a></li>
<li><a href="#crypto">{% trans %}Cryptographic attacks{% endtrans %}</a></li>
<li><a href="#floodfill">{% trans %}Floodfill attacks{% endtrans %}</a></li>
<li><a href="#netdb">{% trans %}Other Network Database attacks{% endtrans %}</a></li>
<li><a href="#central">{% trans %}Attacks on centralized resources{% endtrans %}</a></li>
<li><a href="#dev">{% trans %}Development attacks{% endtrans %}</a></li>
<li><a href="#impl">{% trans %}Implementation attacks{% endtrans %}</a></li>
<li><a href="#blocklist">{% trans %}Other Defenses{% endtrans %}</a></li>
</ul>
<h3 id="bruteforce">{% trans %}Brute force attacks{% endtrans %}</h3>
<p>{% trans -%}
A brute force attack can be mounted by a global passive or active adversary,
watching all the messages pass between all of the nodes and attempting to correlate
which message follows which path. Mounting this attack against I2P should be
nontrivial, as all peers in the network are frequently sending messages (both
end to end and network maintenance messages), plus an end to end message changes
size and data along its path. In addition, the external adversary does not have
access to the messages either, as inter-router communication is both encrypted
and streamed (making two 1024 byte messages indistinguishable from one 2048 byte
message).
{%- endtrans %}</p>
<p>{% trans -%}
However, a powerful attacker can use brute force to detect trends - if they
can send 5GB to an I2P destination and monitor everyone's network connection,
they can eliminate all peers who did not receive 5GB of data. Techniques to
defeat this attack exist, but may be prohibitively expensive (see:
<a href="http://citeseer.ist.psu.edu/freedman02tarzan.html">Tarzan</a>'s mimics
or constant rate traffic). Most users are not concerned with this attack, as
the cost of mounting it are extreme (and often require illegal activity).
However, the attack is still possible, for example by an observer at
a large ISP or an Internet exchange point.
Those who want to defend against it
would want to take appropriate countermeasures, such as
setting low bandwidth limits, and using unpublished or encrypted leasesets for eepsites.
Other countermeasures, such as nontrivial delays and restricted routes, are
not currently implemented.
{%- endtrans %}</p>
<p>{% trans peerselection=site_url('docs/how/peer-selection') -%}
As a partial defense against a single router or group of routers trying to route all the network's traffic,
routers contain limits as to how many tunnels can be routed through a single peer.
As the network grows, these limits are subject to further adjustment.
Other mechanisms for peer rating, selection and avoidance
are discussed on the
<a href="{{ peerselection }}">peer selection page</a>.
{%- endtrans %}</p>
<h3 id="timing">{% trans %}Timing attacks{% endtrans %}</h3>
<p>{% trans -%}
I2P's messages are unidirectional and do not necessarily imply that a reply
will be sent. However, applications on top of I2P will most likely have
recognizable patterns within the frequency of their messages - for instance, an
HTTP request will be a small message with a large sequence of reply messages
containing the HTTP response. Using this data as well as a broad view of the
network topology, an attacker may be able to disqualify some links as being too
slow to have passed the message along.
{%- endtrans %}</p>
<p>{% trans -%}
This sort of attack is powerful, but its applicability to I2P is non obvious,
as the variation on message delays due to queuing, message processing, and
throttling will often meet or exceed the time of passing a message along a
single link - even when the attacker knows that a reply will be sent as soon as
the message is received. There are some scenarios which will expose fairly
automatic replies though - the streaming library does (with the SYN+ACK) as does the
message mode of guaranteed delivery (with the DataMessage+DeliveryStatusMessage).
{%- endtrans %}</p>
<p>{% trans todo=site_url('get-involved/todo') -%}
Without protocol scrubbing or higher latency, global active adversaries can
gain substantial information. As such, people concerned with these attacks could
increase the latency (using <a href="{{ todo }}#stop">nontrivial delays</a> or
<a href="{{ todo }}#batching">batching strategies</a>), include protocol scrubbing, or
other advanced tunnel routing <a href="{{ todo }}#batching">techniques</a>,
but these are unimplemented in I2P.
{%- endtrans %}</p>
<p>{% trans pdf='http://www.cs.colorado.edu/department/publications/reports/docs/CU-CS-1025-07.pdf' -%}
References: <a href="{{ pdf }}">Low-Resource Routing Attacks Against Anonymous Systems</a>
{%- endtrans %}</p>
<h3 id="intersection">{% trans %}Intersection attacks{% endtrans %}</h3>
<p>{% trans -%}
Intersection attacks against low latency systems are extremely powerful -
periodically make contact with the target and keep track of what peers are on
the network. Over time, as node churn occurs the attacker will gain
significant information about the target by simply intersecting the sets of
peers that are online when a message successfully goes through. The cost of
this attack is significant as the network grows, but may be feasible in some
scenarios.
{%- endtrans %}</p>
<p>{% trans url='https://trac.torproject.org/projects/tor/wiki/TheOnionRouter/TorFAQ#Whatattacksremainagainstonionrouting' -%}
In summary, if an attacker is at both ends of your tunnel at the same time,
he may be successful.
I2P does not have a full defense to this for low latency communication.
This is an inherent weakness of low-latency onion routing.
Tor provides a <a href="{{ url }}">similar disclaimer</a>.
{%- endtrans %}</p>
<p>{% trans -%}
Partial defenses implemented in I2P:
{%- endtrans %}</p>
<ul>
<li>{% trans tunnelimpl=site_url('docs/tunnels/implementation') -%}
<a href="{{ tunnelimpl }}#ordering">strict ordering</a> of peers
{%- endtrans %}</li>
<li>{% trans peerselection=site_url('docs/how/peer-selection') -%}
<a href="{{ peerselection }}">peer profiling and selection</a> from a small group that changes slowly
{%- endtrans %}</li>
<li>{% trans -%}
Limits on the number of tunnels routed through a single peer
{%- endtrans %}</li>
<li>{% trans -%}
Prevention of peers from the same /16 IP range from being members of a single tunnel
{%- endtrans %}</li>
<li>{% trans -%}
For eepsites or other hosted services, we support
simultaneous hosting on multiple routers, or
<a href="#intersection">multihoming</a>
{%- endtrans %}</li>
</ul>
<p>{% trans -%}
Even in total, these defenses are not a complete solution.
Also, we have made some design choices that may significantly increase our vulnerability:
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
We do not use low-bandwidth "guard nodes"
{%- endtrans %}</li>
<li>{% trans -%}
We use tunnel pools comprised of several tunnels, and traffic can shift from tunnel to tunnel.
{%- endtrans %}</li>
<li>{% trans -%}
Tunnels are not long-lived; new tunnels are built every 10 minutes.
{%- endtrans %}</li>
<li>{% trans -%}
Tunnel lengths are configurable.
While 3-hop tunnels are recommended for full protection, several applications and
services use 2-hop tunnels by default.
{%- endtrans %}</li>
</ul>
<p>{% trans todo=site_url('get-involved/todo') -%}
In the future, it could
for peers who can afford significant delays (per <a href="{{ todo }}#stop">nontrivial
delays</a> and <a href="{{ todo }}#batching">batching strategies</a>). In addition,
this is only relevant for destinations that other people know about - a private
group whose destination is only known to trusted peers does not have to worry,
as an adversary can't "ping" them to mount the attack.</p>
{%- endtrans %}</p>
<p>{% trans oce='http://blog.torproject.org/blog/one-cell-enough' -%}
Reference: <a href="{{ oce }}">One Cell Enough</a>
{%- endtrans %}</p>
<h3 id="dos">{% trans %}Denial of service attacks{% endtrans %}</h3>
<p>{% trans -%}
There are a whole slew of denial of service attacks available against I2P,
each with different costs and consequences:
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
<b>Greedy user attack:</b> This is simply
people trying to consume significantly more resources than they are
willing to contribute. The defense against this is:
{%- endtrans %}
<ul>
<li>{% trans comparisons=site_url('comparison') -%}
Set defaults so that most users provide resources to the network.
In I2P, users route traffic by default. In sharp distinction to
<a href="{{ comparisons }}">other networks</a>,
over 95&#37; of I2P users relay traffic for others.
{%- endtrans %}</li>
<li>{% trans -%}
Provide easy configuration options so that users may increase their
contribution (share percentage) to the network. Display easy-to-understand
metrics such as "share ratio" so that users may see what they are contributing.
{%- endtrans %}</li>
<li>{% trans -%}
Maintain a strong community with blogs, forums, IRC, and other means of communication.
{%- endtrans %}</li>
</ul>
</li>
<li>{% trans peerselection=site_url('docs/how/peer-selection') -%}
<b>Starvation attack:</b> A hostile user may attempt to harm the network by
creating a significant number of peers in the network who are not identified as
being under control of the same entity (as with Sybil). These nodes then
decide not to provide any resources to the network, causing existing peers
to search through a larger network database or request more tunnels than
should be necessary.
Alternatively, the nodes may provide intermittent service by periodically
dropping selected traffic, or refusing connections to certain peers.
This behavior may be indistinguishable from that of a heavily-loaded or failing node.
I2P addresses these issues by maintaining <a href="{{ peerselection }}">profiles</a> on the
peers, attempting to identify underperforming ones and simply ignoring
them, or using them rarely.
We have significantly enhanced the
ability to recognize and avoid troublesome peers; however there are still
significant efforts required in this area.
{%- endtrans %}</li>
<li>{% trans todo=site_url('get-involved/todo') -%}
<b>Flooding attack:</b> A hostile user may attempt to flood the network,
a peer, a destination, or a tunnel. Network and peer flooding is possible,
and I2P does nothing to prevent standard IP layer flooding. The flooding of
a destination with messages by sending a large number to the target's various
inbound tunnel gateways is possible, but the destination will know this both
by the contents of the message and because the tunnel's tests will fail. The
same goes for flooding just a single tunnel. I2P has no defenses for a network
flooding attack. For a destination and tunnel flooding attack, the target
identifies which tunnels are unresponsive and builds new ones. New code could
also be written to add even more tunnels if the client wishes to handle the
larger load. If, on the other hand, the load is more than the client can
deal with, they can instruct the tunnels to throttle the number of messages or
bytes they should pass on (once the <a href="{{ todo }}#batching">advanced tunnel
operation</a> is implemented).
{%- endtrans %}</li>
<li>{% trans -%}
<b>CPU load attack:</b> There are currently some methods for people to
remotely request that a peer perform some cryptographically expensive
operation, and a hostile attacker could use these to flood that peer with
a large number of them in an attempt to overload the CPU. Both using good
engineering practices and potentially requiring nontrivial certificates
(e.g. HashCash) to be attached to these expensive requests should mitigate
the issue, though there may be room for an attacker to exploit various
bugs in the implementation.
{%- endtrans %}</li>
<li id="ffdos">{% trans peerselection=site_url('docs/how/peer-selection'),
netdb=site_url('docs/how/network-database') -%}
<b>Floodfill DOS attack:</b> A hostile user may attempt to harm the network by
becoming a floodfill router. The current defenses against unreliable,
intermittent, or malicious floodfill routers are poor.
A floodfill router may provide bad or no response to lookups, and
it may also interfere with inter-floodfill communication.
Some defenses and
<a href="{{ peerselection }}">peer profiling</a> are implemented,
however there is much more to do.
For more information see the
<a href="{{ netdb }}#threat">network database page</a>.
{%- endtrans %}</li>
</ul>
<h3 id="tagging">{% trans %}Tagging attacks{% endtrans %}</h3>
<p>{% trans todo=site_url('get-involved/todo') -%}
Tagging attacks - modifying a message so that it can later be identified
further along the path - are by themselves impossible in I2P, as messages
passed through tunnels are signed. However, if an attacker is the inbound
tunnel gateway as well as a participant further along in that tunnel, with
collusion they can identify the fact that they are in the same tunnel (and
prior to adding <a href="{{ todo }}#tunnelId">unique hop ids</a> and other updates,
colluding peers within the same tunnel can recognize that fact without any
effort). An attacker in an outbound tunnel and any part of an inbound tunnel cannot
collude however, as the tunnel encryption pads and modifies the data separately
for the inbound and outbound tunnels. External attackers cannot do anything,
as the links are encrypted and messages signed.
{%- endtrans %}</p>
<h3 id="partitioning">{% trans %}Partitioning attacks{% endtrans %}</h3>
<p>{% trans -%}
Partitioning attacks - finding ways to segregate (technically or analytically)
the peers in a network - are important to keep in mind when dealing with a
powerful adversary, since the size of the network plays a key role in determining
your anonymity. Technical partitioning by cutting links between peers to create
fragmented networks is addressed by I2P's built in network database, which
maintains statistics about various peers so as to allow any existing connections
to other fragmented sections to be exploited so as to heal the network. However,
if the attacker does disconnect all links to uncontrolled peers, essentially
isolating the target, no amount of network database healing will fix it. At
that point, the only thing the router can hope to do is notice that a significant
number of previously reliable peers have become unavailable and alert the client
that it is temporarily disconnected (this detection code is not implemented at
the moment).
{%- endtrans %}</p>
<p>{% trans todo=site_url('get-involved/todo') -%}
Partitioning the network analytically by looking for differences in how routers
and destinations behave and grouping them accordingly is also a very powerful
attack. For instance, an attacker <a href="#harvesting">harvesting</a> the network
database will know when a particular destination has 5 inbound tunnels in their
LeaseSet while others have only 2 or 3, allowing the adversary to potentially
partition clients by the number of tunnels selected. Another partition is
possible when dealing with the <a href="{{ todo }}#stop">nontrivial delays</a> and
<a href="{{ todo }}#batching">batching strategies</a>, as the tunnel gateways and the
particular hops with non-zero delays will likely stand out. However, this data
is only exposed to those specific hops, so to partition effectively on that
matter, the attacker would need to control a significant portion of the network
(and still that would only be a probabilistic partition, as they wouldn't know
which other tunnels or messages have those delays).
{%- endtrans %}</p>
<p>{% trans netdb=site_url('docs/how/network-database') -%}
Also discussed on the <a href="{{ netdb }}#threat">network database page</a> (bootstrap attack).
{%- endtrans %}</p>
<h3 id="predecessor">{% trans %}Predecessor attacks{% endtrans %}</h3>
<p>{% trans -%}
The predecessor attack is passively gathering statistics in an attempt to see
what peers are 'close' to the destination by participating in their tunnels and
keeping track of the previous or next hop (for outbound or inbound tunnels,
respectively). Over time, using a perfectly random sample of peers and random
ordering, an attacker would be able to see which peer shows up as 'closer'
statistically more than the rest, and that peer would in turn be where the
target is located.
{%- endtrans %}</p>
<p>{% trans peerselection=site_url('docs/how/peer-selection'),
tunnelimpl=site_url('docs/tunnels/implementation'),
todo=site_url('get-involved/todo') -%}
I2P avoids this in four ways: first, the peers selected to participate in
tunnels are not randomly sampled throughout the network - they are derived from
the <a href="{{ peerselection }}">peer selection</a> algorithm which breaks them
into tiers. Second, with <a href="{{ tunnelimpl }}#ordering">strict ordering</a> of peers
in a tunnel, the fact that a peer shows up more frequently does not mean they're
the source. Third, with <a href="{{ tunnelimpl }}#length">permuted tunnel length</a>
(not enabled by default)
even 0 hop tunnels can provide plausible deniability as the occasional
variation of the gateway will look like normal tunnels. Fourth, with
<a href="{{ todo }}#fullRestrictedRoutes">restricted routes</a> (unimplemented), only the peer with
a restricted connection to the target will ever contact the target, while
attackers will merely run into that gateway.
{%- endtrans %}</p>
<p>{% trans tunnelcreation=site_url('docs/spec/tunnel-creation') -%}
The current <a href="{{ tunnelcreation }}">tunnel build method</a>
was specifically designed to combat the predecessor attack.
See also <a href="#intersection">the intersection attack</a>.
{%- endtrans %}</p>
<p>{% trans pdf2008='http://forensics.umass.edu/pubs/wright.tissec.2008.pdf',
pdf2004='http://forensics.umass.edu/pubs/wright-tissec.pdf' -%}
References: <a href="{{ pdf2008 }}">{{ pdf2008 }}</a>
which is an update to the 2004 predecessor attack paper
<a href="{{ pdf2004 }}">{{ pdf2004 }}</a>.
{%- endtrans %}</p>
<h3 id="harvesting">{% trans %}Harvesting attacks{% endtrans %}</h3>
<p>{% trans -%}
"Harvesting" means compiling a list of users running I2P.
It can be used for legal attacks and to help
other attacks by simply running a peer, seeing who it connects to, and
harvesting whatever references to other peers it can find.
{%- endtrans %}</p>
<p>{% trans -%}
I2P itself is not designed with effective defenses against
this attack, since there is the distributed network database
containing just this information.
The following factors make the attack somewhat harder in practice:
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
Network growth will make it more difficult to obtain a given proportion of the network
{%- endtrans %}</li>
<li>{% trans -%}
Floodfill routers implement query limits as DOS protection
{%- endtrans %}</li>
<li>{% trans -%}
"Hidden mode", which prevents a router from publishing its information to the netDb,
(but also prevents it from relaying data) is not widely used now but could be.
{%- endtrans %}</li>
</ul>
<p>{% trans todo=site_url('get-involved/todo') -%}
In future implementations,
<a href="{{ todo }}#nat">basic</a> and
<a href="{{ todo }}#fullRestrictedRoutes">comprehensive</a> restricted routes,
this attack loses much of its power, as the "hidden" peers do not publish their
contact addresses in the network database - only the tunnels through which
they can be reached (as well as their public keys, etc).
{%- endtrans %}</p>
<p>{% trans -%}
In the future, routers could use GeoIP to identify if they are in a particular
country where identification as an I2P node would be risky.
In that case, the router could automatically enable hidden mode, or
enact other restricted route methods.
{%- endtrans %}</p>
<h3 id="traffic">{% trans %}Identification Through Traffic Analysis{% endtrans %}</h3>
<p>{% trans transport=site_url('docs/transport') -%}
By inspecting the traffic into and out of a router, a malicious ISP
or state-level firewall could identify that a computer is running I2P.
As discussed <a href="#harvesting">above</a>, I2P is not specifically designed
to hide that a computer is running I2P. However, several design decisions made
in the design of the
<a href="{{ transport }}">transport layer and protocols</a>
make it somewhat difficult to identify I2P traffic:
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
Random port selection
{%- endtrans %}</li>
<li>{% trans -%}
Point-to-Point Encryption of all traffic
{%- endtrans %}</li>
<li>{% trans -%}
DH key exchange with no protocol bytes or other unencrypted constant fields
{%- endtrans %}</li>
<li>{% trans ntcp=site_url('docs/transport/ntcp'), ssu=site_url('docs/transport/ssu') -%}
Simultaneous use of both
<a href="{{ ntcp }}">TCP</a> and
<a href="{{ ssu }}">UDP</a> transports.
UDP may be much harder for some Deep Packet Inspection (DPI) equipment to track.
{%- endtrans %}</li>
</ul>
<p>{% trans -%}
In the near future, we plan to directly address traffic analysis issues by further obfuscation of I2P transport protocols, possibly including:
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
Padding at the transport layer to random lengths, especially during the connection handshake
{%- endtrans %}</li>
<li>{% trans -%}
Study of packet size distribution signatures, and additional padding as necessary
{%- endtrans %}</li>
<li>{% trans -%}
Development of additional transport methods that mimic SSL or other common protocols
{%- endtrans %}</li>
<li>{% trans -%}
Review of padding strategies at higher layers to see how they affect packet sizes at the transport layer
{%- endtrans %}</li>
<li>{% trans -%}
Review of methods implemented by various state-level firewalls to block Tor
{%- endtrans %}</li>
<li>{% trans -%}
Working directly with DPI and obfuscation experts
{%- endtrans %}</li>
</ul>
<p>{% trans pdf='http://www.iis.se/docs/hjelmvik_breaking.pdf' -%}
Reference: <a href="{{ pdf }}">Breaking and Improving Protocol Obfuscation</a>
{%- endtrans %}</p>
<h3 id="sybil">{% trans %}Sybil attacks{% endtrans %}</h3>
<p>{% trans -%}
Sybil describes a category of attacks where the adversary creates arbitrarily
large numbers of colluding nodes and uses the increased numbers to help
mounting other attacks. For instance, if an attacker is in a network where peers
are selected randomly and they want an 80&#37; chance to be one of those peers, they
simply create five times the number of nodes that are in the network and roll
the dice. When identity is free, Sybil can be a very potent technique for a
powerful adversary. The primary technique to address this is simply to make
identity 'non free' - <a href="http://www.pdos.lcs.mit.edu/tarzan/">Tarzan</a>
(among others) uses the fact that IP addresses are limited, while
IIP used
<a href="http://www.hashcash.org/">HashCash</a> to 'charge' for creating a new
identity. We currently have not implemented any particular technique to address
Sybil, but do include placeholder certificates in the router's and
destination's data structures which can contain a HashCash certificate of
appropriate value when necessary (or some other certificate proving scarcity).
{%- endtrans %}</p>
<p>{% trans -%}
Requiring HashCash Certificates in various places has two major problems:
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
Maintaining backward compatibility
{%- endtrans %}</li>
<li>{% trans -%}
The classic HashCash problem -
selecting HashCash values that are meaningful proofs of work on high-end machines,
while still being feasible on low-end machines such as mobile devices.
{%- endtrans %}</li>
</ul>
<p>{% trans -%}
Various limitations on the number of routers in a given IP range restrict
the vulnerability to attackers that don't have the ability to put machines
in several IP blocks.
However, this is not a meaningful defense against a powerful adversary.
{%- endtrans %}</p>
<p>{% trans netdb=site_url('docs/how/network-database') -%}
See the <a href="{{ netdb }}#threat">network database page</a>
for more Sybil discussion.
{%- endtrans %}</p>
<h3 id="buddy">{% trans %}Buddy Exhaustion attacks{% endtrans %}</h3>
<p>{% trans pdf='http://www.eecs.berkeley.edu/~pmittal/publications/nisan-torsk-ccs10.pdf' -%}
(Reference: <a href="{{ pdf }}">In Search of an Anonymouns and Secure Lookup</a> Section 5.2)
{%- endtrans %}</p>
<p>{% trans peerselection=site_url('docs/how/peer-selection') -%}
By refusing to accept or forward tunnel build requests, except to a colluding peer, a router could ensure
that a tunnel is formed wholly from its set of colluding routers.
The chances of success are enhanced if there is a large number of colluding routers,
i.e. a <a href="#sybil">Sybil attack</a>.
This is somewhat mitigated by our
<a href="{{ peerselection }}">peer profiling</a> methods used to monitor the performance
of peers.
However, this is a powerful attack as the number of routers approaches
<i>f</i> = 0.2, or 20&#37; malicious nodes, as specifed in the paper.
The malicous routers could also maintain connections to the target router and provide
excellent forwarding bandwidth for traffic over those connections, in an attempt
to manipulate the profiles managed by the target and appear attractive.
Further research and defenses may be necessary.
{%- endtrans %}</p>
<h3 id="crypto">{% trans %}Cryptographic attacks{% endtrans %}</h3>
<p>{% trans cryptography=site_url('docs/how/cryptography') -%}
We use strong cryptography with long keys, and
we assume the security of the industry-standard cryptographic primitives used in I2P, as documented
<a href="{{ cryptography }}">on the low-level cryptography page</a>.
Security features include the immediate detection of
altered messages along the path, the inability to decrypt messages not addressed to you,
and defense against man-in-the-middle attacks.
The key sizes chosen in 2003 were quite conservative at the time, and are still longer than
those used in <a href="https://torproject.org/">other anonymity networks</a>.
We don't think the current key lengths are our biggest weakness,
especially for traditional, non-state-level adversaries;
bugs and the small size of the network are much more worrisome.
Of course, all cryptographic algorithms eventually become obsolete due to
the advent of faster processors, cryptographic research, and advancements in
methods such as rainbow tables, clusters of video game hardware, etc.
Unfortunately, I2P was not designed with easy mechanisms to lengthen keys or change
shared secret values while maintaining backward compatibility.
{%- endtrans %}</p>
<p>{% trans cryptography=site_url('docs/how/cryptography') -%}
Upgrading the various data structures and protocols to support longer keys
will have to be tackled eventually, and this will be a
<a href="{{ cryptography }}">major undertaking</a>, just as it will be for
<a href="https://torproject.org/">others</a>.
Hopefully, through careful planning, we can minimize the disruption, and
implement mechanisms to make it easier for future transitions.
{%- endtrans %}</p>
<p>{% trans -%}
In the future, several I2P protocols and data structures
support securely padding messages to arbitrary sizes, so messages could be made constant
size or garlic messages could be modified randomly so that some cloves appear to contain
more subcloves than they actually do. At the moment, however, garlic, tunnel, and
end to end messages include simple random padding.
{%- endtrans %}</p>
<h3 id="floodfill">{% trans %}Floodfill Anonymity attacks{% endtrans %}</h3>
<p>{% trans netdb=site_url('docs/how/network-database') -%}
In addition to the floodfill DOS attacks described
<a href="#ffdos">above</a>, floodfill routers are uniquely positioned
to learn about network participants, due to their role
in the netDb, and the high frequency of communication with those participants.
This is somewhat mitigated because floodfill routers only manage a portion
of the total keyspace, and the keyspace rotates daily, as explained
on the <a href="{{ netdb }}#threat">network database page</a>.
The specific mechanisms by which routers communicate with floodfills have been
<a href="{{ netdb }}#delivery">carefully designed</a>.
However, these threats should be studied further.
The specific potential threats and corresponding defenses are a topic for future research.
{%- endtrans %}</p>
<h3 id="netdb">{% trans %}Other Network Database attacks{% endtrans %}</h3>
<p>{% trans netdb=site_url('docs/how/network-database') -%}
A hostile user may attempt to harm the network by
creating one or more floodfill routers and crafting them to offer
bad, slow, or no responses.
Several scenarios are discussed on the
<a href="{{ netdb }}#threat">network database page</a>.
{%- endtrans %}</p>
<h3 id="central">{% trans %}Central Resource Attacks{% endtrans %}</h3>
<p>{% trans -%}
There are a few centralized or limited resources (some inside I2P, some not)
that could be attacked or used as a vector for attacks.
The absence of jrandom starting November 2007, followed by the loss of the i2p.net hosting service in January 2008,
highlighted numerous centralized resources in the development and operation of the I2P network,
most of which are now distributed.
Attacks on externally-reachable resources mainly affect the ability of new users to find us,
not the operation of the network itself.
{%- endtrans %}</p>
<ul>
<li>{% trans site=site_url() -%}
The <a href="{{ site }}">website</a> is mirrored and uses DNS round-robin for external public access.
{%- endtrans %}</li>
<li>{% trans faq=site_url('faq') -%}
Routers now support <a href="{{ faq }}#reseed">multiple external reseed locations</a>,
however more reseed hosts may be needed, and the handling of unreliable or malicious
reseed hosts may need improvement.
{%- endtrans %}</li>
<li>{% trans -%}
Routers now support multiple update file locations.
A malicious update host could feed a huge file, need to limit the size.
{%- endtrans %}</li>
<li>{% trans -%}
Routers now support multiple default trusted update signers.
{%- endtrans %}</li>
<li>{% trans -%}
Routers now better handle <a href="#ffdos">multiple unreliable floodfill peers</a>.
Malicious floodfills <a href="#ffdos">needs</a> <a href="#floodfill">more</a> study.
{%- endtrans %}</li>
<li>{% trans monotone=site_url('get-involved/guides/monotone') -%}
The code is now stored in a <a href="{{ monotone }}">distributed source control system</a>.
{%- endtrans %}</li>
<li>{% trans -%}
Routers rely on a single news host, but there is a hardcoded backup URL pointing to a different host.
A malicious news host could feed a huge file, need to limit the size.
{%- endtrans %}</li>
<li>{% trans naming=site_url('docs/naming') -%}
<a href="{{ naming }}">Naming system services</a>, including addressbook subscription providers, add-host services,
and jump services, could be malicious. Substantial protections for subscriptions were implemented
in release 0.6.1.31, with additional enhancements in subsequent releases.
However, all naming services require some measure of trust, see
<a href="{{ naming }}">the naming page</a> for details.
{%- endtrans %}</li>
<li>{% trans -%}
We remain reliant on the DNS service for i2p2.de, losing this would cause substantial
disruption in our ability to attract new users,
and would shrink the network (in the short-to-medium term), just as the loss of i2p.net did.
{%- endtrans %}</li>
</ul>
<h3 id="dev">{% trans %}Development attacks{% endtrans %}</h3>
<p>{% trans -%}
These attacks aren't directly on the network, but instead go after its development team
by either introducing legal hurdles on anyone contributing to the development
of the software, or by using whatever means are available to get the developers to
subvert the software. Traditional technical measures cannot defeat these attacks, and
if someone threatened the life or livelihood of a developer (or even just issuing a
court order along with a gag order, under threat of prison), we would have a big problem.
{%- endtrans %}</p>
<p>{% trans -%}
However, two techniques help defend against these attacks:
{%- endtrans %}</p>
<ul>
<li>{% trans monotone=site_url('get-involved/guides/monotone') -%}
All components of the network must be open source to enable inspection, verification,
modification, and improvement. If a developer is compromised, once it is noticed
the community should demand explanation and cease to accept that developer's work.
All checkins to our <a href="{{ monotone }}">distributed source control system</a>
are cryptographically signed, and the release packagers use a trust-list system
to restrict modifications to those previously approved.
{%- endtrans %}</li>
<li>{% trans monotone=site_url('get-involved/guides/monotone') -%}
Development over the network itself, allowing developers to stay anonymous but still
secure the development process. All I2P development can occur through I2P - using
a <a href="{{ monotone }}">distributed source control system</a>,
a distributed source control system, IRC chat,
public web servers,
discussion forums (forum.i2p), and the software distribution sites,
all available within I2P.
{%- endtrans %}</li>
</ul>
<p>{% trans -%}
We also maintain relationships with various organizations that offer legal advice,
should any defense be necessary.
{%- endtrans %}</p>
<h3 id="impl">{% trans %}Implementation attacks (bugs){% endtrans %}</h3>
<p>{% trans -%}
Try as we might, most nontrivial applications include errors in the design or
implementation, and I2P is no exception. There may be bugs that could be exploited to
attack the anonymity or security of the communication running over I2P in unexpected
ways. To help withstand attacks against the design or protocols in use, we publish
all designs and documentation and solicit review and criticism with
the hope that many eyes will improve the system.
We do not believe in
<a href="http://www.haystacknetwork.com/">security through obscurity</a>.
{%- endtrans %}</p>
<p>{% trans -%}
In addition, the code is being
treated the same way, with little aversion towards reworking or throwing out
something that isn't meeting the needs of the software system (including ease of
modification). Documentation for the design and implementation of the network and
the software components are an essential part of security, as without them it is
unlikely that developers would be willing to spend the time to learn the software
enough to identify shortcomings and bugs.
{%- endtrans %}</p>
<p>{% trans -%}
Our software is likely, in particular, to contain bugs related to denial of service
through out-of-memory errors (OOMs), cross-site-scripting (XSS) issues in the router console,
and other vulnerabilities to non-standard inputs via the various protocols.
{%- endtrans %}</p>
<p>{% trans volunteer=site_url('get-involved') -%}
I2P is still a small network with a small development community and almost no
interest from academic or research groups.
Therefore we lack the analysis that
<a href="https://torproject.org/">other anonymity networks</a>
may have received. We continue to recruit people to
<a href="{{ volunteer }}">get involved</a> and help.
{%- endtrans %}</p>
<h2>{% trans %}Other Defenses{% endtrans %}</h2>
<h3 id="blocklist">{% trans %}Blocklists{% endtrans %}</h3>
<p>{% trans -%}
To some extent, I2P could be enhanced to avoid peers operating at IP addresses
listed in a blocklist. Several blocklists are commonly available in standard formats,
listing anti-P2P organizations, potential state-level adversaries, and others.
{%- endtrans %}</p>
<p>{% trans -%}
To the extent that active peers actually do show up in the actual blocklist,
blocking by only a subset of peers would tend to segment the network,
exacerbate reachability problems, and decrease overall reliability.
Therefore we would want to agree on a particular blocklist and
enable it by default.
{%- endtrans %}</p>
<p>{% trans -%}
Blocklists are only a part (perhaps a small part) of an array of defenses
against maliciousness.
In large part the profiling system does a good job of measuring
router behavior so that we don't need to trust anything in netDb.
However there is more that can be done. For each of the areas in the
list above there are improvements we can make in detecting badness.
{%- endtrans %}</p>
<p>{% trans -%}
If a blocklist is hosted at a central location with automatic updates
the network is vulnerable to a
<a href="#central">central resource attack</a>.
Automatic subscription to a list gives the list provider the power to shut
the i2p network down. Completely.
{%- endtrans %}</p>
<p>{% trans -%}
Currently, a default blocklist is distributed with our software,
listing only the IPs of past DOS sources.
There is no automatic update mechanism.
Should a particular IP range implement serious attacks on the I2P network,
we would have to ask people to update their blocklist manually through
out-of-band mechanisms such as forums, blogs, etc.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,299 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Tunnel Overview{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}July 2011{% endtrans %}{% endblock %}
{% block accuratefor %}0.8.7{% endblock %}
{% block content %}
<h2>{% trans %}Tunnel Overview{% endtrans %}</h2>
<p>{% trans -%}
This page contains an overview of I2P tunnel terminology and operation, with
links to more technical pages, details, and specifications.
{%- endtrans %}</p>
<p>{% trans intro=site_url('docs/how/intro') -%}
As briefly explained in the <a href="{{ intro }}">introduction</a>, I2P builds virtual "tunnels" -
temporary and unidirectional paths through a sequence of routers. These
tunnels are classified as either inbound tunnels (where everything
given to it goes towards the creator of the tunnel) or outbound tunnels
(where the tunnel creator shoves messages away from them). When Alice
wants to send a message to Bob, she will (typically) send it out one of
her existing outbound tunnels with instructions for that tunnel's endpoint
to forward it to the gateway router for one of Bob's current inbound
tunnels, which in turn passes it to Bob.
{%- endtrans %}</p>
<p style="text-align:center;">
<img src="{{ url_for('static', filename='images/tunnelSending.png') }}" alt="{{ _('Alice connecting through her outbound tunnel to Bob via his inbound tunnel') }}" title="{{ _('Alice connecting through her outbound tunnel to Bob via his inbound tunnel') }}" />
<pre>
A: {% trans %}Outbound Gateway{% endtrans %} (Alice)
B: {% trans %}Outbound Participant{% endtrans %}
C: {% trans %}Outbound Endpoint{% endtrans %}
D: {% trans %}Inbound Gateway{% endtrans %}
E: {% trans %}Inbound Participant{% endtrans %}
F: {% trans %}Inbound Endpoint{% endtrans %} (Bob)
</pre>
</p>
<h2>{% trans %}Tunnel vocabulary{% endtrans %}</h2>
<ul>
<li class="gap">{% trans netdb=site_url('docs/how/network-database') -%}
<b>Tunnel gateway</b> - the first router in a tunnel. For inbound tunnels,
this is the one mentioned in the LeaseSet published in the
<a href="{{ netdb }}">network database</a>. For outbound tunnels, the
gateway is the originating router. (e.g. both A and D above)
{%- endtrans %}</li>
<li class="gap">{% trans %}<b>Tunnel endpoint</b> - the last router in a tunnel. (e.g. both C and F above){% endtrans %}</li>
<li class="gap">{% trans -%}
<b>Tunnel participant</b> - all routers in a tunnel except for the gateway or
endpoint (e.g. both B and E above)
{%- endtrans %}</li>
<li>{% trans %}<b>n-Hop tunnel</b> - a tunnel with a specific number of inter-router jumps, e.g.:{% endtrans %}
<ul>
<li>{% trans %}<b>0-hop tunnel</b> - a tunnel where the gateway is also the endpoint{% endtrans %}</li>
<li>{% trans %}<b>1-hop tunnel</b> - a tunnel where the gateway talks directly to the endpoint{% endtrans %}</li>
<li>{% trans -%}
<b>2-(or more)-hop tunnel</b> - a tunnel where there is at least one intermediate
tunnel participant. (the above diagram includes two 2-hop tunnels - one
outbound from Alice, one inbound to Bob)
{%- endtrans %}</li>
</ul>
</li>
<li class="gap">{% trans commonstructures=site_url('docs/spec/common-structures') -%}
<b>Tunnel ID</b> - A <a href="{{ commonstructures }}#type_TunnelId">4 byte integer</a>
different for each hop in a tunnel, and unique among all tunnels on a router.
Chosen randomly by the tunnel creator.
{%- endtrans %}</li>
</ul>
<h2>{% trans %}Tunnel Build Information{% endtrans %}</h2>
<p>{% trans tunnelcreation=site_url('docs/spec/tunnel-creation') -%}
Routers performing the three roles (gateway, participant, endpoint) are given
different pieces of data in the initial
<a href="{{ tunnelcreation }}">Tunnel Build Message</a>
to accomplish their tasks:
{%- endtrans %}</p>
<ul>
<li class="gap"><b>{% trans %}The tunnel gateway gets:{% endtrans %}</b>
<ul>
<li>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
<b>tunnel encryption key</b> - an <a href="{{ commonstructures }}#type_SessionKey">AES private key</a> for encrypting
messages and instructions to the next hop
{%- endtrans %}</li>
<li>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
<b>tunnel IV key</b> - an <a href="{{ commonstructures }}#type_SessionKey">AES private key</a> for double-encrypting
the IV to the next hop
{%- endtrans %}</li>
<li>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
<b>reply key</b> - an <a href="{{ commonstructures }}#type_SessionKey">AES public key</a> for encrypting
the reply to the tunnel build request
{%- endtrans %}</li>
<li>{% trans %}<b>reply IV</b> - the IV for encrypting the reply to the tunnel build request{% endtrans %}</li>
<li>{% trans %}<b>tunnel id</b> - 4 byte integer (inbound gateways only){% endtrans %}</li>
<li>{% trans %}<b>next hop</b> - what router is the next one in the path (unless this is a 0-hop tunnel, and the gateway is also the endpoint){% endtrans %}</li>
<li>{% trans %}<b>next tunnel id</b> - The tunnel ID on the next hop{% endtrans %}</li>
</ul>
</li>
<li class="gap"><b>{% trans %}All intermediate tunnel participants get:{% endtrans %}</b>
<ul>
<li>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
<b>tunnel encryption key</b> - an <a href="{{ commonstructures }}#type_SessionKey">AES private key</a> for encrypting
messages and instructions to the next hop
{%- endtrans %}</li>
<li>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
<b>tunnel IV key</b> - an <a href="{{ commonstructures }}#type_SessionKey">AES private key</a> for double-encrypting
the IV to the next hop
{%- endtrans %}</li>
<li>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
<b>reply key</b> - an <a href="{{ commonstructures }}#type_SessionKey">AES public key</a> for encrypting
the reply to the tunnel build request
{%- endtrans %}</li>
<li>{% trans %}<b>reply IV</b> - the IV for encrypting the reply to the tunnel build request{% endtrans %}</li>
<li>{% trans %}<b>tunnel id</b> - 4 byte integer{% endtrans %}</li>
<li>{% trans %}<b>next hop</b> - what router is the next one in the path{% endtrans %}</li>
<li>{% trans %}<b>next tunnel id</b> - The tunnel ID on the next hop{% endtrans %}</li>
</ul>
</li>
<li class="gap"> <b>{% trans %}The tunnel endpoint gets:{% endtrans %}</b>
<ul>
<li>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
<b>tunnel encryption key</b> - an <a href="{{ commonstructures }}#type_SessionKey">AES private key</a> for encrypting
messages and instructions to the the endpoint (itself)
{%- endtrans %}</li>
<li>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
<b>tunnel IV key</b> - an <a href="{{ commonstructures }}#type_SessionKey">AES private key</a> for double-encrypting
the IV to the endpoint (itself)
{%- endtrans %}</li>
<li>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
<b>reply key</b> - an <a href="{{ commonstructures }}#type_SessionKey">AES public key</a> for encrypting
the reply to the tunnel build request (outbound endpoints only)
{%- endtrans %}</li>
<li>{% trans %}<b>reply IV</b> - the IV for encrypting the reply to the tunnel build request (outbound endpoints only){% endtrans %}</li>
<li>{% trans %}<b>tunnel id</b> - 4 byte integer (outbound endpoints only){% endtrans %}</li>
<li>{% trans %}<b>reply router</b> - the inbound gateway of the tunnel to send the reply through (outbound endpoints only){% endtrans %}</li>
<li>{% trans %}<b>reply tunnel id</b> - The tunnel ID of the reply router (outbound endpoints only){% endtrans %}</li>
</ul>
</li>
</ul>
<p>{% trans tunnelcreation=site_url('docs/spec/tunnel-creation') -%}
Details are in the
<a href="{{ tunnelcreation }}">tunnel creation specification</a>.
{%- endtrans %}</p>
<h2>{% trans %}Tunnel pooling{% endtrans %}</h2>
<p>{% trans tunnelimpl=site_url('docs/tunnels/implementation') -%}
Several tunnels for a particular purpose may be grouped into a "tunnel pool",
as described in the
<a href="{{ tunnelimpl }}#tunnel.pooling">tunnel specification</a>.
This provides redundancy and additional bandwidth.
The pools used by the router itself are called "exploratory tunnels".
The pools used by applications are called "client tunnels".
{%- endtrans %}</p>
<h2 id="length">{% trans %}Tunnel length{% endtrans %}</h2>
<p>{% trans i2cp=site_url('docs/protocol/i2cp') -%}
As mentioned above, each client requests that their router provide tunnels to
include at least a certain number of hops.
The decision as to how many routers
to have in one's outbound and inbound tunnels has an important effect upon the
latency, throughput, reliability, and anonymity provided by I2P - the more peers
that messages have to go through, the longer it takes to get there and the more
likely that one of those routers will fail prematurely. The less routers in a
tunnel, the easier it is for an adversary to mount traffic analysis attacks and
pierce someone's anonymity.
Tunnel lengths are specified by clients via
<a href="{{ i2cp }}#options">I2CP options</a>.
The maximum number of hops in a tunnel is 7.
{%- endtrans %}</p>
<h3>{% trans %}0-hop tunnels{% endtrans %}</h3>
<p>{% trans -%}
With no remote routers in a tunnel, the user has very basic plausible
deniability (since no one knows for sure that the peer that sent them the
message wasn't simply just forwarding it on as part of the tunnel). However, it
would be fairly easy to mount a statistical analysis attack and notice that
messages targeting a specific destination are always sent through a single
gateway. Statistical analysis against outbound 0-hop tunnels are more complex,
but could show similar information (though would be slightly harder to mount).
{%- endtrans %}</p>
<h3>{% trans %}1-hop tunnels{% endtrans %}</h3>
<p>{% trans threatmodel=site_url('docs/how/threat-model') -%}
With only one remote router in a tunnel, the user has both plausible
deniability and basic anonymity, as long as they are not up against an internal
adversary (as described on <a href="{{ threatmodel }}">threat model</a>). However,
if the adversary ran a sufficient number of routers such that the single remote
router in the tunnel is often one of those compromised ones, they would be able
to mount the above statistical traffic analysis attack.
{%- endtrans %}</p>
<h3>{% trans %}2-hop tunnels{% endtrans %}</h3>
<p>{% trans -%}
With two or more remote routers in a tunnel, the costs of mounting the traffic
analysis attack increases, since many remote routers would have to be compromised
to mount it.
{%- endtrans %}</p>
<h3>{% trans %}3-hop (or more) tunnels{% endtrans %}</h3>
<p>{% trans url='http://blog.torproject.org/blog/one-cell-enough' -%}
To reduce the susceptibility to <a href="{{ url }}">some attacks</a>,
3 or more hops are recommended for the highest level of protection.
<a href="{{ url }}">Recent studies</a>
also conclude that more than 3 hops does not provide additional protection.
{%- endtrans %}</p>
<h3>{% trans %}Tunnel default lengths{% endtrans %}</h3>
<p>{% trans i2cp=site_url('docs/protocol/i2cp') -%}
The router uses 2-hop tunnels by default for its exploratory tunnels.
Client tunnel defaults are set by the application, using
<a href="{{ i2cp }}#options">I2CP options</a>.
Most applications use 2 or 3 hops as their default.
{%- endtrans %}</p>
<h2 id="testing">{% trans %}Tunnel testing{% endtrans %}</h2>
<p>{% trans peerselection=site_url('docs/how/peer-selection') -%}
All tunnels are periodically tested by their creator by sending a
DeliveryStatusMessage out an outbound tunnel and bound for another inbound tunnel
(testing both tunnels at once). If either fails a number of consecutive tests, it is marked as no longer
functional. If it was used for a client's inbound tunnel, a new leaseSet
is created.
Tunnel test failures are also reflected in the
<a href="{{ peerselection }}#capacity">capacity rating in the peer profile</a>.
{%- endtrans %}</p>
<h2>{% trans %}Tunnel creation{% endtrans %}</h2>
<p>{% trans garlicrouting=site_url('docs/how/garlic-routing'),
tunnelcreation=site_url('docs/spec/tunnel-creation') -%}
Tunnel creation is handled by <a href="{{ garlicrouting }}">garlic routing</a>
a Tunnel Build Message to a router, requesting that they participate in the
tunnel (providing them with all of the appropriate information, as above, along
with a certificate, which right now is a 'null' cert, but will support hashcash
or other non-free certificates when necessary).
That router forwards the message to the next hop in the tunnel.
Details are in the
<a href="{{ tunnelcreation }}">tunnel creation specification</a>.
{%- endtrans %}</p>
<h2>Tunnel encryption</h2>
<p>{% trans garlicrouting=site_url('docs/how/garlic-routing'),
tunnelimpl=site_url('docs/tunnels/implementation') -%}
Multi-layer encryption is handled by <a href="{{ garlicrouting }}">garlic encryption</a>
of tunnel messages.
Details are in the
<a href="{{ tunnelimpl }}">tunnel specification</a>.
The IV of each hop is encrypted with a separate key as explained there.
{%- endtrans %}</p>
<h2>{% trans %}Future Work{% endtrans %}</h2>
<ul>
<li>{% trans -%}
Other tunnel test techniques could be used, such as
garlic wrapping a number of tests into cloves, testing individual tunnel
participants separately, etc.
{%- endtrans %}</li>
<li>{% trans -%}
Move to 3-hop exploratory tunnels defaults.
{%- endtrans %}</li>
<li>{% trans -%}
In a distant future release,
options specifying the pooling, mixing, and chaff generation settings may be implemented.
{%- endtrans %}</li>
<li>{% trans -%}
In a distant future release,
limits on the quantity and size of messages allowed during the
tunnel's lifetime may be implemented (e.g. no more than 300 messages or
1MB per minute).
{%- endtrans %}</li>
</ul>
<h2>{% trans %}See Also{% endtrans %}</h2>
<ul>
<li>
<a href="{{ site_url('docs/tunnels/implementation') }}">{% trans %}Tunnel specification{% endtrans %}</a>
</li><li>
<a href="{{ site_url('docs/spec/tunnel-creation') }}">{% trans %}Tunnel creation specification{% endtrans %}</a>
</li><li>
<a href="{{ site_url('docs/tunnels/unidirectional') }}">{% trans %}Unidirectional tunnels{% endtrans %}</a>
</li><li>
<a href="{{ site_url('docs/spec/tunnel-message') }}">{% trans %}Tunnel message specification{% endtrans %}</a>
</li><li>
<a href="{{ site_url('docs/how/garlic-routing') }}">{% trans %}Garlic routing{% endtrans %}</a>
</li><li>
<a href="{{ site_url('docs/how/elgamal-aes') }}">{% trans %}ElGamal/AES+SessionTag{% endtrans %}</a>
</li><li>
<a href="{{ site_url('docs/protocol/i2cp') }}#options">{% trans %}I2CP options{% endtrans %}</a>
</li>
</ul>
{% endblock %}

View File

@@ -0,0 +1,241 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Index to Technical Documentation{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}May 2013{% endtrans %}{% endblock %}
{% block accuratefor %}0.9.6{% endblock %}
{% block content %}
<h1>{% trans %}How does I2P work{% endtrans %}</h1>
<p>{% trans -%}
Following is an index to the technical documentation for I2P.
{%- endtrans %}</p>
<p>{% trans -%}
This index is ordered from the highest to lowest layers.
The higher layers are for "clients" or applications;
the lower layers are inside the router itself.
The interface between applications and the router is the I2CP (I2P Control Protocol) API.
{%- endtrans %}</p>
<p>{% trans trac=i2pconv('trac.i2p2.i2p') -%}
The I2P Project is committed to maintaining accurate, current documentation.
If you find any inaccuracies in the documents linked below, please
<a href="http://{{ trac }}/report/1">enter a ticket identifying the problem</a>.
{%- endtrans %}</p>
<h2>{% trans %}Index to Technical Documentation{% endtrans %}</h2>
<h3>{% trans %}Overview{% endtrans %}</h3>
<ul class="helplist">
<li><a href="{{ site_url('docs/how/tech-intro') }}">{{ _('Technical Introduction') }}</a></li>
<li><a href="{{ site_url('docs/how/intro') }}">{{ _('A Less-Technical Introduction') }}</a></li>
<li><a href="{{ site_url('docs/how/threat-model') }}">{{ _('Threat model and analysis') }}</a></li>
<li><a href="{{ site_url('comparison') }}">{{ _('Comparisons to other anonymous networks') }}</a></li>
<li><a href="{{ site_url('docs/protocol') }}">{{ _('Protocol stack chart') }}</a></li>
<li><a href="{{ site_url('research/papers') }}">{{ _('Papers on I2P') }}</a></li>
<li>{% trans pdf=url_for('static', filename='pdf/i2p_philosophy.pdf') %}<a href="{{ pdf }}">Invisible Internet Project (I2P) Project Overview</a> August 28, 2003 (pdf){% endtrans %}</li>
</ul>
<h3>{% trans %}Application-Layer Topics{% endtrans %}</h3>
<ul>
<li><a href="{{ site_url('get-involved/develop/applications') }}">Application Development Overview and Guide</a></li>
<li><a href="{{ site_url('docs/naming') }}">{{ _('Naming and Addressbook') }}</a></li>
<li><a href="{{ site_url('docs/plugins') }}">{{ _('Plugins Overview') }}</a></li>
<li><a href="{{ site_url('docs/spec/plugin') }}">{{ _('Plugin Specification') }}</a></li>
<li><a href="{{ site_url('docs/spec/updates') }}">{{ _('Router software updates') }}</a></li>
<li><a href="{{ site_url('docs/applications/bittorrent') }}">{{ _('Bittorrent over I2P') }}</a></li>
<li><a href="{{ site_url('docs/api/i2pcontrol') }}">{{ _('I2PControl Plugin API') }}</a></li>
<li><a href="{{ site_url('docs/spec/blockfile') }}">{{ _('hostsdb.blockfile Format') }}</a></li>
<li><a href="{{ site_url('docs/spec/configuration') }}">{{ _('Configuration File Format') }}</a></li>
</ul>
<h3>{% trans %}Application Layer API and Protocols{% endtrans %}</h3>
{% trans %}High-level, easy-to-use APIs for applications written in any language to send and receive data.{% endtrans %}
<ul><li>
<a href="{{ site_url('get-involved/develop/applications') }}">{{ _('Application Development Overview and Guide') }}</a>
</li><li>
<a href="{{ site_url('docs/api/i2ptunnel') }}">I2PTunnel</a>
</li><li>
<a href="{{ site_url('docs/api/socks') }}">SOCKS Proxy</a>
</li><li>
HTTP Proxy
</li><li>
CONNECT Proxy
</li><li>
IRC Proxy
</li><li>
SOCKS IRC Proxy
</li><li>
Streamr Proxy
</li><li>
HTTP Bidir Proxy
</li><li>
<a href="{{ site_url('docs/api/sam') }}">{{ _('SAM Protocol') }}</a>
</li><li>
<a href="{{ site_url('docs/api/samv2') }}">{{ _('SAMv2 Protocol') }}</a>
</li><li>
<a href="{{ site_url('docs/api/samv3') }}">{{ _('SAMv3 Protocol') }}</a>
</li><li>
<a href="{{ site_url('docs/api/bob') }}">{{ _('BOB Protocol') }}</a>
</li></ul>
<h3>{% trans %}End-to-End Transport API and Protocols{% endtrans %}</h3>
{% trans %}The end-to-end protocols used by clients for reliable and unreliable communication.{% endtrans %}
<ul><li>
<a href="{{ site_url('docs/api/streaming') }}">{{ _('Streaming Library') }}</a>
</li><li>
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/client/streaming/package-summary.html">{{ _('Streaming Javadoc') }}</a>
</li><li>
<a href="{{ site_url('docs/spec/datagrams') }}">{{ _('Datagrams') }}</a>
</li><li>
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/client/datagram/package-summary.html">{{ _('Datagram Javadoc') }}</a>
</li></ul>
<h3>{% trans %}Client-to-Router Interface API and Protocol{% endtrans %}</h3>
{% trans -%}
The lowest-level API used for clients (applications) to send and receive traffic to a router.
Traditionally used only by Java applications and higher-level APIs.
{%- endtrans %}
<ul><li>
<a href="{{ site_url('docs/protocol/i2cp') }}">{{ _('I2CP - I2P Control Protocol / API overview') }}</a>
</li><li>
<a href="{{ site_url('docs/spec/i2cp') }}">{{ _('I2CP Specification') }}</a>
</li><li>
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/client/package-summary.html">{{ _('I2CP API Javadoc') }}</a>
</li><li>
<a href="{{ site_url('docs/spec/common-structures') }}">{{ _('Common data structures specification') }}</a>
</li><li>
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/package-summary.html">{{ _('Data Structures Javadoc') }}</a>
</li></ul>
<h3>{% trans %}End-to-End Encryption{% endtrans %}</h3>
{% trans %}How client messages are end-to-end encrypted by the router.{% endtrans %}
<ul>
<li><a href="{{ site_url('docs/how/elgamal-aes') }}">{{ _('ElGamal/AES+SessionTag encryption') }}</a></li>
<li><a href="{{ site_url('docs/how/cryptography') }}">{{ _('ElGamal and AES cryptography details') }}</a></li>
</ul>
<h3>{% trans %}Network Database{% endtrans %}</h3>
{% trans %}Distributed storage and retrieval of information about routers and clients.{% endtrans %}
<ul>
<li><a href="{{ site_url('docs/how/network-database') }}">{{ _('Network database overview, details, and threat analysis') }}</a></li>
<li><a href="{{ site_url('docs/how/cryptography') }}#SHA256">{{ _('Cryptographic hashes') }}</a></li>
<li><a href="{{ site_url('docs/how/cryptography') }}#DSA">{{ _('Cryptographic signatures') }}</a></li>
</ul>
<h3>{% trans %}Router Message Protocol{% endtrans %}</h3>
{% trans %}I2P is a message-oriented router. The messages sent between routers are defined by the I2NP protocol.{% endtrans %}
<ul><li>
<a href="{{ site_url('docs/protocol/i2np') }}">{{ _('I2NP - I2P Network Protocol Overview') }}</a>
</li><li>
<a href="{{ site_url('docs/spec/i2np') }}">{{ _('I2NP Specification') }}</a>
</li><li>
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/i2np/package-summary.html">{{ _('I2NP Javadoc') }}</a>
</li><li>
<a href="{{ site_url('docs/spec/common-structures') }}">{{ _('Common data structures specification') }}</a>
</li><li>
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/package-summary.html">{{ _('Data Structures Javadoc') }}</a>
</li></ul>
<h3>{% trans %}Tunnels{% endtrans %}</h3>
{% trans %}Selecting peers, requesting tunnels through those peers, and encrypting and routing messages through these tunnels.{% endtrans %}
<ul>
<li><a href="{{ site_url('docs/how/peer-selection') }}">{{ _('Peer profiling and selection') }}</a></li>
<li><a href="{{ site_url('docs/how/tunnel-routing') }}">{{ _('Tunnel routing overview') }}</a></li>
<li><a href="{{ site_url('docs/how/garlic-routing') }}">{% trans %}Garlic routing and "garlic" terminology{% endtrans %}</a></li>
<li><a href="{{ site_url('docs/tunnels/implementation') }}">{{ _('Tunnel building and encryption') }}</a></li>
<li><a href="{{ site_url('docs/how/elgamal-aes') }}">{{ _('ElGamal/AES') }}</a> {{ _('for build request encryption') }}</li>
<li><a href="{{ site_url('docs/how/cryptography') }}">{{ _('ElGamal and AES cryptography details') }}</a></li>
<li><a href="{{ site_url('docs/spec/tunnel-creation') }}">{{ _('Tunnel building specification') }}</a></li>
<li><a href="{{ site_url('docs/spec/tunnel-message') }}">{{ _('Low-level tunnel message specification') }}</a></li>
<li><a href="{{ site_url('docs/tunnels/unidirectional') }}">{{ _('Unidirectional Tunnels') }}</a></li>
<li><a href="{{ url_for('static', filename='pdf/I2P-PET-CON-2009.1.pdf') }}">{{ _('Peer Profiling and Selection in the I2P Anonymous Network') }}</a>
{{ _('2009 paper (pdf), not current but still generally accurate') }}</li>
</ul>
<h3>{% trans %}Transport Layer{% endtrans %}</h3>
{% trans %}The protocols for direct (point-to-point) router to router communication.{% endtrans %}
<ul><li>
<a href="{{ site_url('docs/transport') }}">{{ _('Transport layer overview') }}</a>
</li><li>
<a href="{{ site_url('docs/transport/ntcp') }}">NTCP</a> {{ _('TCP-based transport overview and specification') }}
</li><li>
<a href="{{ site_url('docs/transport/ssu') }}">SSU</a> {{ _('UDP-based transport overview') }}
</li><li>
<a href="{{ site_url('docs/spec/ssu') }}">{{ _('SSU specification') }}</a>
</li><li>
<a href="{{ site_url('docs/how/cryptography') }}#tcp">{{ _('NTCP transport encryption') }}</a>
</li><li>
<a href="{{ site_url('docs/how/cryptography') }}#udp">{{ _('SSU transport encryption') }}</a>
</li><li>
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/router/transport/package-summary.html">{{ _('Transport Javadoc') }}</a>
</li><li>
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/router/transport/ntcp/package-summary.html">{{ _('NTCP Javadoc') }}</a>
</li><li>
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/router/transport/udp/package-summary.html">{{ _('SSU Javadoc') }}</a>
</li></ul>
<h3>{% trans %}Other Router Topics{% endtrans %}</h3>
<ul><li>
<a href="{{ site_url('misc/jbigi') }}">{{ _('Native BigInteger Library') }}</a>
</li><li>
{{ _('Time synchronization and NTP') }}
</li><li>
<a href="{{ site_url('about/performance') }}">{{ _('Performance') }}</a>
</li><li>
<a href="{{ site_url('docs/spec/configuration') }}">{{ _('Configuration File Format') }}</a></li>
</li><li>
<a href="{{ site_url('docs/spec/geoip') }}">GeoIP File Format</a></li>
</li></ul>
<h3>{% trans %}Developer's Guides and Resources{% endtrans %}</h3>
<ul><li>
<a href="{{ site_url('get-involved/guides/new-developers') }}">{% trans %}New Developer's Guide{% endtrans %}</a>
</li><li>
<a href="{{ site_url('get-involved/guides/new-translators') }}">{% trans %}New Translator's Guide{% endtrans %}</a>
</li><li>
<a href="{{ site_url('get-involved/guides/monotone') }}">{{ _('Monotone Guide') }}</a>
</li><li>
<a href="{{ site_url('get-involved/guides/dev-guidelines') }}">{{ _('Developer Guidelines') }}</a>
</li><li>
{% trans %}Javadocs on the standard internet:{% endtrans %}
<a href="http://docs.i2p-projekt.de/javadoc/">{% trans num=1 %}Server {{ num }}{% endtrans %}</a>
{% trans %}Note: always verify that javadocs are current by checking the release number.{% endtrans %}
</li><li>
{% trans %}Javadocs inside I2P:{% endtrans %}
<a href="http://{{ i2pconv('i2p-javadocs.i2p') }}">{% trans num=1 %}Server {{ num }}{% endtrans %}</a>
<a href="http://{{ i2pconv('i2pdocs.str4d.i2p') }}/i2p.i2p/javadoc/">{% trans num=2 %}Server {{ num }}{% endtrans %}</a>
<a href="http://{{ i2pconv('echelon.i2p') }}/javadoc/">{% trans num=3 %}Server {{ num }}{% endtrans %}</a>
<!--
<a href="http://{{ i2pconv('docs.i2p2.i2p') }}/javadoc/">Server 4 - out of date, incomplete</a>
-->
{% trans %}Note: always verify that javadocs are current by checking the release number.{% endtrans %}
</li><li>
<a href="{{ site_url('docs/ports') }}">{{ _('Ports used by I2P') }}</a>
</li><li>
<a href="http://{{ i2pconv('update.killyourtv.i2p') }}/mtn/">{{ _('Automatic updates to development builds inside I2P') }}</a>
</li><li>
<a href="{{ site_url('misc/manual-wrapper') }}">{{ _('Updating the wrapper manually') }}</a>
</li><li>
<a href="http://{{ i2pconv('forum.i2p') }}">{{ _('User forum') }}</a>
</li><li>
<a href="http://{{ i2pconv('zzz.i2p') }}/">{{ _('Developer forum inside I2P') }}</a>
</li><li>
<a href="http://{{ i2pconv('trac.i2p2.i2p') }}/report/1">{{ _('Bug tracker') }}</a>
</li><li>
<a href="http://{{ i2pconv('killyourtv.i2p') }}/viewmtn/">{{ _('Viewmtn inside I2P') }}</a>.
</li><li>
<a href="https://github.com/i2p/i2p.i2p">{{ _('I2P Source exported to GitHub') }}</a>
</li><li>
<a href="http://{{ i2pconv('git.repo.i2p') }}/w/i2p.i2p.git">{{ _('I2P Source Git Repo inside I2P') }}</a>
</li><li>
<a href="https://www.transifex.net/projects/p/I2P/">{{ _('Source translation at Transifex') }}</a>
</li><li>
<a href="http://{{ i2pconv('trac.i2p2.i2p') }}/wiki/Roadmaps/1.0">{{ _('Roadmap wiki') }}</a>
</li><li>
<a href="{{ site_url('get-involved/roadmap') }}">{{ _('Old roadmap') }}</a> ({{ _('not current') }})
</li><li>
<a href="{{ site_url('get-involved/todo') }}">{{ _('To Do List') }}</a> ({{ _('not current') }})
</li></ul>
{% endblock %}

View File

@@ -0,0 +1,425 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Naming and Addressbook{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}March 2012{% endtrans %}{% endblock %}
{% block accuratefor %}0.8.13{% endblock %}
{% block content %}
<h1>{% trans %}Naming in I2P{% endtrans %}</h1>
<h2 id="overview">{% trans %}Overview{% endtrans %}</h2>
<p>{% trans -%}
I2P ships with a generic naming library and a base implementation
designed to work off a local name to destination mapping, as well as an
add-on application called the <a href="#addressbook">addressbook</a>.
I2P also supports <a href="#base32">Base32 hostnames</a> similar to Tor's .onion addresses.
{%- endtrans %}</p>
<p>{% trans -%}
The addressbook is a web-of-trust
driven secure, distributed, and human readable naming system, sacrificing only
the call for all human readable names to be globally unique by mandating only
local uniqueness. While all messages in I2P are cryptographically addressed
by their destination, different people can have local addressbook entries for
"Alice" which refer to different destinations. People can still discover new
names by importing published addressbooks of peers specified in their web of trust,
by adding in the entries provided through a third party, or (if some people organize
a series of published addressbooks using a first come first serve registration
system) people can choose to treat these addressbooks as name servers, emulating
traditional DNS.
{%- endtrans %}</p>
<p>{% trans namingdiscussion=site_url('docs/discussions/naming') -%}
NOTE: For the reasoning behind the I2P naming system, common arguments against it
and possible alternatives see the <a href="{{ namingdiscussion }}">naming discussion</a>
page.
{%- endtrans %}</p>
<h2 id="components">{% trans %}Naming System Components{% endtrans %}</h2>
<p>{% trans -%}
There is no central naming authority in I2P.
All hostnames are local.
{%- endtrans %}</p>
<p>{% trans -%}
The naming system is quite simple and most of it is implemented
in applications external to the router, but bundled with
the I2P distribution.
The components are:
{%- endtrans %}</p>
<ol>
<li>{% trans -%}
The <a href="#lookup">client application</a> which does local lookups in hosts.txt
and also takes care of the <a href="#base32">Base32 hostnames</a>.
{%- endtrans %}</li>
<li>{% trans -%}
The <a href="#httpproxy">HTTP proxy</a> which asks the router for lookups and points
the user to remote jump services to assist with failed lookups.
{%- endtrans %}</li>
<li>{% trans -%}
HTTP <a href="#add-services">host-add forms</a> which allow users to add hosts to their local hosts.txt
{%- endtrans %}</li>
<li>{% trans -%}
HTTP <a href="#jump-services">jump services</a> which provide their own lookups and redirection.
{%- endtrans %}</li>
<li>{% trans -%}
The <a href="#addressbook">addressbook</a> application which merges external
host lists, retrieved via HTTP, with the local list.
{%- endtrans %}</li>
<li>{% trans -%}
The <a href="#susidns">SusiDNS</a> application which is a simple web front-end
for addressbook configuration and viewing of the local host lists.
{%- endtrans %}</li>
</ol>
<h2 id="lookup">{% trans %}Naming Files and Lookups{% endtrans %}</h2>
<p>{% trans namingdiscussion=site_url('docs/discussions/naming'), todo=site_url('get-involved/todo') -%}
All destinations in I2P are 516-byte (or longer) keys.
(To be more precise, it is a 256-byte public key plus a 128-byte signing key
plus a null certificate, which in Base64 representation is 516 bytes.
<a href="{{ namingdiscussion }}#certificates">Certificates</a> are not used now,
if they are, the keys will be longer.
One possible use of certificates is for <a href="{{ todo }}#hashcash">proof of work</a>.)
{%- endtrans %}</p>
<p>{% trans -%}
If an application (i2ptunnel or the HTTP proxy) wishes to access
a destination by name, the router does a very simple local lookup
to resolve that name.
The client application (technically, the client side of I2CP in the I2P API)
does a linear search through three local files, in order, to
look up host names and convert them to a 516-byte destination key:
{%- endtrans %}</p>
<ol>
<li>privatehosts.txt
<li>userhosts.txt
<li>hosts.txt
</ol>
<p>{% trans -%}
The lookup is case-insensitive.
The first match is used, and conflicts are not detected.
There is no enforcement of naming rules in lookups.
{%- endtrans %}</p>
<p>{% trans namingdiscussion=site_url('docs/discussions/naming') -%}
Lookups are cached for a few minutes.
There is an experimental facility for real-time lookups (a la DNS) over the network within the router,
although it is not enabled by default
(see "EepGet" under <a href="{{ namingdiscussion }}#alternatives">Alternatives on the discussion page</a>).
{%- endtrans %}</p>
<h2 id="httpproxy">{% trans %}HTTP Proxy{% endtrans %}</h2>
<p>{% trans -%}
The HTTP proxy does a lookup via the router for all hostnames ending in '.i2p'.
Otherwise, it forwards the request to a configured HTTP outproxy.
Thus, in practice, all HTTP (eepsite) hostnames must end in the pseudo-Top Level Domain '.i2p'.
{%- endtrans %}</p>
<p>{% trans -%}
If the router fails to resolve the hostname, the HTTP proxy returns
an error page to the user with links to several "jump" services.
See below for details.
{%- endtrans %}</p>
<h2 id="addressbook">{% trans %}Addressbook{% endtrans %}</h2>
<h3>{% trans %}Incoming Subscriptions and Merging{% endtrans %}</h3>
<p>{% trans -%}
The addressbook application periodically
retrieves other users' hosts.txt files and merges
them with the local hosts.txt, after several checks.
Naming conflicts are resolved on a first-come first-served
basis.
{%- endtrans %}</p>
<p>{% trans -%}
Subscribing to another user's hosts.txt file involves
giving them a certain amount of trust.
You do not want them, for example, 'hijacking' a new site
by quickly entering in their own key for a new site before
passing the new host/key entry to you.
{%- endtrans %}</p>
<p>{% trans -%}
For this reason, the only subscription configured by
default is <code>http://www.i2p2.i2p/hosts.txt</code>,
which contains a copy of the hosts.txt included
in the I2P release.
Users must configure additional subscriptions in their
local addressbook application (via subscriptions.txt or <a href="#susidns">SusiDNS</a>).
{%- endtrans %}</p>
<p>{% trans -%}
Some other public addressbook subscription links:
{%- endtrans %}</p>
<ul>
<li><a href="http://{{ i2pconv('i2host.i2p') }}/cgi-bin/i2hostetag">http://{{ i2pconv('i2host.i2p') }}/cgi-bin/i2hostetag</a>
<li><a href="http://{{ i2pconv('stats.i2p') }}/cgi-bin/newhosts.txt">http://{{ i2pconv('stats.i2p') }}/cgi-bin/newhosts.txt</a>
</ul>
<p>{% trans -%}
The operators of these services may have various policies for listing hosts.
Presence on this list does not imply endorsement.
{%- endtrans %}</p>
<h3>{% trans %}Naming Rules{% endtrans %}</h3>
<p>{% trans -%}
While there are hopefully not any technical limitations within I2P on host names,
the addressbook enforces several restrictions on host names
imported from subscriptions.
It does this for basic typographical sanity and compatibility with browsers,
and for security.
The rules are essentially the same as those in RFC2396 Section 3.2.2.
Any hostnames violating these rules may not be propagated
to other routers.
{%- endtrans %}</p>
<p>{% trans -%}
Naming Rules
{%- endtrans %}:</p>
<ul>
<li>{% trans -%}
Names are converted to lower case on import.
{%- endtrans %}</li>
<li>{% trans -%}
Names are checked for conflict with existing names in the existing userhosts.txt and hosts.txt
(but not privatehosts.txt) after conversion to lower case.
{%- endtrans %}</li>
<li>{% trans -%}
Must contain only [a-z] [0-9] '.' and '-' after conversion to lower case.
{%- endtrans %}</li>
<li>{% trans -%}
Must not start with '.' or '-'.
{%- endtrans %}</li>
<li>{% trans -%}
Must end with '.i2p'.
{%- endtrans %}</li>
<li>{% trans -%}
67 characters maximum, including the '.i2p'.
{%- endtrans %}</li>
<li>{% trans -%}
Must not contain '..'.
{%- endtrans %}</li>
<li>{% trans -%}
Must not contain '.-' or '-.' (as of 0.6.1.33).
{%- endtrans %}</li>
<li>{% trans -%}
Must not contain '--' except in 'xn--' for IDN.
{%- endtrans %}</li>
<li>{% trans -%}
Base32 hostnames (*.b32.i2p) are not allowed.
{%- endtrans %}</li>
<li>{% trans -%}
Certain hostnames reserved for project use are not allowed
(proxy.i2p, router.i2p, console.i2p, *.proxy.i2p, *.router.i2p, *.console.i2p, and others)
{%- endtrans %}</li>
<li>{% trans -%}
Keys are checked for base64 validity.
{%- endtrans %}</li>
<li>{% trans -%}
Keys are checked for conflict with existing keys in hosts.txt (but not privatehosts.txt).
{%- endtrans %}</li>
<li>{% trans -%}
Minimum key length 516 bytes.
{%- endtrans %}</li>
<li>{% trans -%}
Maximum key length 616 bytes (to account for certs up to 100 bytes).
{%- endtrans %}</li>
</ul>
<p>{% trans -%}
Any name received via subscription that passes all the checks is added to the local hosts.txt.
{%- endtrans %}</p>
<p>{% trans -%}
Note that the '.' symbols in a host name are of no significance,
and do not denote any actual naming or trust hierarchy.
If the name 'host.i2p' already exists, there is nothing
to prevent anybody from adding a name 'a.host.i2p' to their hosts.txt,
and this name can be imported by others' addressbook.
Methods to deny subdomains to non-domain 'owners' (certificates?),
and the desirability and feasibility of these methods,
are topics for future discussion.
{%- endtrans %}</p>
<p>{% trans -%}
International Domain Names (IDN) also work in i2p (using punycode 'xn--' form).
To see IDN .i2p domain names rendered correctly in Firefox's location bar,
add 'network.IDN.whitelist.i2p (boolean) = true' in about:config.
{%- endtrans %}</p>
<p>{% trans -%}
As the addressbook application does not use privatehosts.txt at all, in practice
this file is the only place where it is appropriate to place private aliases or
"pet names" for sites already in hosts.txt.
{%- endtrans %}</p>
<h3>{% trans %}Outgoing Subscriptions{% endtrans %}</h3>
<p>{% trans -%}
Addressbook will publish the merged hosts.txt to a location
(traditionally hosts.txt in the local eepsite's home directory) to be accessed by others
for their subscriptions.
This step is optional and is disabled by default.
{%- endtrans %}</p>
<h3>Hosting and HTTP Transport Issues</h3>
<p>{% trans -%}
The addressbook application, together with eepget, saves the Etag and/or Last-Modified
information returned by the web server of the subscription.
This greatly reduces the bandwidth required, as the web server will
return a '304 Not Modified' on the next fetch if nothing has changed.
{%- endtrans %}</p>
<p>{% trans -%}
However the entire hosts.txt is downloaded if it has changed.
See below for discussion on this issue.
{%- endtrans %}</p>
<p>{% trans -%}
Hosts serving a static hosts.txt or an equivalent CGI application
are strongly encouraged to deliver
a Content-Length header, and either an Etag or Last-Modified header.
Also ensure that the server delivers a '304 Not Modified' when appropriate.
This will dramatically reduce the network bandwidth, and
reduce chances of corruption.
{%- endtrans %}</p>
<h2 id="add-services">{% trans %}Host Add Services{% endtrans %}</h2>
<p>{% trans -%}
A host add service is a simple CGI application that takes a hostname and a Base64 key as parameters
and adds that to its local hosts.txt.
If other routers subscribe to that hosts.txt, the new hostname/key
will be propagated through the network.
{%- endtrans %}</p>
<p>{% trans -%}
It is recommended that host add services impose, at a minimum, the restrictions imposed by the addressbook application listed above.
Host add services may impose additional restrictions on hostnames and keys, for example:
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
A limit on number of 'subdomains'.
{%- endtrans %}</li>
<li>{% trans -%}
Authorization for 'subdomains' through various methods.
{%- endtrans %}</li>
<li>{% trans -%}
Hashcash or signed certificates.
{%- endtrans %}</li>
<li>{% trans -%}
Editorial review of host names and/or content.
{%- endtrans %}</li>
<li>{% trans -%}
Categorization of hosts by content.
{%- endtrans %}</li>
<li>{% trans -%}
Reservation or rejection of certain host names.
{%- endtrans %}</li>
<li>{% trans -%}
Restrictions on the number of names registered in a given time period.
{%- endtrans %}</li>
<li>{% trans -%}
Delays between registration and publication.
{%- endtrans %}</li>
<li>{% trans -%}
Requirement that the host be up for verification.
{%- endtrans %}</li>
<li>{% trans -%}
Expiration and/or revocation.
{%- endtrans %}</li>
<li>{% trans -%}
IDN spoof rejection.
{%- endtrans %}</li>
</ul>
<h2 id="jump-services">{% trans %}Jump Services{% endtrans %}</h2>
<p>{% trans -%}
A jump service is a simple CGI application that takes a hostname as a parameter
and returns a 301 redirect to the proper URL with a <code>?i2paddresshelper=key</code>
string appended.
The HTTP proxy will interpret the appended string and
use that key as the actual destination.
In addition, the proxy will cache that key so the
address helper is not necessary until restart.
{%- endtrans %}</p>
<p>{% trans -%}
Note that, like with subscriptions, using a jump service
implies a certain amount of trust, as a jump service could maliciously
redirect a user to an incorrect destination.
{%- endtrans %}</p>
<p>{% trans -%}
To provide the best service, a jump service should be subscribed to
several hosts.txt providers so that its local host list is current.
{%- endtrans %}</p>
<h2 id="susidns">SusiDNS</h2>
<p>{% trans -%}
SusiDNS is simply a web interface front-end to configuring addressbook subscriptions
and accessing the four addressbook files.
All the real work is done by the 'addressbook' application.
{%- endtrans %}</p>
<p>{% trans -%}
Currently, there is little enforcement of addressbook naming rules within SusiDNS,
so a user may enter hostnames locally that would be rejected by
the addressbook subscription rules.
{%- endtrans %}</p>
<h2 id="base32">{% trans %}Base32 Names{% endtrans %}</h2>
<p>{% trans -%}
I2P supports Base32 hostnames similar to Tor's .onion addresses.
Base32 addresses are much shorter and easier to handle than the
full 516-character Base64 Destinations or addresshelpers.
Example: <code>ukeu3k5oycgaauneqgtnvselmt4yemvoilkln7jpvamvfx7dnkdq.b32.i2p</code>
{%- endtrans %}</p>
<p>{% trans -%}
In Tor, the address is 16 characters (80 bits), or half of the SHA-1 hash.
I2P uses 52 characters (256 bits) to represent the full SHA-256 hash.
The form is {52 chars}.b32.i2p.
Base32 is implemented in the naming service, which queries the
router over I2CP to lookup the LeaseSet to get the full Destination.
Base32 lookups will only be successful when the Destination is up and publishing
a LeaseSet.
Because resolution may require a network database lookup, it may take significantly
longer than a local address book lookup.
{%- endtrans %}</p>
<p>{% trans -%}
Base32 addresses can be used in most places where hostnames or full destinations
are used, however there are some exceptions where they may fail if the
name does not immediately resolve. I2PTunnel will fail, for example, if
the name does not resolve to a destination.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,194 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Plugins{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}June 2012{% endtrans %}{% endblock %}
{% block accuratefor %}0.9{% endblock %}
{% block content %}
<h2>{% trans %}I2P Plugins{% endtrans %}</h2>
<h3>{% trans %}General Information{% endtrans %}</h3>
<p>{% trans -%}
I2P includes a plugin architecture
to support easy development and installation of additional software.
{%- endtrans %}</p>
<p>{% trans -%}
There are now plugins available that support distributed email, blogs, IRC
clients, distributed file storage, wikis, and more.
{%- endtrans %}</p>
<p>{% trans -%}
Benefits to i2p users and app developers:
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
Easy distribution of applications
{%- endtrans %}</li>
<li>{% trans -%}
Allows innovation and use of additional libraries without worrying about
increasing the size of <code>i2pupdate.sud</code>
{%- endtrans %}</li>
<li>{% trans -%}
Support large or special-purpose applications that would never be bundled
with the I2P installation
{%- endtrans %}</li>
<li>{% trans -%}
Cryptographically signed and verified applications
{%- endtrans %}</li>
<li>{% trans -%}
Automatic updates of applications, just like for the router
{%- endtrans %}</li>
<li>{% trans -%}
Separate initial install and update packages, if desired, for smaller update downloads
{%- endtrans %}</li>
<li>{% trans -%}
One-click installation of applications. No more asking users to modify
<code>wrapper.config</code> or <code>clients.config</code>
{%- endtrans %}</li>
<li>{% trans -%}
Isolate applications from the base <code>$I2P</code> installation
{%- endtrans %}</li>
<li>{% trans -%}
Automatic compatibility checking for I2P version, Java version, Jetty
version, and previous installed application version
{%- endtrans %}</li>
<li>{% trans -%}
Automatic link addition in console
{%- endtrans %}</li>
<li>{% trans -%}
Automatic startup of application, including modifying classpath, without requiring a restart
{%- endtrans %}</li>
<li>{% trans -%}
Automatic integration and startup of webapps into console Jetty instance
{%- endtrans %}</li>
<li>{% trans pluginsite=i2pconv('plugins.i2p') -%}
Facilitate creation of 'app stores' like the one at
<a href="http://{{ pluginsite }}">{{ pluginsite }}</a>
{%- endtrans %}</li>
<li>{% trans -%}
One-click uninstall
{%- endtrans %}</li>
<li>{% trans -%}
Language and theme packs for the console
{%- endtrans %}</li>
<li>{% trans -%}
Bring detailed application information to the router console
{%- endtrans %}</li>
<li>{% trans -%}
Non-java applications also supported
{%- endtrans %}</li>
</ul>
<h4>{% trans %}Required I2P version{% endtrans %}</h4>
<p>{% trans %}0.7.12 or newer.{% endtrans %}</p>
<h4>{% trans %}Installation{% endtrans %}</h4>
<p>{% trans -%}
To install and start a plugin, copy the <code>.xpi2p</code> install link to
the form at the bottom of
<a href="http://127.0.0.1:7657/configclients.jsp#plugin">configclients.jsp in
your router console</a> and click the "install plugin" button. After a
plugin is installed and started, a link to the plugin will usually appear at
the top of your summary bar.
{%- endtrans %}</p>
<p>{% trans -%}
To update a plugin to the latest version, just click the update button on
<a href="http://127.0.0.1:7657/configclients.jsp#plugin">configclients.jsp</a>.
There is also a button to check if the plugin has a more recent version, as
well as a button to check for updates for all plugins. Plugins will be checked
for updates automatically when updating to a new I2P release (not including dev
builds).
{%- endtrans %}</p>
<h3>{% trans %}Development{% endtrans %}</h3>
<p>{% trans pluginspec=site_url('docs/spec/plugin'), zzz=i2pconv('zzz.i2p') -%}
See the latest <a href="{{ pluginspec }}">plugin specification</a> and the
<a href="http://{{ zzz }}/forums/16">plugin forum</a> on {{ zzz }}.
{%- endtrans %}</p>
<p>{% trans pluginsite=i2pconv('plugins.i2p') -%}
See also the sources for plugins developed by various people. Some plugins, such
as <a href="http://{{ pluginsite }}/plugins/snowman">snowman</a>, were developed
specifically as examples.
{%- endtrans %}</p>
<p>{% trans -%}
<b>Developers wanted!</b> Plugins are a great way to learn more about I2P
or easily add some feature.
{%- endtrans %}</p>
<h3>{% trans %}Getting Started{% endtrans %}</h3>
<p>{% trans url='http://'+i2pconv('trac.i2p2.i2p')+'/browser/plugin/makeplugin.sh?rev=776519571fda0689ef09c42f66e7398f30432e87' -%}
To create a plugin from an existing binary package you will need to get
makeplugin.sh from <a href="{{ url }}">the i2p.scripts branch in monotone</a>.
{%- endtrans %}</p>
<h3>{% trans %}Known Issues{% endtrans %}</h3>
<p>{% trans -%}
Note that the router's plugin architecture does <b>NOT</b> currently
provide any additional security isolation or sandboxing of plugins.
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
Updates of a plugin with included jars (not wars) won't be recognized if
the plugin was already run, as it requires class loader trickery to flush the
class cache; a full router restart is required.
{%- endtrans %}</li>
<li>{% trans -%}
The stop button may be displayed even if there is nothing to stop.
{%- endtrans %}</li>
<li>{% trans -%}
Plugins running in a separate JVM create a <code>logs/</code> directory in
<code>$CWD</code>.
{%- endtrans %}</li>
<li>{% trans -%}
No initial keys are present, except for those of jrandom and zzz (using the
same keys as for router update), so the first key seen for a signer is
automatically accepted&mdash;there is no signing key authority.
{%- endtrans %}</li>
<li>{% trans -%}
When deleting a plugin, the directory is not always deleted, especially on
Windows.
{%- endtrans %}</li>
<li>{% trans -%}
Installing a plugin requiring Java 1.6 on a Java 1.5 machine will result in a
"plugin is corrupt" message if pack200 compression of the plugin file is used.
{%- endtrans %}</li>
<li>{% trans -%}
Theme and translation plugins are untested.
{%- endtrans %}</li>
<li>{% trans -%}
Disabling autostart doesn't always work.
{%- endtrans %}</li>
</ul>
<!-- vim: set noai ff=unix nosi ft=html tw=79 et sw=4 ts=4 spell spelllang=en: -->
{% endblock %}

View File

@@ -0,0 +1,73 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Ports Used by I2P{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}May 2013{% endtrans %}{% endblock %}
{% block accuratefor %}0.9.6{% endblock %}
{% block content %}
<p>{% trans -%}
These are the ports used or reserved by I2P, including those for known plugins,
common alternates,
and some typical related applications.
{%- endtrans %}</p>
<p>{% trans faq=site_url('faq') -%}
Note that many of these are not enabled by default.
There is more information in <a href="{{ faq }}#ports">the FAQ</a>.
See also the documentation for individual plugins.
Plugin authors please add any ports you use here.
For new plugins, we recommend using the next available port
in the 766x range.
{%- endtrans %}</p>
<table>
<tr><th>Port</th><th>Usage</th></tr>
<tr><td>123</td><td>SNTP</td></tr>
<tr><td>1900</td><td>UPnP SSDP UDP multicast listener</td>
<tr><td>2827</td><td>BOB Bridge</td></tr>
<tr><td>3456</td><td>Tahoe-LAFS-Controller Plugin</td></tr>
<tr><td>3458</td><td>Tahoe-LAFS-Controller Plugin</td></tr>
<tr><td>3459</td><td>Tahoe-LAFS-Controller Plugin</td></tr>
<tr><td>4444</td><td>HTTP Proxy</td></tr>
<tr><td>4445</td><td>HTTPS Proxy</td></tr>
<tr><td>4691</td><td>Monotone Server (reserve)</td></tr>
<tr><td>6667</td><td>IRC Proxy (alt)</td></tr>
<tr><td>6668</td><td>IRC Proxy</td></tr>
<tr><td>6669</td><td>IRC Proxy (alt)</td></tr>
<tr><td>7650</td><td>I2PControl Plugin</td></tr>
<tr><td>7651</td><td>UPnP (alt - retries going down)</td></tr>
<tr><td>7652</td><td>UPnP HTTP TCP event listener</td></tr>
<tr><td>7653</td><td>UPnP SSDP UDP search response listener</td></tr>
<tr><td>7654</td><td>I2CP</td></tr>
<tr><td>7655</td><td>SAM Bridge (UDP)</td></tr>
<tr><td>7656</td><td>SAM Bridge (TCP)</td></tr>
<tr><td>7657</td><td>Router Console</td></tr>
<tr><td>7658</td><td>Eepsite</td></tr>
<tr><td>7659</td><td>SMTP Proxy</td></tr>
<tr><td>7660</td><td>POP Proxy</td></tr>
<tr><td>7661</td><td>Pebble Plugin</td></tr>
<tr><td>7661</td><td>I2PBote Plugin SMTP</td></tr>
<tr><td>7662</td><td>Zzzot Plugin</td></tr>
<tr><td>7662</td><td>I2PBote Plugin IMAP</td></tr>
<tr><td>7663</td><td>?? Plugin ??</td></tr>
<tr><td>7664</td><td>JAMWiki Plugin</td></tr>
<tr><td></td><td><i>{% trans %}recommended spot for new plugins/applications{% endtrans %}</i></td></tr>
<tr><td>8118</td><td>Privoxy (reserve)</td></tr>
<tr><td>8123</td><td>Tor Polipo (reserve)</td></tr>
<tr><td>8887</td><td>Old default network port</td></tr>
<tr><td>8888</td><td>Freenet (reserve)</td></tr>
<tr><td>8997</td><td>Monotone Proxy (alt)</td></tr>
<tr><td>8998</td><td>Monotone Proxy</td></tr>
<tr><td>8999</td><td>Monotone Proxy (alt)</td></tr>
<tr><td>9050</td><td>Tor SOCKS Proxy (reserve)</td></tr>
<tr><td>9051-9053</td><td>SOCKS Proxy (typ)</td></tr>
<tr><td>9111-30777</td><td>Network (random)</td></tr>
<tr><td>11371</td><td>SKS/GPG Key Server (reserve)</td></tr>
<tr><td>31000</td><td>Wrapper</td></tr>
<tr><td>31001-31999</td><td>Wrapper (alt - retries going up)</td>
<tr><td>32000</td><td>Wrapper</td></tr>
<tr><td>65534</td><td>Neodatis Plugin</td></tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,677 @@
{% extends "global/layout.html" %}
{% block title %}I2CP{% endblock %}
{% block lastupdated %}{% trans %}November 2012{% endtrans %}{% endblock %}
{% block accuratefor %}0.9.3{% endblock %}
{% block content %}
<p>{% trans -%}
The I2P Client Protocol (I2CP) exposes a strong separation of concerns between
the router and any client that wishes to communicate over the network. It enables
secure and asynchronous messaging by sending and receiving messages over a
single TCP socket, yet never exposing any private keys and authenticating itself
to the router only through signatures. With I2CP, a client application tells the
router who they are (their "destination"), what anonymity, reliability, and
latency tradeoffs to make, and where to send messages. In turn the router uses
I2CP to tell the client when any messages have arrived, and to request authorization
for some tunnels to be used.
{%- endtrans %}</p>
<p>{% trans url='http://docs.i2p-projekt.de/javadoc/net/i2p/client/package-summary.html' -%}
The protocol itself has only been implemented in Java, to provide the
<a href="{{ url }}">Client SDK</a>.
This SDK is exposed in the i2p.jar package, which implements the client-side of I2CP.
Clients should never need to access the router.jar package, which contains the
router itself and the router-side of I2CP.
{%- endtrans %}</p>
<p>{% trans streaming=site_url('docs/api/streaming') -%}
While implementing the client side of I2CP in a non-Java language is certainly feasible,
a non-Java client would also have to implement the
<a href="{{ streaming }}">streaming library</a> for TCP-style connections.
Together, implementing I2CP and the streaming library would be a sizable task.
{%- endtrans %}</p>
<p>{% trans streaming=site_url('docs/api/streaming'), datagrams=site_url('docs/spec/datagrams'),
sam=site_url('docs/api/sam'), bob=site_url('docs/api/bob') -%}
Applications can take advantage of the base I2CP plus the
<a href="{{ streaming }}">streaming</a> and <a href="{{ datagrams }}">datagram</a> libraries
by using the <a href="{{ sam }}">Simple Anonymous Messaging</a> or <a href="{{ bob }}">BOB</a> protocols,
which do not require clients to deal with any sort of cryptography.
Also, clients may access the network by one of several proxies -
HTTP, CONNECT, and SOCKS 4/4a/5.
Alternatively, Java clients may access those libraries in ministreaming.jar and streaming.jar.
So there are several options for both Java and non-Java applications.
{%- endtrans %}</p>
<p>{% trans elgamalaes=site_url('docs/how/elgamal-aes'),
cryptography=site_url('docs/how/cryptography'),
i2cp=site_url('docs/spec/i2cp') -%}
Client-side end-to-end encryption (encrypting the data over the I2CP connection)
was disabled in I2P release 0.6,
leaving in place the <a href="{{ elgamalaes }}">ElGamal/AES end-to-end encryption</a>
which is implemented in the router.
The only cryptography that client libraries must still implement is
<a href="{{ cryptography }}#DSA">DSA public/private key signing</a>
for <a href="{{ i2cp }}#msg_CreateLeaseSet">LeaseSets</a> and
<a href="{{ i2cp }}#struct_SessionConfig">Session Configurations</a>, and management of those keys.
{%- endtrans %}</p>
<p>{% trans -%}
In a standard I2P installation, port 7654 is used by external java clients to communicate
with the local router via I2CP.
By default, the router binds to address 127.0.0.1. To bind to 0.0.0.0, set the
router advanced configuration option <tt>i2cp.tcp.bindAllInterfaces=true</tt> and restart.
Clients in the same JVM as the router pass messages directly to the router
through an internal JVM interface.
{%- endtrans %}</p>
<h2>{% trans %}I2CP Protocol Specification{% endtrans %}</h2>
<p>{% trans i2cp=site_url('docs/spec/i2cp') -%}
Now on the <a href="{{ i2cp }}">I2CP Specification page</a>.
{%- endtrans %}</p>
<h2>{% trans %}I2CP Initialization{% endtrans %}</h2>
<p>{% trans i2cp=site_url('docs/spec/i2cp') -%}
When a client connects to the router, it first sends a single protocol version byte (0x2A).
Then it sends a <a href="{{ i2cp }}#msg_GetDate">GetDate Message</a> and waits for the <a href="{{ i2cp }}#msg_SetDate">SetDate Message</a> response.
Next, it sends a <a href="{{ i2cp }}#msg_CreateSession">CreateSession Message</a> containing the session configuration.
It next awaits a <a href="{{ i2cp }}#msg_RequestLeaseSet">RequestLeaseSet Message</a> from the router, indicating that inbound tunnels
have been built, and responds with a CreateLeaseSetMessage containing the signed LeaseSet.
The client may now initiate or receive connections from other I2P destinations.
{%- endtrans %}</p>
<h2 id="options">{% trans %}I2CP Options{% endtrans %}</h2>
<p>{% trans i2cp=site_url('docs/spec/i2cp') -%}
The following options are traditionally passed to the router via
a <a href="{{ i2cp }}#struct_SessionConfig">SessionConfig</a> contained in a <a href="{{ i2cp }}#msg_CreateSession">CreateSession Message</a> or a <a href="{{ i2cp }}#msg_ReconfigureSession">ReconfigureSession Message</a>.
{%- endtrans %}</p>
<table border=1>
<tr>
<th colspan="6">{% trans %}Router-side Options{% endtrans %}</th>
</tr>
<tr>
<th>{% trans %}Option{% endtrans %}</th>
<th>{% trans %}As Of Release{% endtrans %}</th>
<th>{% trans %}Recommended Arguments{% endtrans %}</th>
<th>{% trans %}Allowable Range{% endtrans %}</th>
<th>{% trans %}Default{% endtrans %}</th>
<th>{% trans %}Description{% endtrans %}</th>
</tr>
<tr>
<td>inbound.quantity</td>
<td>&nbsp;</td>
<td>{% trans from=1, to=3 %}number from {{ from }} to {{ to }}{% endtrans %}</td>
<td>{% trans from=1, to=16 %}{{ from }} to {{ to }}{% endtrans %}</td>
<td>2</td>
<td>{% trans -%}
Number of tunnels in.
Limit was increased from 6 to 16 in release 0.9; however, numbers higher than 6 are not
currently recommended, as this is untested and is incompatible with older releases.
{%- endtrans %}</td>
</tr>
<tr>
<td>outbound.quantity
<td>&nbsp;</td>
<td>{% trans from=1, to=3 %}number from {{ from }} to {{ to }}{% endtrans %}</td>
<td>{% trans %}No limit{% endtrans %}</td>
<td>2
<td>{% trans %}Number of tunnels out{% endtrans %}</td>
</tr>
<tr>
<td>inbound.length
<td>&nbsp;</td>
<td>{% trans from=0, to=3 %}number from {{ from }} to {{ to }}{% endtrans %}</td>
<td>{% trans from=0, to=7 %}{{ from }} to {{ to }}{% endtrans %}</td>
<td>2
<td>{% trans %}Length of tunnels in{% endtrans %}</td>
</tr>
<tr>
<td>outbound.length
<td>&nbsp;</td>
<td>{% trans from=0, to=3 %}number from {{ from }} to {{ to }}{% endtrans %}</td>
<td>{% trans from=0, to=7 %}{{ from }} to {{ to }}{% endtrans %}</td>
<td>2
<td>{% trans %}Length of tunnels out{% endtrans %}</td>
</tr>
<tr>
<td>inbound.lengthVariance
<td>&nbsp;</td>
<td>{% trans from=-1, to=2 %}number from {{ from }} to {{ to }}{% endtrans %}</td>
<td>{% trans from=-7, to=7 %}{{ from }} to {{ to }}{% endtrans %}</td>
<td>0
<td>{% trans -%}
Random amount to add or subtract to the length of tunnels in.
A positive number x means add a random amount from 0 to x inclusive.
A negative number -x means add a random amount from -x to x inclusive.
The router will limit the total length of the tunnel to 0 to 7 inclusive.
The default variance was 1 prior to release 0.7.6.
{%- endtrans %}</td>
</tr>
<tr>
<td>outbound.lengthVariance
<td>&nbsp;</td>
<td>{% trans from=-1, to=2 %}number from {{ from }} to {{ to }}{% endtrans %}</td>
<td>{% trans from=-7, to=7 %}{{ from }} to {{ to }}{% endtrans %}</td>
<td>0
<td>{% trans -%}
Random amount to add or subtract to the length of tunnels out.
A positive number x means add a random amount from 0 to x inclusive.
A negative number -x means add a random amount from -x to x inclusive.
The router will limit the total length of the tunnel to 0 to 7 inclusive.
The default variance was 1 prior to release 0.7.6.
{%- endtrans %}</td>
</tr>
<tr>
<td>inbound.backupQuantity
<td>&nbsp;</td>
<td>{% trans from=0, to=3 %}number from {{ from }} to {{ to }}{% endtrans %}</td>
<td>{% trans %}No limit{% endtrans %}</td>
<td>0
<td>{% trans %}Number of redundant fail-over for tunnels in{% endtrans %}</td>
</tr>
<tr>
<td>outbound.backupQuantity
<td>&nbsp;</td>
<td>{% trans from=0, to=3 %}number from {{ from }} to {{ to }}{% endtrans %}</td>
<td>{% trans %}No limit{% endtrans %}</td>
<td>0
<td>{% trans %}Number of redundant fail-over for tunnels out{% endtrans %}</td>
</tr>
<tr>
<td>inbound.nickname
<td>&nbsp;</td>
<td>string
<td>&nbsp;
<td>&nbsp;
<td>{% trans -%}
Name of tunnel - generally used in routerconsole, which will
use the first few characters of the Base64 hash of the destination by default.
{%- endtrans %}</td>
</tr>
<tr>
<td>outbound.nickname
<td>&nbsp;</td>
<td>string
<td>&nbsp;
<td>&nbsp;
<td>{% trans %}Name of tunnel - generally ignored unless inbound.nickname is unset.{% endtrans %}</td>
</tr>
<tr>
<td>inbound.allowZeroHop
<td>&nbsp;</td>
<td>true, false
<td>&nbsp;
<td>true
<td>{% trans %}If incoming zero hop tunnel is allowed{% endtrans %}</td>
</tr>
<tr>
<td>outbound.allowZeroHop
<td>&nbsp;</td>
<td>true, false
<td>&nbsp;
<td>true
<td>{% trans %}If outgoing zero hop tunnel is allowed{% endtrans %}</td>
</tr>
<tr>
<td>inbound.IPRestriction
<td>&nbsp;</td>
<td>{% trans from=0, to=4 %}number from {{ from }} to {{ to }}{% endtrans %}</td>
<td>{% trans from=0, to=4 %}{{ from }} to {{ to }}{% endtrans %}</td>
<td>2
<td>{% trans -%}
Number of IP bytes to match to determine if
two routers should not be in the same tunnel. 0 to disable.
{%- endtrans %}</td>
</tr>
<tr>
<td>outbound.IPRestriction
<td>&nbsp;</td>
<td>{% trans from=0, to=4 %}number from {{ from }} to {{ to }}{% endtrans %}</td>
<td>{% trans from=0, to=4 %}{{ from }} to {{ to }}{% endtrans %}</td>
<td>2
<td>{% trans -%}
Number of IP bytes to match to determine if
two routers should not be in the same tunnel. 0 to disable.
{%- endtrans %}</td>
</tr>
<tr>
<td>outbound.priority
<td>0.9.4</td>
<td>{% trans from=-25, to=25 %}number from {{ from }} to {{ to }}{% endtrans %}</td>
<td>{% trans from=-25, to=25 %}{{ from }} to {{ to }}{% endtrans %}</td>
<td>0
<td>{% trans -%}
Priority adjustment for outbound messages.
Higher is higher priority.
{%- endtrans %}</td>
</tr>
<tr>
<td>i2cp.dontPublishLeaseSet
<td>&nbsp;</td>
<td>true, false
<td>&nbsp;
<td>false
<td>{% trans %}Should generally be set to true for clients and false for servers{% endtrans %}</td>
</tr>
<tr>
<td>i2cp.messageReliability
<td>&nbsp;</td>
<td>&nbsp;
<td>BestEffort, None
<td>BestEffort
<td>{% trans -%}
Guaranteed is disabled;
None implemented in 0.8.1; the streaming lib default is None as of 0.8.1, the client side default is None as of 0.9.4
{%- endtrans %}</td>
</tr>
<tr>
<td>i2cp.fastReceive
<td>0.9.4</td>
<td>&nbsp;
<td>true, false
<td>false
<td>{% trans -%}
If true, the router just sends the MessagePayload instead
of sending a MessageStatus and awaiting a ReceiveMessageBegin.
{%- endtrans %}</td>
</tr>
<tr>
<td>explicitPeers
<td>&nbsp;</td>
<td>&nbsp;
<td>&nbsp;
<td>null
<td>{% trans %}Comma-separated list of Base 64 Hashes of peers to build tunnels through; for debugging only{% endtrans %}</td>
</tr>
<tr>
<td>i2cp.username
<td>0.8.2</td>
<td>string
<td>&nbsp;
<td>&nbsp;
<td>{% trans -%}
For authorization, if required by the router.
If the client is running in the same JVM as a router, this option is not required.
{%- endtrans %}</td>
</tr>
<tr>
<td>i2cp.password
<td>0.8.2</td>
<td>string
<td>&nbsp;
<td>&nbsp;
<td>{% trans -%}
For authorization, if required by the router.
If the client is running in the same JVM as a router, this option is not required.
{%- endtrans %}</td>
</tr>
<tr>
<td>crypto.tagsToSend
<td>0.9.2</td>
<td>&nbsp;
<td>1-128
<td>40
<td>{% trans -%}
Number of ElGamal/AES Session Tags to send at a time.
For clients with relatively low bandwidth per-client-pair (IRC, some UDP apps), this may be set lower.
{%- endtrans %}</td>
</tr>
<tr>
<td>crypto.lowTagThreshold
<td>0.9.2</td>
<td>&nbsp;
<td>1-128
<td>30
<td>{% trans -%}
Minimum number of ElGamal/AES Session Tags before we send more.
Recommended: approximately tagsToSend * 2/3
{%- endtrans %}</td>
</tr>
<tr>
<td>shouldBundleReplyInfo
<td>0.9.2</td>
<td>true, false
<td>&nbsp;
<td>true
<td>{% trans -%}
Set to false to disable ever bundling a reply LeaseSet.
For clients that do not publish their LeaseSet, this option must be true
for any reply to be possible. "true" is also recommended for multihomed servers
with long connection times.
{%- endtrans %}
<p>{% trans -%}
Setting to "false" may save significant outbound bandwidth, especially if
the client is configured with a large number of inbound tunnels (Leases).
If replies are still required, this may shift the bandwidth burden to
the far-end client and the floodfill.
There are several cases where "false" may be appropriate:
{%- endtrans %}</p>
<ul>
<li>{% trans %}Unidirectional communication, no reply required{% endtrans %}</li>
<li>{% trans %}LeaseSet is published and higher reply latency is acceptable{% endtrans %}</li>
<li>{% trans -%}
LeaseSet is published, client is a "server", all connections are inbound
so the connecting far-end destination obviously has the leaseset already.
Connections are either short, or it is acceptable for latency on a long-lived
connection to temporarily increase while the other end re-fetches the LeaseSet
after expiration.
HTTP servers may fit these requirements.
{%- endtrans %}</li>
</ul>
</td>
</tr>
<tr>
<td>inbound.*
<td>&nbsp;</td>
<td>&nbsp;
<td>&nbsp;
<td>&nbsp;
<td>{% trans -%}
Any other options prefixed with "inbound." are stored
in the "unknown options" properties of the inbound tunnel pool's settings.
{%- endtrans %}</td>
</tr>
<tr>
<td>outbound.*
<td>&nbsp;</td>
<td>&nbsp;
<td>&nbsp;
<td>&nbsp;
<td>{% trans -%}
Any other options prefixed with "outbound." are stored
in the "unknown options" properties of the outbound tunnel pool's settings.
{%- endtrans %}</td>
</tr>
</table>
<p>{% trans -%}
Note: Large quantity, length, or variance settings may cause significant performance or reliability problems.
{%- endtrans %}</p>
<p>{% trans -%}
Note: As of release 0.7.7, option names and values must use UTF-8 encoding.
This is primarily useful for nicknames.
Prior to that release, options with multi-byte characters were corrupted.
{%- endtrans %}</p>
<p>{% trans -%}
The following options are interpreted on the client side,
and will be interpreted if passed to the I2PSession via the I2PClient.createSession() call.
The streaming lib should also pass these options through to I2CP.
Other implementations may have different defaults.
{%- endtrans %}</p>
<table border=1>
<tr>
<th colspan="6">{% trans %}Client-side Options{% endtrans %}</th></tr>
</tr>
<tr>
<th>{% trans %}Option{% endtrans %}</th>
<th>{% trans %}As Of Release{% endtrans %}</th>
<th>{% trans %}Recommended Arguments{% endtrans %}</th>
<th>{% trans %}Allowable Range{% endtrans %}</th>
<th>{% trans %}Default{% endtrans %}</th>
<th>{% trans %}Description{% endtrans %}</th>
</tr>
<tr>
<td>i2cp.tcp.host
<td>&nbsp;
<td>&nbsp;
<td>&nbsp;
<td>127.0.0.1
<td>{% trans -%}
Router hostname.
If the client is running in the same JVM as a router, this option is ignored, and the client connects to that router internally.
{%- endtrans %}</td>
</tr>
<tr>
<td>i2cp.tcp.port
<td>&nbsp;
<td>&nbsp;
<td>1-65535
<td>7654
<td>{% trans -%}
Router I2CP port.
If the client is running in the same JVM as a router, this option is ignored, and the client connects to that router internally.
{%- endtrans %}</td>
</tr>
<tr>
<td>i2cp.SSL
<td>0.8.3
<td>true, false
<td>&nbsp;
<td>false
<td>{% trans -%}
Connect to the router using SSL.
If the client is running in the same JVM as a router, this option is ignored, and the client connects to that router internally.
{%- endtrans %}</td>
</tr>
<tr>
<td>i2cp.gzip
<td>0.6.5
<td>true, false
<td>&nbsp;
<td>true
<td>{% trans %}Gzip outbound data{% endtrans %}</td>
</tr>
<tr>
<td>i2cp.reduceOnIdle
<td>0.7.1
<td>true, false
<td>&nbsp;
<td>false
<td>{% trans %}Reduce tunnel quantity when idle{% endtrans %}</td>
</tr>
<tr>
<td>i2cp.closeOnIdle
<td>0.7.1
<td>true, false
<td>&nbsp;
<td>false
<td>{% trans %}Close I2P session when idle{% endtrans %}</td>
</tr>
<tr>
<td>i2cp.reduceIdleTime
<td>0.7.1
<td>1200000
<td>{% trans num=300000 %}{{ num }} minimum{% endtrans %}
<td>&nbsp;
<td>{% trans %}(ms) Idle time required (default 20 minutes, minimum 5 minutes){% endtrans %}</td>
</tr>
<tr>
<td>i2cp.closeIdleTime
<td>0.7.1
<td>1800000
<td>{% trans num=300000 %}{{ num }} minimum{% endtrans %}
<td>&nbsp;
<td>{% trans %}(ms) Idle time required (default 30 minutes){% endtrans %}</td>
</tr>
<tr>
<td>i2cp.reduceQuantity
<td>0.7.1
<td>1
<td>{% trans from=1, to=5 %}{{ from }} to {{ to }}{% endtrans %}</td>
<td>1
<td>{% trans %}Tunnel quantity when reduced (applies to both inbound and outbound){% endtrans %}</td>
</tr>
<tr>
<td>i2cp.encryptLeaseSet
<td>0.7.1
<td>true, false
<td>&nbsp;
<td>false
<td>{% trans %}Encrypt the lease{% endtrans %}</td>
</tr>
<tr>
<td>i2cp.leaseSetKey
<td>0.7.1
<td>&nbsp;
<td>&nbsp;
<td>&nbsp;
<td>{% trans %}Base64 SessionKey (44 characters){% endtrans %}</td>
</tr>
<tr>
<td>i2cp.messageReliability
<td>&nbsp;
<td>&nbsp;
<td>BestEffort, None
<td>None
<td>{% trans -%}
Guaranteed is disabled;
None implemented in 0.8.1; None is the default as of 0.9.4
{%- endtrans %}</td>
</tr>
<tr>
<td>i2cp.fastReceive
<td>0.9.4
<td>&nbsp;
<td>true, false
<td>true
<td>{% trans -%}
If true, the router just sends the MessagePayload instead
of sending a MessageStatus and awaiting a ReceiveMessageBegin.
{%- endtrans %}</td>
</tr>
</table>
<p>{% trans -%}
Note: All arguments, including numbers, are strings. True/false values are case-insensitive strings.
Anything other than case-insensitive "true" is interpreted as false.
All option names are case-sensitive.
{%- endtrans %}</p>
<h2 id="format">{% trans %}I2CP Payload Data Format and Multiplexing{% endtrans %}</h2>
<p>{% trans i2cp=site_url('docs/spec/i2cp') -%}
The end-to-end messages handled by I2CP (i.e. the data sent by the client in a
<a href="{{ i2cp }}#msg_SendMessage">SendMessageMessage</a>
and received by the client in a
<a href="{{ i2cp }}#msg_MessagePayload">MessagePayloadMessage</a>)
are gzipped with a standard 10-byte gzip
header beginning with 0x1F 0x8B 0x08 as
specified by <a href="http://www.ietf.org/rfc/rfc1952.txt">RFC 1952</a>.
As of release 0.7.1, I2P uses ignored portions of the gzip header to include
protocol, from-port, and to-port information, thus supporting streaming and
datagrams on the same destination, and allowing query/response using datagrams
to work reliably in the presence of multiple channels.
{%- endtrans %}</p>
<p>{% trans -%}
The gzip function cannot be completely turned off, however setting i2cp.gzip=false
turns the gzip effort setting to 0, which may save a little CPU.
{%- endtrans %}</p>
<table border=1>
<tr>
<th>{% trans %}Bytes{% endtrans %}</th>
<th>{% trans %}Content{% endtrans %}</th>
</tr>
<tr>
<td>0-2
<td>{% trans %}Gzip header{% endtrans %} 0x1F 0x8B 0x08</th>
</tr>
<tr>
<td>3
<td>{% trans %}Gzip flags{% endtrans %}</td>
</tr>
<tr>
<td>4-5
<td>{% trans %}I2P Source port (Gzip mtime){% endtrans %}</td>
</tr>
<tr>
<td>6-7
<td>{% trans %}I2P Destination port (Gzip mtime){% endtrans %}</td>
</tr>
<tr>
<td>8
<td>{% trans %}Gzip xflags{% endtrans %}</td>
</tr>
<tr>
<td>9
<td>{% trans %}I2P Protocol (6 = Streaming, 17 = Datagram, 18 = Raw Datagrams) (Gzip OS){% endtrans %}</td>
</tr>
</table>
<p>{% trans -%}
Data integrity is verified with the standard gzip CRC-32 as
specified by <a href="http://www.ietf.org/rfc/rfc1952.txt">RFC 1952</a>.
{%- endtrans %}</p>
<h2 id="future">{% trans %}Future Work{% endtrans %}</h2>
<ul>
<li>{% trans -%}
Implement I2CP and the streaming library in another programming language.
{%- endtrans %}</li>
<li>{% trans -%}
Is the initial Get Date / Set Date handshake required?
{%- endtrans %}</li>
<li>{% trans -%}
The current authorization mechanism could be modified to use hashed passwords.
{%- endtrans %}</li>
<li>{% trans -%}
Private Keys are included in the Create Lease Set message,
are they really required? Revocation is unimplemented.
{%- endtrans %}</li>
<li>{% trans pdf1=url_for('static', filename='pdf/I2CP_spec.pdf'), pdf2=url_for('static', filename='pdf/datastructures.pdf') -%}
Some improvements may be able to use messages previously defined but not implemented.
For reference, here is the
<a href="{{ pdf1 }}">I2CP Protocol Specification Version 0.9</a>
(PDF) dated August 28, 2003.
That document also references the
<a href="{{ pdf2 }}">Common Data Structures Specification Version 0.9</a>.
{%- endtrans %}</li>
</ul>
{% endblock %}

View File

@@ -0,0 +1,234 @@
{% extends "global/layout.html" %}
{% block title %}I2NP{% endblock %}
{% block lastupdated %}{% trans %}June 2013{% endtrans %}{% endblock %}
{% block accuratefor %}0.9.6{% endblock %}
{% block content %}
<h2>{% trans %}I2P Network Protocol{% endtrans %} (I2NP)</h2>
<p>{% trans -%}
The I2P Network Protocol (I2NP),
which is sandwiched between I2CP and the various I2P transport protocols, manages the
routing and mixing of messages between routers, as well as the selection of what
transports to use when communicating with a peer for which there are multiple
common transports supported.
{%- endtrans %}</p>
<h3>{% trans %}I2NP Definition{% endtrans %}</h3>
<p>{% trans -%}
I2NP (I2P Network Protocol) messages can be used for one-hop, router-to-router, point-to-point messages.
By encrypting and wrapping messages in other messages, they can be sent in a secure way
through multiple hops to the ultimate destination.
Priority is only used locally at the origin, i.e. when queuing for outbound delivery.
{%- endtrans %}</p>
<p>{% trans outnetmessage='http://docs.i2p-projekt.de/javadoc/net/i2p/router/OutNetMessage.html' -%}
The priorities listed below may not be current and are subject to change.
See the <a href="{{ outnetmessage }}">OutNetMessage Javadocs</a>
for the current priority settings.
Priority queueing implementation may vary.
{%- endtrans %}</p>
<h3>{% trans %}Message Format{% endtrans %}</h3>
<table border=1>
<tr><th>{% trans %}Field{% endtrans %}</th><th>{% trans %}Bytes{% endtrans %}</th></tr>
<tr><td>{% trans %}Unique ID{% endtrans %}</td><td>4</td></tr>
<tr><td>{% trans %}Expiration{% endtrans %}</td><td>8</td></tr>
<tr><td>{% trans %}Payload Length{% endtrans %}</td><td>2</td></tr>
<tr><td>{% trans %}Checksum{% endtrans %}</td><td>1</td></tr>
<tr><td>{% trans %}Payload{% endtrans %}</td><td>0 - 61.2KB</td></tr>
</table>
<p>{% trans tunnelimpl=site_url('docs/tunnels/implementation') -%}
While the maximum payload size is nominally 64KB, the size is further constrained by the
method of fragmenting I2NP messages into multiple 1KB tunnel messages as described on
<a href="{{ tunnelimpl }}">the tunnel implementation page</a>.
The maximum number of fragments is 64, and the message may not be perfectly aligned,
So the message must nominally fit in 63 fragments.
{%- endtrans %}</p>
<p>{% trans -%}
The maximum size of an initial fragment is 956 bytes (assuming TUNNEL delivery mode);
the maximum size of a follow-on fragment is 996 bytes.
Therefore the maximum size is approximately 956 + (62 * 996) = 62708 bytes, or 61.2 KB.
{%- endtrans %}</p>
<p>{% trans -%}
In addition, the transports may have additional restrictions.
NTCP currently limits to 16KB - 6 = 16378 bytes but this will be increased in a future release.
The SSU limit is approximately 32 KB.
{%- endtrans %}</p>
<p>{% trans -%}
Note that these are not the limits for datagrams that the client sees, as the
router may bundle a reply leaseset and/or session tags together with the client message
in a garlic message. The leaseset and tags together may add about 5.5KB.
Therefore the current datagram limit is about 10KB. This limit will be
increased in a future release.
{%- endtrans %}</p>
<h3>{% trans %}Message Types{% endtrans %}</h3>
<p>{% trans -%}
Higher-numbered priority is higher priority.
The majority of traffic is TunnelDataMessages (priority 400),
so anything above 400 is essentially high priority, and
anything below is low priority.
Note also that many of the messages are generally routed
through exploratory tunnels, not client tunnels, and
therefore may not be in the same queue unless the
first hops happen to be on the same peer.
{%- endtrans %}</p>
<p>{% trans -%}
Also, not all message types are sent unencrypted.
For example, when testing a tunnel, the router wraps a
DeliveryStatusMessage, which is wrapped in a GarlicMessage,
which is wrapped in a DataMessage.
{%- endtrans %}</p>
<table border=1>
<tr>
<th>{% trans %}Message{% endtrans %}</th>
<th>{% trans %}Type{% endtrans %}</th>
<th>{% trans %}Payload Length{% endtrans %}</th>
<th>{% trans %}Priority{% endtrans %}</th>
<th>{% trans %}Comments{% endtrans %}</th>
</tr>
<tr><td>
DatabaseLookupMessage
<td align=right>2
<td>&nbsp;
<td align=right>500
<td>{% trans %}May vary{% endtrans %}</td>
<tr><td>
DatabaseSearchReplyMessage
<td align=right>3
<td align=right>Typ. 161
<td align=right>300
<td>{% trans -%}
Size is 65 + 32*(number of hashes) where typically, the hashes for
three floodfill routers are returned.
{%- endtrans %}</td>
</tr>
<tr><td>
DatabaseStoreMessage
<td align=right>1
<td align=right>{% trans %}Varies{% endtrans %}</td>
<td align=right>460
<td>{% trans -%}
Priority may vary.
Size is 898 bytes for a typical 2-lease leaseSet.
RouterInfo structures are compressed, and size varies; however
there is a continuing effort to reduce the amount of data published in a RouterInfo
as we approach release 1.0.
{%- endtrans %}</td>
</tr>
<tr><td>
DataMessage
<td align=right>20
<td align=right>4 - 62080
<td align=right>425
<td>{% trans -%}
Priority may vary on a per-destination basis
{%- endtrans %}</td>
</tr>
<tr><td>
DeliveryStatusMessage
<td align=right>10
<td align=right>12
<td>&nbsp;
<td>{% trans %}Used for message replies, and for testing tunnels - generally wrapped in a GarlicMessage{% endtrans %}</td>
</tr>
<tr><td>
<a href="{{ site_url('docs/how/tech-intro') }}#op.garlic">GarlicMessage</a>
<td align=right>11
<td>&nbsp;
<td>&nbsp;
<td>{% trans -%}
Generally wrapped in a DataMessage -
but when unwrapped, given a priority of 100 by the forwarding router
{%- endtrans %}</td>
</tr>
<tr><td>
<a href="{{ site_url('docs/spec/tunnel-creation') }}#tunnelCreate.requestRecord">TunnelBuildMessage</a>
<td align=right>21
<td align=right>4224
<td align=right>500
<td>
</tr>
<tr><td>
<a href="{{ site_url('docs/spec/tunnel-creation') }}#tunnelCreate.replyRecord">TunnelBuildReplyMessage</a>
<td align=right>22
<td align=right>4224
<td align=right>300
<td>
</tr>
<tr><td>
TunnelDataMessage
<td align=right>18
<td align=right>1028
<td align=right>400
<td>{% trans -%}
The most common message. Priority for tunnel participants, outbound endpoints, and inbound gateways was
reduced to 200 as of release 0.6.1.33.
Outbound gateway messages (i.e. those originated locally) remains at 400.
{%- endtrans %}</td>
</tr>
<tr><td>
TunnelGatewayMessage
<td align=right>19
<td>&nbsp;
<td align=right>300/400
<td>
</tr>
<tr><td>
VariableTunnelBuildMessage
<td align=right>23
<td align=right>1057 - 4225
<td align=right>500
<td>{% trans %}Shorter TunnelBuildMessage as of 0.7.12{% endtrans %}</td>
</tr>
<tr><td>
VariableTunnelBuildReplyMessage
<td align=right>24
<td align=right>1057 - 4225
<td align=right>300
<td>{% trans %}Shorter TunnelBuildReplyMessage as of 0.7.12{% endtrans %}</td>
</tr>
<tr><td>{% trans pdf=url_for('static', filename='pdf/I2NP_spec.pdf') -%}
Others listed in <a href="{{ pdf }}">2003 Spec</a>
{%- endtrans %}
<td>0,4-9,12
<td>&nbsp;
<td>&nbsp;
<td>{% trans %}Obsolete, Unused{% endtrans %}
</tr>
</table>
<h3>{% trans %}Full Protocol Specification{% endtrans %}</h3>
<p>{% trans i2npspec=site_url('docs/spec/i2np'), commonstructures=site_url('docs/spec/common-structures') -%}
<a href="{{ i2npspec }}">On the I2NP Specification page</a>.
See also the
<a href="{{ commonstructures }}">Common Data Structure Specification page</a>.
{%- endtrans %}</p>
<h3>{% trans %}Future Work{% endtrans %}</h3>
<p>{% trans -%}
It isn't clear whether the current priority scheme is generally effective,
and whether the priorities for various messages should be adjusted further.
This is a topic for further research, analysis and testing.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,121 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Protocol Stack{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}August 2010{% endtrans %}{% endblock %}
{% block accuratefor %}0.8{% endblock %}
{% block content %}
<p>{% trans docs=site_url('docs') -%}
Here is the protocol stack for I2P.
See also the <a href="{{ docs }}">Index to Technical Documentation</a>.
{%- endtrans %}</p>
<p>{% trans -%}
Each of the layers in the stack provides extra capabilities.
The capabilities are listed below, starting at the bottom of the protocol stack.
{%- endtrans %}</p>
<ul>
<li>
<b>{% trans %}Internet Layer:{% endtrans %}</b>
<br />
{% trans %}IP: Internet Protocol, allow addressing hosts on the regular internet and routing packets across the internet using best-effort delivery.{% endtrans %}
</li>
<li>
<b>{% trans %}Transport Layer:{% endtrans %}</b>
<br />
{% trans %}TCP: Transmission Control Protocol, allow reliable, in-order delivery of packets across the internet.{% endtrans %}
<br />
{% trans %}UDP: User Datagram Protocol, allow unreliable, out-of-order delivery of packets across the internet.{% endtrans %}
</li>
<li>
{% trans -%}
<b>I2P Transport Layer:</b> provide encrypted connections between 2 I2P routers. These are not anonymous yet, this is strictly a hop-to-hop connection.
Two protocols are implemented to provide these capabilities. NTCP builds on top of TCP, while SSU uses UDP.
{%- endtrans %}
<br />
<a href="{{ site_url('docs/transport/ntcp') }}">NTCP</a>: {% trans %}NIO-based TCP{% endtrans %}
<br />
<a href="{{ site_url('docs/transport/ssu') }}">SSU</a>: {% trans %}Secure Semi-reliable UDP{% endtrans %}
</li>
<li>
{% trans %}<b>I2P Tunnel Layer:</b> provide full encrypted tunnel connections.{% endtrans %}
<br />
{% trans tunnelmessage=site_url('docs/spec/tunnel-message') -%}
<a href="{{ tunnelmessage }}">Tunnel messages</a>: tunnel messages are large messages containing encrypted I2NP (see below) messages and encrypted instructions for their delivery.
The encryption is layered. The first hop will decrypt the tunnel message and read a part. Another part can still be encrypted (with another key),
so it will be forwarded.
{%- endtrans %}
<br />
{% trans i2np=site_url('docs/protocol/i2np') -%}
<a href="{{ i2np }}">I2NP messages</a>: I2P Network Protocol messages are used to pass messages through multiple routers. These I2NP messages are combined in tunnel messages.
{%- endtrans %}
</li>
<li>
{% trans %}<b>I2P Garlic Layer:</b> provide encrypted and anonymous end-to-end I2P message delivery.{% endtrans %}
<br />
{% trans i2np=site_url('docs/protocol/i2np') -%}
<a href="{{ i2np }}">I2NP messages</a>: I2P Network Protocol messages are wrapped in each other and used to ensure encryption between two tunnels and are passed along from source to destination, keeping both anonymous.
{%- endtrans %}
</li>
</ul>
<p>{% trans -%}
The following layers are strictly speaking no longer part of the I2P Protocol stack, they are not part of the core 'I2P router' functionality.
However, each of these layers adds additional functionality, to allow applications simple and convenient I2P usage.
{%- endtrans %}</p>
<ul>
<li>
{% trans %}<b>I2P Client Layer:</b> allow any client to use I2P functionality, without requiring the direct use of the router API.{% endtrans %}
<br />
{% trans i2cp=site_url('docs/protocol/i2cp') -%}
<a href="{{ i2cp }}">I2CP</a>: I2P Client Protocol, allows secure and asynchronous messaging over I2P by communicating messages over the I2CP TCP socket.
{%- endtrans %}
</li>
<li>
{% trans %}<b>I2P End-to-end Transport Layer:</b> allow TCP- or UDP-like functionality on top of I2P.{% endtrans %}
<br />
{% trans streaming=site_url('docs/api/streaming') -%}
<a href="{{ streaming }}">Streaming Library</a>: an implementation of TCP-like streams over I2P. This allows easier porting of existing applications to I2P.
{%- endtrans %}
<br />
{% trans datagrams=site_url('docs/spec/datagrams') -%}
<a href="{{ datagrams }}">Datagram Library</a>: an implementation of UDP-like messages over I2P. This allows easier porting of existing applications to I2P.
{%- endtrans %}
</li>
<li>
{% trans %}<b>I2P Application Interface Layer:</b> additional (optional) libraries allowing easier implementations on top of I2P.{% endtrans %}
<br />
<a href="{{ site_url('docs/api/i2ptunnel') }}">I2PTunnel</a>
<br />
<a href="{{ site_url('docs/api/sam') }}">SAM</a>/<a href="{{ site_url('docs/api/samv2') }}">SAMv2</a>/<a href="{{ site_url('docs/api/samv3') }}">SAMv3</a>(*),
<a href="{{ site_url('docs/api/bob') }}">BOB</a>
</li>
<li>
{% trans %}<b>I2P Application Proxy Layer:</b> proxy systems.{% endtrans %}
<br />
{% trans socks=site_url('docs/api/socks') %}HTTP Client/Server, IRC Client, <a href="{{ socks }}">SOCKS</a>, Streamr{% endtrans %}
</li>
</ul>
<p>{% trans -%}
Finally, what could be considered the <b>'I2P application layer'</b>, is a large number of applications on top of I2P.
We can order this based on the I2P stack layer they use.
{%- endtrans %}</p>
<ul>
<li>{% trans %}<b>Streaming/datagram applications</b>: i2psnark, Syndie, i2phex...{% endtrans %}</li>
<li>{% trans %}<b>SAM/BOB applications</b>: IMule, i2p-bt, i2prufus, Robert...{% endtrans %}</li>
<li>{% trans plugins=site_url('docs/plugins') %}<b>Other I2P applications</b>: Syndie, EepGet, <a href="{{ plugins }}">plugins</a>...{% endtrans %}</li>
<li>{% trans %}<b>Regular applications</b>: Jetty, Apache, Monotone, CVS, browsers, e-mail...{% endtrans %}</li>
</ul>
<div class="box" style="text-align:center;">
<img src="{{ url_for('static', filename='images/protocol_stack.png') }}" alt="{{ _('I2P Network stack') }}" title="{{ _('I2P Network stack') }}" />
<br /><br />
{% trans %}Figure 1: The layers in the I2P Network stack.{% endtrans %}
</div>
<br/>
<p>
* {% trans %}Note: SAM/SAMv2 can use both the streaming lib and datagrams.{% endtrans %}
</p>
{% endblock %}

View File

@@ -0,0 +1,225 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}I2P Blockfile Specification{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}January 2012{% endtrans %}{% endblock %}
{% block accuratefor %}0.8.12{% endblock %}
{% block content %}
<h2>{% trans %}Blockfile and Hosts Database Specification{% endtrans %}</h2>
<h3>{% trans %}Overview{% endtrans %}</h3>
<p>{% trans naming=site_url('docs/naming') -%}
This document specifies
the I2P blockfile file format
and the tables in the hostsdb.blockfile used by the Blockfile <a href="{{ naming }}">Naming Service</a>.
{%- endtrans %}</p>
<p>{% trans -%}
The blockfile provides fast Destination lookup in a compact format. While the blockfile page overhead is substantial,
the destinations are stored in binary rather than in Base 64 as in the hosts.txt format.
In addition, the blockfile provides the capability of arbitrary metadata storage
(such as added date, source, and comments) for each entry.
The metadata may be used in the future to provide advanced addressbook features.
The blockfile storage requirement is a modest increase over the hosts.txt format, and the blockfile provides
approximately 10x reduction in lookup times.
{%- endtrans %}</p>
<p>{% trans url='http://www.metanotion.net/software/sandbox/block.html' -%}
A blockfile is simply on-disk storage of multiple sorted maps (key-value pairs),
implemented as skiplists.
The blockfile format is adopted from the
<a href="{{ url }}">Metanotion Blockfile Database</a>.
First we will define the file format, then the use of that format by the BlockfileNamingService.
{%- endtrans %}</p>
<h3>{% trans %}Blockfile Format{% endtrans %}</h3>
<p>{% trans -%}
The original blockfile spec was modified to add magic numbers to each page.
The file is structured in 1024-byte pages. Pages are numbered starting from 1.
The "superblock" is always at page 1, i.e. starting at byte 0 in the file.
The metaindex skiplist is always at page 2, i.e. starting at byte 1024 in the file.
{%- endtrans %}</p>
<p>{% trans -%}
All 2-byte integer values are unsigned.
All 4-byte integer values (page numbers) are signed and negative values are illegal.
{%- endtrans %}</p>
<p>{% trans -%}
The database is designed to be opened and accessed by a single thread.
The BlockfileNamingService provides synchronization.
{%- endtrans %}</p>
<p>{% trans -%}
Superblock format:
{%- endtrans %}</p>
{% highlight %}
Byte Contents
0-5 Magic number 0x3141de493250 ("1A" 0xde "I2P")
6 Major version 0x01
7 Minor version 0x01
8-15 File length Total length in bytes
16-19 First free list page
20-21 Mounted flag 0x01 = yes
22-23 Span size max number of key/value pairs per span (16 for hostsdb)
24-1023 unused
{% endhighlight %}
<p>{% trans -%}
Skip list block page format:
{%- endtrans %}</p>
{% highlight %}
Byte Contents
0-7 Magic number 0x536b69704c697374 "SkipList"
8-11 First span page
12-15 First level page
16-19 Size (total number of keys - may only be valid at startup)
20-23 Spans (total number of spans - may only be valid at startup)
24-27 Levels (total number of levels - may only be valid at startup)
28-1023 unused
{% endhighlight %}
<p>{% trans -%}
Skip level block page format is as follows.
All levels have a span. Not all spans have levels.
{%- endtrans %}</p>
{% highlight %}
Byte Contents
0-7 Magic number 0x42534c6576656c73 "BSLevels"
8-9 Max height
10-11 Current height
12-15 Span page
16- Next level pages ('current height' entries, 4 bytes each, lowest first)
remaining bytes unused
{% endhighlight %}
<p>{% trans -%}
Skip span block page format is as follows.
Key/value structures are sorted by key within each span and across all spans.
Key/value structures are sorted by key within each span.
Spans other than the first span may not be empty.
{%- endtrans %}</p>
{% highlight %}
Byte Contents
0-3 Magic number 0x5370616e "Span"
4-7 First continuation page or 0
8-11 Previous span page or 0
12-15 Next span page or 0
16-17 Max keys (16 for hostsdb)
18-19 Size (current number of keys)
20-1023 key/value structures
{% endhighlight %}
<p>{% trans -%}
Span Continuation block page format:
{%- endtrans %}</p>
{% highlight %}
Byte Contents
0-3 Magic number 0x434f4e54 "CONT"
4-7 Next continuation page or 0
8-1023 key/value structures
{% endhighlight %}
<p>{% trans -%}
Key/value structure format is as follows.
Key and value lengths must not be split across pages, i.e. all 4 bytes must be on the same page.
If there is not enough room the last 1-3 bytes of a page are unused and the lengths will
be at offset 8 in the continuation page.
Key and value data may be split across pages.
Max key and value lengths are 65535 bytes.
{%- endtrans %}</p>
{% highlight %}
Byte Contents
0-1 key length in bytes
2-3 value length in bytes
4- key data
value data
{% endhighlight %}
<p>{% trans -%}
Free list block page format:
{%- endtrans %}</p>
{% highlight %}
Byte Contents
0-7 Magic number 0x2366724c69737423 "#frList#"
8-11 Next free list block or 0 if none
12-15 Number of valid free pages in this block (0 - 252)
16-1023 Free pages (4 bytes each), only the first (valid number) are valid
{% endhighlight %}
<p>{% trans -%}
Free page block format:
{%- endtrans %}</p>
{% highlight %}
Byte Contents
0-7 Magic number 0x7e2146524545217e "~!FREE!~"
8-1023 unused
{% endhighlight %}
<p>{% trans -%}
The metaindex (located at page 2) is a mapping of US-ASCII strings to 4-byte integers.
The key is the name of the skiplist and the value is the page index of the skiplist.
{%- endtrans %}</p>
<h3>{% trans %}Blockfile Naming Service Tables{% endtrans %}</h3>
<p>{% trans -%}
The tables created and used by the BlockfileNamingService are as follows.
The maximum number of entries per span is 16.
{%- endtrans %}</p>
<h4>{% trans %}Properties Skiplist{% endtrans %}</h4>
<p>{% trans INFO='"%%__INFO__%%"' -%}
{{ INFO }} is the master database skiplist with String/Properties key/value entries containing only one entry:
{%- endtrans %}</p>
<pre>
"info": a Properties (UTF-8 String/String Map), serialized as a <a href="{{ site_url('docs/spec/common-structures') }}#type_Mapping">Mapping</a>:
"version": "2"
"created": Java long time (ms)
"upgraded": Java long time (ms) (as of database version 2)
"lists": Comma-separated list of host databases, to be
searched in-order for lookups. Almost always "privatehosts.txt,userhosts.txt,hosts.txt".
</pre>
<h4>{% trans %}Reverse Lookup Skiplist{% endtrans %}</h4>
<p>{% trans REVERSE='"%%__REVERSE__%%"' -%}
{{ REVERSE }} is the reverse lookup skiplist with Integer/Properties key/value entries
(as of database version 2):
{%- endtrans %}</p>
<pre>
The skiplist keys are 4-byte Integers, the first 4 bytes of the hash of the Destination.
The skiplist values are each a Properties (a UTF-8 String/String Map) serialized as a <a href="{{ site_url('docs/spec/common-structures') }}#type_Mapping">Mapping</a>
There may be multiple entries in the properties, each one is a reverse mapping,
as there may be more than one hostname for a given destination,
or there could be collisions with the same first 4 bytes of the hash.
Each property key is a hostname.
Each property value is the empty string.
</pre>
<h4>{% trans %}hosts.txt, userhosts.txt, and privatehosts.txt Skiplists{% endtrans %}</h4>
<p>{% trans -%}
For each host database, there is a skiplist containing
the hosts for that database.
The keys/values in these skiplists are as follows:
{%- endtrans %}</p>
<pre>
key: a UTF-8 String (the hostname)
value: a DestEntry, which is a Properties (a UTF-8 String/String Map) serialized as a <a href="{{ site_url('docs/spec/common-structures') }}#type_Mapping">Mapping</a>
followed by a binary Destination (serialized <a href="{{ site_url('docs/spec/common-structures') }}#struct_Destination">as usual</a>).
</pre>
<p>{% trans -%}
The DestEntry Properties typically contains:
{%- endtrans %}</p>
<pre>
"a": The time added (Java long time in ms)
"s": The original source of the entry (typically a file name or subscription URL)
others: TBD
</pre>
<p>{% trans -%}
Hostname keys are stored in lower-case and always end in ".i2p".
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,734 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Common structure Specification{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}June 2013{% endtrans %}{% endblock %}
{% block accuratefor %}0.9.6{% endblock %}
{% block content %}
<h1>{% trans %}Data types Specification{% endtrans %}</h1>
<p>{% trans i2np=site_url('docs/protocol/i2np'),
i2cp=site_url('docs/protocol/i2cp'),
ssu=site_url('docs/transport/ssu') -%}
This document describes some data types common to all I2P protocols, like
<a href="{{ i2np }}">I2NP</a>, <a href="{{ i2cp }}">I2CP</a>,
<a href="{{ ssu }}">SSU</a>, etc.
{%- endtrans %}</p>
<h2 id="type_Integer">Integer</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans -%}
Represents a non-negative integer.
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
1 to 8 bytes in network byte order representing an unsigned integer
{% endtrans %}</p>
<h2 id="type_Date">Date</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans -%}
The number of milliseconds since midnight on January 1, 1970 in the GMT timezone.
If the number is 0, the date is undefined or null.
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
8 byte <a href="#type_Integer">Integer</a>
{% endtrans %}</p>
<h2 id="type_String">String</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans -%}
Represents a UTF-8 encoded string.
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
1 or more bytes where the first byte is the number of bytes (not characters!)
in the string and the remaining 0-255 bytes are the non-null terminated UTF-8 encoded character array.
Length limit is 255 bytes (not characters). Length may be 0.
{% endtrans %}</p>
<h2 id="type_Boolean">Boolean</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans -%}
A boolean value, supporting null/unknown representation
0=false, 1=true, 2=unknown/null
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
1 byte <a href="#type_Integer">Integer</a>
{% endtrans %}</p>
<h4>{% trans %}Notes{% endtrans %}</h4>
<p>{% trans -%}
Deprecated - unused
{% endtrans %}</p>
<h2 id="type_PublicKey">PublicKey</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans cryptography=site_url('docs/how/cryptography') -%}
This structure is used in ElGamal encryption, representing only the exponent, not the primes, which are constant and defined in
<a href="{{ cryptography }}#elgamal">the cryptography specification</a>.
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
256 bytes
{% endtrans %}</p>
<h4><a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/PublicKey.html">Javadoc</a></h4>
<h2 id="type_PrivateKey">PrivateKey</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans cryptography=site_url('docs/how/cryptography') -%}
This structure is used in ElGamal decryption, representing only the exponent, not the primes which are constant and defined in
<a href="{{ cryptography }}#elgamal">the cryptography specification</a>.
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
256 bytes
{% endtrans %}</p>
<h4><a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/PrivateKey.html">Javadoc</a></h4>
<h2 id="type_SessionKey">SessionKey</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans -%}
This structure is used for AES256 encryption and decryption.
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
32 bytes
{% endtrans %}</p>
<h4><a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/SessionKey.html">Javadoc</a></h4>
<h2 id="type_SigningPublicKey">SigningPublicKey</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans cryptography=site_url('docs/how/cryptography') -%}
This structure is used for verifying <a href="{{ cryptography }}#DSA">DSA</a> signatures.
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
128 bytes
{% endtrans %}</p>
<h4><a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/SigningPublicKey.html">Javadoc</a></h4>
<h2 id="type_SigningPrivateKey">SigningPrivateKey</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans cryptography=site_url('docs/how/cryptography') -%}
This structure is used for creating <a href="{{ cryptography }}#DSA">DSA</a> signatures.
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
20 bytes
{% endtrans %}</p>
<h4><a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/SigningPrivateKey.html">Javadoc</a></h4>
<h2 id="type_Signature">Signature</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans cryptography=site_url('docs/how/cryptography') -%}
This structure represents the <a href="{{ cryptography }}#DSA">DSA</a> signature of some data.
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
40 bytes
{% endtrans %}</p>
<h4><a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/Signature.html">Javadoc</a></h4>
<h2 id="type_Hash">Hash</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans -%}
Represents the SHA256 of some data.
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
32 bytes
{% endtrans %}</p>
<h4><a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/Hash.html">Javadoc</a></h4>
<h2 id="type_SessionTag">Session Tag</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans -%}
A random number
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
32 bytes
{% endtrans %}</p>
<h4><a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/SessionTag.html">Javadoc</a></h4>
<h2 id="type_TunnelId">TunnelId</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans -%}
Defines an identifier that is unique to each router in a tunnel.
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
4 byte <a href="#type_Integer">Integer</a>
{% endtrans %}</p>
<h4><a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/TunnelId.html">Javadoc</a></h4>
<h2 id="type_Certificate">Certificate</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans -%}
A certificate is a container for various receipts or proof of works used throughout the I2P network.
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
1 byte <a href="#type_Integer">Integer</a> specifying certificate type, followed by a 2 <a href="#type_Integer">Integer</a> specifying the size of the certificate payload, then that many bytes.
{% endtrans %}</p>
{% highlight lang='dataspec' %}
+----+----+----+----+----+-//
|type| length | payload
+----+----+----+----+----+-//
type :: Integer
length -> 1 byte
case 0 -> NULL
case 1 -> HASHCASH
case 2 -> HIDDEN
case 3 -> SIGNED
case 4 -> MULTIPLE
length :: Integer
length -> 2 bytes
payload :: data
length -> $length bytes
{% endhighlight %}
<h4>{% trans %}Notes{% endtrans %}</h4>
<ul>
<li>{% trans -%}
For <a href="#struct_RouterIdentity">Router Identities</a>, the Certificate is always NULL, no others are currently implemented.
{%- endtrans %}</li>
<li>{% trans i2np=site_url('docs/spec/i2np') -%}
For <a href="{{ i2np }}#struct_GarlicClove">Garlic Cloves</a>, the Certificate is always NULL, no others are currently implemented.
{%- endtrans %}</li>
<li>{% trans i2np=site_url('docs/spec/i2np') -%}
For <a href="{{ i2np }}#msg_Garlic">Garlic Messages</a>, the Certificate is always NULL, no others are currently implemented.
{%- endtrans %}</li>
<li>{% trans -%}
For <a href="#struct_Destination">Destinations</a>, the Certificate may be non-NULL,
however non-NULL certs are not widely used, and any checking is left to the application-level.
{%- endtrans %}</li>
</ul>
<h4><a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/Certificate.html">Javadoc</a></h4>
<h2 id="type_Mapping">Mapping</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans -%}
A set of key/value mappings or properties
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
A 2-byte size Integer followed by a series of String=String; pairs
{% endtrans %}</p>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| size |key_string (len + data) | = |
+----+----+----+----+----+----+----+----+
| val_string (len + data) | ; | ...
+----+----+----+----+----+----+----+
size :: Integer
length -> 2 bytes
Total number of bytes that follow
key_string :: String
A string (one byte length followed by UTF-8 encoded characters)
= :: A single byte containing '='
val_string :: String
A string (one byte length followed by UTF-8 encoded characters)
; :: A single byte containing ';'
{% endhighlight %}
<h4>{% trans %}Notes{% endtrans %}</h4>
<ul>
<li>{% trans -%}
The encoding isn't optimal - we either need the '=' and ';' characters, or the string lengths, but not both
{%- endtrans %}</li>
<li>{% trans -%}
Some documentation says that the strings may not include '=' or ';' but this encoding supports them
{%- endtrans %}</li>
<li>{% trans -%}
Strings are defined to be UTF-8 but in the current implementation, I2CP uses UTF-8 but I2NP does not.
For example,
UTF-8 strings in a RouterInfo options mapping in a I2NP Database Store Message will be corrupted.
{%- endtrans %}</li>
<li>{% trans -%}
Mappings contained in I2NP messages (i.e. in a RouterAddress or RouterInfo)
must be sorted by key so that the signature will be invariant.
{%- endtrans %}</li>
<li>{% trans -%}
Key and value string length limits are 255 bytes (not characters) each, plus the length byte. Length byte may be 0.
{%- endtrans %}</li>
<li>{% trans -%}
Total length limit is 65535 bytes, plus the 2 byte size field, or 65537 total.
{%- endtrans %}</li>
</ul>
<h4><a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/DataHelper.html">Javadoc</a></h4>
<h1>{% trans %}Common structure specification{% endtrans %}</h1>
<h2 id="struct_RouterIdentity">RouterIdentity</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans -%}
Defines the way to uniquely identify a particular router
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
<a href="#type_PublicKey">PublicKey</a> followed by <a href="#type_SigningPublicKey">SigningPublicKey</a> and then a <a href="#type_Certificate">Certificate</a>
{% endtrans %}</p>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| public_key |
+ +
| |
~ ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| signing_key |
+ +
| |
~ ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| certificate |
+----+----+----+-//
public_key :: PublicKey
length -> 256 bytes
signing_key :: SigningPublicKey
length -> 128 bytes
certificate :: Certificate
length -> >= 3 bytes
total length: 387+ bytes
{% endhighlight %}
<h4>{% trans %}Notes{% endtrans %}</h4>
<p>{% trans -%}
The certificate for a RouterIdentity is currently unused and is always NULL.
{%- endtrans %}</p>
<h4><a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/RouterIdentity.html">Javadoc</a></h4>
<h2 id="struct_Destination">Destination</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans -%}
A Destination defines a particular endpoint to which messages can be directed for secure delivery.
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
<a href="#type_PublicKey">PublicKey</a> followed by a <a href="#type_SigningPublicKey">SigningPublicKey</a> and then a <a href="#type_Certificate">Certificate</a>
{% endtrans %}</p>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| public_key |
+ +
| |
~ ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| signing_public_key |
+ +
| |
~ ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| certificate
+-//
public_key :: PublicKey
length -> 256 bytes
signing_public_key :: SigningPublicKey
length -> 128 bytes
certificate :: Certificate
length -> >= 3 bytes
total length: 387+ bytes
{% endhighlight %}
<h4>Notes</h4>
<ul><li>
The public key of the destination was used for the old i2cp-to-i2cp encryption
which was disabled in version 0.6, it is currently unused
except for the IV for LeaseSet encryption,
which is deprecated. The public key in the LeaseSet is used instead.
</li></ul>
<h4><a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/Destination.html">Javadoc</a></h4>
<h2 id="struct_Lease">Lease</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans -%}
Defines the authorization for a particular tunnel to receive messages targeting a <a href="#struct_Destination">Destination</a>.
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
SHA256 <a href="#type_Hash">Hash</a> of the
<a href="#struct_RouterIdentity">RouterIdentity</a> of the gateway router, then the <a href="#type_TunnelId">TunnelId</a>, and finally an end <a href="#type_Date">Date</a>
{% endtrans %}</p>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| tunnel_gw |
+ +
| |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| tunnel_id | end_date
+----+----+----+----+----+----+----+----+
|
+----+----+----+----+
tunnel_gw :: Hash of the RouterIdentity of the tunnel gateway
length -> >= 32 bytes
tunnel_id :: TunnelId
length -> 4 bytes
end_date :: Date
length -> 8 bytes
{% endhighlight %}
<h4>{% trans %}Notes{% endtrans %}</h4>
<ul>
<li>{% trans -%}
Total size: 44 bytes
{%- endtrans %}</li>
</ul>
<h4><a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/Lease.html">Javadoc</a></h4>
<h2 id="struct_LeaseSet">LeaseSet</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans -%}
Contains all of the currently authorized <a href="#struct_Lease">Lease</a>s for a particular <a href="#struct_Destination">Destination</a>, the <a href="#type_PublicKey">PublicKey</a> to which garlic messages can be encrypted,
and then the <a href="#type_SigningPublicKey">public key</a> that can be used to revoke this particular version of the structure. The <a href="#struct_LeaseSet">LeaseSet</a> is one of the two structures stored in the network database(
the other being <a href="#struct_RouterInfo">RouterInfo</a>), and is keyed under the SHA256 of the contained <a href="#struct_Destination">Destination</a>.
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
<a href="#struct_Destination">Destination</a>, followed by a <a href="#type_PublicKey">PublicKey</a> for encryption, then a <a href="#type_SigningPublicKey">SigningPublicKey</a> which can be used to revoke this version of the <a href="#struct_LeaseSet">LeaseSet</a>,
then a 1 byte <a href="#type_Integer">Integer</a> specifying how many <a href="#struct_Lease">Lease</a> structures are in the set, followed by the actual <a href="#struct_Lease">Lease</a> structures and finally a <a href="#type_Signature">Signature</a> of the previous
bytes signed by the <a href="#struct_Destination">Destination's</a> <a href="#type_SigningPrivateKey">SigningPrivateKey</a>
{%- endtrans %}</p>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| destination |
+ +
| |
~ ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| encryption_key |
+ +
| |
~ ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| signing_key |
+ +
| |
~ ~
~ ~
| |
+----+----+----+----+----+----+----+----+
|num | Lease 0 |
+----+ +
| |
~ ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| Lease 1 |
+ +
| |
~ ~
~ ~
~ ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| Lease ($num-1) |
+ +
| |
~ ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| signature |
+ +
| |
+ +
| |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
destination :: Destination
length -> >= 387 bytes
encryption_key :: PublicKey
length -> 256 bytes
signing_key :: SigningPublicKey
length -> 128 bytes
num :: Integer
length -> 1 byte
value: 0 <= num <= 16
leases :: [Lease]
length -> >= $num*44 bytes
signature :: Signature
length -> 40 bytes
{% endhighlight %}
<h4>{% trans %}Notes{% endtrans %}</h4>
<ul>
<li>{% trans -%}
The public key of the destination was used for the old i2cp-to-i2cp encryption
which was disabled in version 0.6, it is currently unused.
{%- endtrans %}</li>
<li>{% trans elgamalaes=site_url('docs/how/elgamal-aes') -%}
The encryption key is used for end-to-end <a href="{{ elgamalaes }}">ElGamal/AES+SessionTag</a> encryption.
It is currently generated anew at every router startup, it is not persistent.
{%- endtrans %}</li>
<li>{% trans -%}
The signature may be verified using the signing public key of the destination.
{%- endtrans %}</li>
<li>{% trans -%}
The signing_key is currently unused. It was intended for LeaseSet revocation, which is unimplemented.
It is currently generated anew at every router startup, it is not persistent.
{%- endtrans %}</li>
<li>{% trans -%}
The earliest expiration of all the Leases is treated as the timestamp or version of the LeaseSet.
Routers will generally not accept a store of a LeaseSet unless it is "newer" than the current one.
Take care when publishing a new LeaseSet where the oldest Lease is the same as the oldest Lease
in the previous LeaseSet. The publishing router should generally increment the expiration
of the oldest Lease by at least 1 ms in that case.
{%- endtrans %}</li>
<li>{% trans -%}
Prior to release 0.9.7, when included in a DatabaseStore Message sent by the originating router,
the router set all the published leases' expirations to the same value, that of the
earliest lease. As of release 0.9.7, the router publishes the actual lease expiration for each lease.
This is an implementation detail and not part of the structures specification.
{%- endtrans %}</li>
</ul>
<h4><a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/LeaseSet.html">Javadoc</a></h4>
<h2 id="struct_RouterAddress">RouterAddress</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans -%}
This structure defines the means to contact a router through a transport protocol.
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
1 byte <a href="#type_Integer">Integer</a> defining the relative cost of using the address, where 0 is free and 255 is expensive, followed by the expiration <a href="#type_Date">Date</a> after which the address should not be used, or if null, the address never expires.
After that comes a <a href="#type_String">String</a> defining the transport protocol this router address uses. Finally there is a <a href="#type_Mapping">Mapping</a> containing all of the transport specific options necessary to establish the connection, such as
IP address, port number, email address, URL, etc.
{% endtrans %}</p>
{% highlight lang='dataspec' %}
+----+
|cost|
+----+----+----+----+----+----+----+----+
| expiration |
+----+----+----+----+-//-+----+----+----+
| transport_style |
+----+----+----+----+-//-+----+----+----+
| options |
+----+----+----+----+-//-+----+----+----+
cost :: Integer
length -> 1 byte
case 0 -> free
case 255 -> expensive
expiration :: Date
length -> 8 bytes
case null -> never expires
transport_style :: String
length -> 1-256 bytes
options :: Mapping
{% endhighlight %}
<h4>{% trans %}Notes{% endtrans %}</h4>
<ul>
<li>{% trans -%}
Cost is typically 5 or 6 for SSU, and 10 or 11 for NTCP.
{%- endtrans %}</li>
<li>{% trans -%}
Expiration is currently unused, always null (all zeroes)).
As of release 0.9.3, the expiration is assumed zero and not stored, so any non-zero expiration
will fail in the RouterInfo signature verification.
Implementing expiration (or another use for these bytes) will be a backwards-incompatible change.
{%- endtrans %}</li>
</ul>
<h4><a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/RouterAddress.html">Javadoc</a></h4>
<h2 id="struct_RouterInfo">RouterInfo</h2>
<h4>{% trans %}Description{% endtrans %}</h4>
<p>{% trans -%}
Defines all of the data that a router wants to publish for the network to see. The <a href="#struct_RouterInfo">RouterInfo</a> is one of two structures stored in the network database(the other being <a href="#struct_LeaseSet">LeaseSet</a>, and is keyed under the SHA256 of
the contained <a href="#struct_RouterIdentity">RouterIdentity</a>.
{% endtrans %}</p>
<h4>{% trans %}Contents{% endtrans %}</h4>
<p>{% trans -%}
<a href="#struct_RouterIdentity">RouterIdentity</a> followed by the <a href="#type_Date">Date</a>, when the entry was published
{% endtrans %}</p>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| router_ident |
+ +
| |
~ ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| published |
+----+----+----+----+----+----+----+----+
|size| RouterAddress 0 |
+----+ +
| |
~ ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| RouterAddress 1 |
+ +
| |
~ ~
~ ~
~ ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| RouterAddress ($size-1) |
+ +
| |
~ ~
~ ~
| |
+----+----+----+----+-//-+----+----+----+
|psiz| options |
+----+----+----+----+-//-+----+----+----+
| signature |
+ +
| |
+ +
| |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
router_ident :: RouterIdentity
length -> >= 387 bytes
published :: Date
length -> 8 bytes
size :: Integer
length -> 1 byte
addresses :: [RouterAddress]
length -> >= $size*267 bytes
peer_size :: Integer
length -> 1 byte
value -> 0
options :: Mapping
signature :: Signature
length -> 40 bytes
{% endhighlight %}
<h4>{% trans %}Notes{% endtrans %}</h4>
<p>{% trans -%}
The peer_size Integer may be followed by a list of that many router hashes.
This is currently unused. It was intended for a form of restricted routes, which is unimplemented.
{% endtrans %}</p>
<p>{% trans -%}
The signature may be verified using the signing public key of the router_ident.
{% endtrans %}</p>
<h4><a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/RouterInfo.html">Javadoc</a></h4>
<h2 id="struct_DeliveryInstructions">Delivery Instructions</h2>
<p>{% trans tunnelmessage=site_url('docs/spec/tunnel-message') -%}
Defined in the <a href="{{ tunnelmessage }}#delivery">Tunnel Message Specification</a>.
{% endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,107 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Configuration File Specification{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}September 2012{% endtrans %}{% endblock %}
{% block accuratefor %}0.9.2{% endblock %}
{% block content %}
<h2>{% trans %}Overview{% endtrans %}</h2>
<p>{% trans -%}
This page provides a general specification of I2P configuration files,
used by the router and various applications.
It also gives an overview of the information contained in the various files,
and links to detailed documentation where available.
{%- endtrans %}</p>
<h2>{% trans %}General Format{% endtrans %}</h2>
<p>{% trans url='http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Properties.html#load%28java.io.InputStream%29' -%}
An I2P configuration file is formatted as specified in
<a href="{{ url }}">Java Properties</a>
with the following exceptions:
{%- endtrans %}</p>
<ul>
<li>{% trans %}Encoding must be UTF-8{% endtrans %}</li>
<li>{% trans %}Does not use or recognize any escapes, including '\', so lines may not be continued{% endtrans %}</li>
<li>{% trans %}'#' or ';' starts a comment, but '!' does not{% endtrans %}</li>
<li>{% trans %}'#' starts a comment in any position but ';' must be in column 1 to start a comment{% endtrans %}</li>
<li>{% trans %}Leading and trailing whitespace is not trimmed on keys{% endtrans %}</li>
<li>{% trans %}Leading and trailing whitespace is trimmed on values{% endtrans %}</li>
<li>{% trans %}'=' is the only key-termination character (not ':' or whitespace){% endtrans %}</li>
<li>{% trans %}Lines without '=' are ignored. It does not store the key with a value of ""{% endtrans %}</li>
<li>{% trans %}As there are no escapes, keys may not contain '#', '=', or '\n', or start with ';'{% endtrans %}</li>
<li>{% trans %}As there are no escapes, values may not contain '#' or '\n', or start or end with '\r' or whitespace{% endtrans %}</li>
</ul>
<p>{% trans -%}
The file need not be sorted, but most applications do sort by key when
writing to the file, for ease of reading and manual editing.
{%- endtrans %}</p>
<p>{% trans url='http://docs.i2p-projekt.de/javadoc/net/i2p/data/DataHelper.html',
commonstructures=site_url('docs/spec/common-structures') -%}
Reads and writes are implemented in
<a href="{{ url }}">DataHelper loadProps() and storeProps()</a>.
Note that the file format is significantly different than the
serialized format for I2P protocols specified in
<a href="{{ commonstructures }}#type_Mapping">Mapping</a>.
{%- endtrans %}</p>
<h2>{% trans %}Core library and router{% endtrans %}</h2>
<h3>{% trans %}Clients{% endtrans %} (clients.config)</h3>
<p>{% trans -%}
Configured via /configclients in the router console.
{%- endtrans %}</p>
<h3>{% trans %}Logger{% endtrans %} (logger.config)</h3>
<p>{% trans -%}
Configured via /configlogging in the router console.
{%- endtrans %}</p>
<h3>{% trans %}Individual Plugin{% endtrans %} (xxx/plugin.config)</h3>
<p>{% trans pluginspec=site_url('docs/spec/plugin') -%}
See <a href="{{ pluginspec }}">the plugin specification</a>.
{%- endtrans %}</p>
<h3>{% trans %}Plugins{% endtrans %} (plugins.config)</h3>
<p>{% trans -%}
Enable/disable for each installed plugin.
{%- endtrans %}</p>
<h3>{% trans %}Router{% endtrans %} (router.config)</h3>
<p>{% trans -%}
Configured via /configadvanced in the router console.
{%- endtrans %}</p>
<h2>{% trans %}Applications{% endtrans %}</h2>
<h3>{% trans %}Addressbook{% endtrans %} (addressbook/config.txt)</h3>
<p>{% trans -%}
See documentation in SusiDNS.
{%- endtrans %}</p>
<h3>I2PSnark (i2psnark.config)</h3>
<p>{% trans -%}
Configured via the application gui.
{%- endtrans %}</p>
<h3>I2PTunnel (i2ptunnel.config)</h3>
<p>{% trans -%}
Configured via the /i2ptunnel application in the router console.
{%- endtrans %}</p>
<h3>{% trans %}Router Console{% endtrans %}</h3>
<p>{% trans -%}
The router console uses the router.config file.
{%- endtrans %}</p>
<h3>SusiMail (susimail.config)</h3>
<p>{% trans -%}
See post on zzz.i2p.
{%- endtrans %}</p>
<!--
<h3>Systray (systray.config)</h3>
<p>
TBD
</p>
-->
{% endblock %}

View File

@@ -0,0 +1,104 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Datagram Specification{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}May 2013{% endtrans %}{% endblock %}
{% block accuratefor %}0.9.6{% endblock %}
{% block content %}
<p><a href="{{ site_url('docs/api/datagrams') }}">{% trans -%}
See the Datagrams page for an overview of the Datagrams API.
{%- endtrans %}</a></p>
<h2 id="spec">{% trans %}Specification{% endtrans %}</h2>
<h3 id="raw">{% trans %}Non-Repliable Datagrams{% endtrans %}</h3>
<p>{% trans -%}
Non-repliable datagrams have no 'from' address and are not authenticated.
They are also called "raw" datagrams.
Strictly speaking, they are not "datagrams" at all, they are just raw data.
They are not handled by the datagram API.
However, SAM and the I2PTunnel classes support "raw datagrams".
{%- endtrans %}</p>
<h4>{% trans %}Format{% endtrans %}</h4>
{% highlight lang='dataspec' %}
+----+----+----+----+----//
| payload...
+----+----+----+----+----//
length: 0 - unlimited (see notes)
{% endhighlight %}
<h4>{% trans %}Notes{% endtrans %}</h4>
<p>{% trans tunnelmessage=site_url('docs/spec/tunnel-message'),
transports=site_url('docs/transport') -%}
The practical length is limited by lower layers of protocols - the
<a href="{{ tunnelmessage }}#notes">tunnel message spec</a>
limits messages to about 61.2 KB and the
<a href="{{ transports }}">transports</a>
currently limit messages to about 32 KB, although this may be raised in the future.
{%- endtrans %}</p>
<h3 id="repliable">{% trans %}Repliable Datagrams{% endtrans %}</h3>
<p>{% trans -%}
Repliable datagrams contain a 'from' address and a signature. These add 427 bytes of overhead.
{%- endtrans %}</p>
<h4>Format</h4>
<pre>
+----+----+----+----+----+----+----+----+
| from |
+ +
| |
~ ~
~ ~
| |
+ +
| |
| |
+----+----+----+----+----+----+----+----+
| signature |
+ +
| |
+ +
| |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| payload...
+----+----+----+----//
from :: a <a href="{{ site_url('docs/spec/common-structures') }}#struct_Destination">Destination</a>
length: 387+ bytes
The originator and signer of the datagram
signature :: a <a href="{{ site_url('docs/spec/common-structures') }}#type_Signature">Signature</a>
length: 40 bytes
The <a href="{{ site_url('docs/how/cryptography') }}#DSA">DSA</a> signature of the SHA256 hash of the payload, which may be verified by the
DSA signing public key of the 'from' Destination
payload :: The data
Length: 0 - 32 KB (see notes)
Total length: Payload length + 427+
</pre>
<h4>{% trans %}Notes{% endtrans %}</h4>
<ul>
<li>{% trans transports=site_url('docs/transport') -%}
The practical length is limited by lower layers of protocols - the
<a href="{{ transports }}">transports</a>
currently limit messages to about 32 KB, so the data length here is limited to about
31.5 KB.
{%- endtrans %}</li>
<li>{% trans -%}
See important notes above about the reliability of large datagrams.
{%- endtrans %}</li>
</ul>
{% endblock %}

View File

@@ -0,0 +1,81 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}GeoIP File Specification{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}May 2013{% endtrans %}{% endblock %}
{% block accuratefor %}0.9.6{% endblock %}
{% block content %}
<h2>{% trans %}Overview{% endtrans %}</h2>
<p>{% trans -%}
This page specifies the format of the various GeoIP files,
used by the router to look up a country for an IP.
{%- endtrans %}</p>
<h2>{% trans %}Country Name (countries.txt) Format{% endtrans %}</h2>
<p>{% trans -%}
This format is easily generated from data files available from many public sources.
For example:
{%- endtrans %}</p>
{% highlight lang='bash' %}
$ wget http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip
$ unzip GeoIPCountryCSV.zip
$ cut -d, -f5,6 < GeoIPCountryWhois.csv |sed 's/"//g' | sort | uniq > countries.txt
{% endhighlight %}
<ul>
<li>Encoding is UTF-8
<li>'#' in column 1 specifies a comment line
<li>Entry lines are CountryCode,CountryName
<li>CountryCode is the ISO two-letter code, upper case
<li>CountryName is in English
</ul>
<h2>{% trans %}IPv4 (geoip.txt) Format{% endtrans %}</h2>
<p>{% trans -%}
This format is borrowed from Tor and is easily generated from data files available from many public sources.
For example:
{%- endtrans %}</p>
{% highlight lang='bash' %}
$ wget http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip
$ unzip GeoIPCountryCSV.zip
$ cut -d, -f3-5 < GeoIPCountryWhois.csv|sed 's/"//g' > geoip.txt
$ cut -d, -f5,6 < GeoIPCountryWhois.csv |sed 's/"//g' | sort | uniq > countries.txt
{% endhighlight %}
<ul>
<li>Encoding is ASCII
<li>'#' in column 1 specifies a comment line
<li>Entry lines are FromIP,ToIP,CountryCode
<li>FromIP and ToIP are unsigned integer representations of the 4-byte IP
<li>CountryCode is the ISO two-letter code, upper case
<li>Entry lines must be sorted by numeric FromIP
</ul>
<h2>{% trans %}IPv6 (geoipv6.dat.gz) Format{% endtrans %}</h2>
<p>{% trans -%}
This is a compressed binary format designed for I2P.
The file is gzipped. Ungzipped format:
{%- endtrans %}</p>
{% highlight %}
Bytes 0-9: Magic number "I2PGeoIPv6"
Bytes 10-11: Version (0x0001)
Bytes 12-15 Options (0x00000000) (future use)
Bytes 16-23: Creation date (Java long)
Bytes 24-xx: Optional comment (UTF-8)
Bytes xx-255: null padding
Bytes 256-: 18 byte records:
8 byte from (/64)
8 byte to (/64)
2 byte ISO country code LOWER case (ASCII)
{% endhighlight %}
<p>{% trans %}NOTES:{% endtrans %}</p>
<ul>
<li>Data must be sorted (SIGNED long twos complement), no overlap.
So the order is 8000:: ... FFFF:: 0000:: ... 7FFF::
<li>
The GeoIPv6.java class contains a program to generate this format from
public sources such as the Maxmind GeoLite data.
<li>
This specification is preliminary; I2P does not yet support IPv6 GeoIP lookup.
</ul>
{% endblock %}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,472 @@
{% extends "global/layout.html" %}
{% block title %}I2P Plugin Specification{% endblock %}
{% block lastupdated %}March 2012{% endblock %}
{% block accuratefor %}0.8.13-13{% endblock %}
{% block content %}
<h2>
Specification Version 0.18
2012-03-15
</h2>
<h3>Overview</h3>
<p>
This document specifies
a .xpi2p file format (like the Firefox .xpi), but with a simple
plugin.config description file instead of an XML install.rdf file.
This file format is used for both initial plugin installs and plugin updates.
<p>
In addition, this document provides a brief overview of how the router installs plugins,
and policies and guidelines for plugin developers.
<p>
The basic .xpi2p file format is the same as a i2pupdate.sud file
(the format used for router updates),
but the installer will let the user install the
addon even if it doesn't know the signer's key yet.
<p>
The standard directory structure will let users install the following types of addons:
<ul>
<li>
console webapps
<li>
new eepsite with cgi-bin, webapps
<li>
console themes
<li>
console translations
<li>
Java programs
<li>
Java programs in a separate JVM
<li>
Any shell script or program
</ul>
<p>
A plugin installs all its files in ~/.i2p/plugins/name/ (%APPDIR%\I2P\plugins\name\ on Windows). The installer will prevent
installation anywhere else, although the plugin can access libraries elsewhere when running.
<p>
This should be viewed only as a way to make installation, uninstallation, and upgrading easier,
and to lessen basic inter-plugin conflicts.
<p>
There is essentially no security model once the plugin is running, however. The plugin runs
in the same JVM and with the same permissions as the router, and has full access to the file
system, the router, executing external programs, etc.
<h3>Details</h3>
<p>
foo.xpi2p is a sud file containing the following:
<pre>
Standard .sud header prepended to the zip file, containing the following:
40-byte <a href="{{ site_url('docs/how/cryptography') }}#DSA">DSA signature</a>
16-byte plugin version in UTF-8, padded with trailing zeroes if necessary
Zip file containing the following:
(REQUIRED) plugin.config file:
(standard I2P config file, UTF-8 containing key=value lines, comments start with #)
Containing the following properties:
(* = required)
The first three must be identical to those in the installed plugin for an update plugin.
*name (will be installed in this directory name)
For native plugins, you may want separate names in different packages -
foo-windows and foo-linux, for example
*key (<a href="{{ site_url('docs/how/cryptography') }}#DSA">DSA public key</a> as 172 B64 chars ending with '=')
*signer (yourname@mail.i2p recommended)
*version (must be in a format VersionComparator can parse, e.g. 1.2.3-4)
16 bytes max (must match sud version)
Valid number separators are '.', '-', and '_'
This must be greater than the one in the installed plugin for an update plugin.
The following items are displayed on configclients.jsp if present:
date (Java time - long int)
author (yourname@mail.i2p recommended)
websiteURL (http://foo.i2p/)
updateURL (http://foo.i2p/foo.xpi2p)
The update checker will check bytes 41-56 at this URL
to determine whether a newer version is available
( Should the checker fetch with ?currentVersion=1.2.3?...
No. If the dev wants to have the URL contain the current version, just
set it in the config file, and remember to change it every release)
description
description_xx (for language xx)
license
disableStop=true
Default false.
If true, the stop button will not be shown. Use this if there are no
webapps and no clients with stopargs.
The following items are used to add a link on the console summary bar:
consoleLinkName (will be added to summary bar)
consoleLinkName_xx (for language xx)
consoleLinkURL (/appname/index.jsp)
consoleLinkTooltip (supported as of 0.7.12-6)
consoleLinkTooltip_xx (lang xx as of 0.7.12-6)
The following items are used by the plugin installer:
type (app/theme/locale/webapp/...) (unimplemented, probably not necessary)
min-i2p-version
max-i2p-version
min-java-version
min-jetty-version (supported as of 0.8.13, use 6 for Jetty 6 webapps)
max-jetty-version (supported as of 0.8.13, use 5.99999 for Jetty 5 webapps)
required-platform-OS (unimplemented - perhaps will be displayed only, not verified)
other-requirements (unimplemented e.g. python x.y - not verified by the installer, just displayed to the user)
dont-start-at-install=true
Default false.
Won't start the plugin when it is installed or updated. On initial installation, sets the plugin as so the user must manually start it. An update will not change the user's preference to start it if they choose to do so.
router-restart-required=true
Default false.
This does not restart the router or the plugin on an update, it just informs the user that a restart is required.
It has no effect on initial plugin installation.
update-only=true
Default false.
If true, will fail if an installation does not exist.
install-only=true
Default false.
If true, will fail if an installation exists.
min-installed-version (to update over, if an installation exists)
max-installed-version (to update over, if an installation exists)
depends=plugin1,plugin2,plugin3 (unimplemented - is this too hard? proposed by sponge)
depends-version=0.3.4,,5.6.7 (unimplemented)
The following item is used for translation plugins:
langs=xx,yy,Klingon,... (unimplemented) (yy is the country flag)
Each of the following directories or files is optional, but something must be there or it won't do anything:
console/
locale/
Only jars containing new resource bundles (translations) for apps in the base I2P installation.
Bundles for this plugin should go inside console/webapp/foo.war or lib/foo.jar
themes/
New themes for the router console
Place each theme in a subdirectory.
webapps/
(See important notes below about webapps)
.wars
These will be run at install time unless disabled in webapps.config
The war name does not have to be the same as the plugin name.
Do not duplicate war names in the base I2P installation.
webapps.config
Same format as router's webapps.config
Also used to specify additional jars in $PLUGIN/lib/ or $I2P/lib for the webapp classpath,
with webapps.warname.classpath=$PLUGIN/lib/foo.jar,$I2P/lib/bar.jar
NOTE: Currently, the classpath line is only loaded if the warname is
the same as the plugin name.
NOTE: Prior to router version 0.7.12-9, the router looked for plugin.warname.startOnLoad instead
of webapps.warname.startOnLoad. For compatibility with older router versions, a plugin
wishing to disable a war should include both lines.
eepsite/
(See important notes below about eepsites)
cgi-bin/
docroot/
logs/
webapps/
jetty.xml
The installer will have to do variable substitution in here to set the path
The location and name of this file doesn't really matter, as long as it is set in
clients.config - it may be more convenient to be up one level from here
(that's what the zzzot plugin does)
lib/
Put any jars here, and specify them in a classpath line in console/webapps.config and/or clients.config
clients.config (same format as router's clients.config)
These will be run when a plugin is started
Start at client #0, number consecutively
New property clientApp.0.stopargs=foo bar stop baz
If present, the class will be called with these args to stop the client
All stop tasks are called with zero delay
Note: The router can't tell if your clients are running or not.
Each should handle stopping an app that isn't running without complaint.
That probably goes for starting a client that is already started too.
New property clientApp.0.uninstallargs=foo bar uninstall baz
If present, the class will be called with these args just before deleting $PLUGIN
All uninstall tasks are called with zero delay
New property clientApp.0.classpath=$I2P/lib/foo.bar,$PLUGIN/lib/bar.jar
The plugin runner will do variable substitution in the args and stopargs lines as follows:
$I2P => i2p base installation dir;
$CONFIG => i2p config dir (typically ~/.i2p)
$PLUGIN => this plugin's installation dir (typically ~/.i2p/plugins/appname)
(See important notes below about running shell scripts or external programs)
</pre>
<h3>Plugin installer tasks</h3>
This lists what happens when a plugin is installed by I2P.
<ul>
<li>The .xpi2p file is downloaded.</li>
<li>The .sud signature is verified against stored keys.
If there is no matching key, the .sud is extracted, the key is loaded from the properties, then verified and stored.</li>
<li>Verify the integrity of the zip file.</li>
<li>Extract the plugin.config file.</li>
<li>Verify the I2P version, to make sure the plugin will work.</li>
<li>Check that webapps don't duplicate the existing $I2P applications.</li>
<li>Stop the existing plugin (if present).</li>
<li>Verify that the install directory does not exist yet if update=false, or ask to overwrite.</li>
<li>Verify that the install directory does exist if update=true, or ask to create.</li>
<li>Unzip the plugin in to appDir/plugins/name/</li>
<li>Add the plugin to plugins.config</li>
</ul>
<h3>
Plugin starter tasks
</h3>
This lists what happens when plugins are started.
First, plugins.config is checked to see which plugins need to be started.
For each plugin:
<ul>
<li>Check clients.config, and load and start each item (add the configured jars to the classpath).</li>
<li>Check console/webapp and console/webapp.config. Load and start required items (add the configured jars to the classpath).</li>
<li>Add console/locale/foo.jar to the translation classpath if present.</li>
<li>Add console/theme to the theme search path if present.</li>
<li>Add the summary bar link.</li>
</ul>
<h3>
Console webapp notes
</h3>
<p>
Console webapps with background tasks should implement a ServletContextListener
(see seedless or i2pbote for examples), or override destroy() in the servlet,
so that they can be stopped.
As of router version 0.7.12-3, console webapps will always be stopped before they
are restarted, so you do not need to worry about multiple instances,
as long as you do this.
Also as of router version 0.7.12-3, console webapps will be stopped at router shutdown.
<p>
Don't bundle library jars in the webapp; put them in lib/ and put a classpath in webapps.config.
Then you can make separate install and update plugins, where the update plugin does not
contain the library jars.
<p>
Don't include .java or .jsp files; otherwise jetty will recompile them at installation.
<p>
For now, a webapp needing to add classpath files in $PLUGIN must be the same name as the plugin.
For example, a webapp in plugin foo must be named foo.war.
<h3>
Eepsite notes
</h3>
<p>
It isn't clear how to have a plugin install to an existing eepsite.
The router has no hook to the eepsite, and it may or may not be running,
and there may be more than one.
Better is to start your own Jetty instance and I2PTunnel instance,
for a brand new eepsite.
<p>
It can instantiate a new I2PTunnel (kinda like the i2ptunnel CLI does),
but it won't appear in the i2ptunnel gui of course, that's a different instance.
But that's ok. Then you can start and stop i2ptunnel and jetty together.
<p>
So don't count on the router to automatically merge this with some existing eepsite. It probably won't happen.
Start a new I2PTunnel and Jetty from clients.config.
The best examples of this are the zzzot and pebble plugins,
available at <a href="http://{{ i2pconv('stats.i2p') }}/i2p/plugins/">zzz's plugins page</a>.
<p>
How to get path substitution into jetty.xml?
See zzzot and pebble plugins for examples.
<h3>
Client start/stop notes
</h3>
<p>
The router has no way to monitor the state of clients started via clients.config.
The plugin author should handle multiple start or stop calls gracefully, if at all possible,
by keeping a static state table, or using PID files, etc.
Avoid logging or exceptions on multiple starts or stops.
This also goes for a stop call without a previous start.
As of router version 0.7.12-3, plugins will be stopped at router shutdown,
which means that all clients with stopargs in clients.config will be called,
whether or not they were previously started.
<h3>
Shell script and external program notes
</h3>
<p>
To run shell scripts or other external programs, see <a href="http://{{ i2pconv('zzz.i2p') }}/topics/141">{{ i2pconv('zzz.i2p') }}</a>
<p>
To work on both Windows and Linux, write a small Java class that checks the OS type, then
runs ShellCommand on either the .bat or a .sh file you provide.
<p>
External programs won't be stopped when the router stops, and a second copy will
fire up when the router starts. To work around this, you could
write a wrapper class or shell script that does the usual storage of the PID
in a PID file, and check for it on start.
<h3>
Other plugin guidelines
</h3>
<ul>
<li>
See i2p.scripts branch or any of the sample plugins on zzz's page for a xpi2p file generator to make it easy.
<li>
Pack200 of jars and wars is strongly recommended for plugins, it generally shrinks plugins by 60-65&#37;.
See any of the sample plugins on zzz's page for an example.
Pack200 unpacking is supported on routers 0.7.11-5 or higher, which is essentially all routers that
support plugins at all.
<li>
Plugins should not attempt to write anywhere in $I2P as it may be readonly, and that isn't good policy anyway.
<li>
Plugins may write to $CONFIG but keeping files in $PLUGIN only is recommended.
All files in $PLUGIN will be deleted at uninstall.
Files elsewhere will not be deleted at uninstall unless the plugin does it explicitly
with a client in clients.config run with uninstallargs.
If the user may want to save data after uninstallation, the uninstallargs hook
could ask.
<li>
$CWD may be anywhere; do not assume it is in a particular place, do not attempt to read or write files relative to $CWD.
<li>
Java programs should find out where they are with the directory getters in I2PAppContext.
<li>
Plugin directory is I2PAppContext.getGlobalContext().getAppDir().getAbsolutePath() + "/plugins/" + appname,
or put a $PLUGIN argument in the args line in clients.config.
There is no reliable way to find the i2p install or config or plugin directory without using the
context API in i2p.jar.
<li>
See <a href="http://{{ i2pconv('zzz.i2p') }}/topics/16">Howto</a> for info on generating signing keys and generating/verifying keys and sud files
<li>
All config files must be UTF-8.
<li>
To run in a separate JVM, use ShellCommand with java -cp foo:bar:baz my.main.class arg1 arg2 arg3.
Of course, it will be a lot harder to stop the plugin then...
But with some trickery with PID files it should be possible.
<li>
As an alternative to stopargs in clients.config,
a Java client may register a shutdown hook with I2PAppContext.addShutdownTask().
But this wouldn't shut down a plugin when upgrading, so stopargs is recommended.
Also, set all created threads to daemon mode.
<li>
Do not include classes duplicating those in the standard installation. Extend the classes if necessary.
<li>
Beware of the different classpath definitions in wrapper.config between old and new installations -
see classpath section below.
<li>
Clients will reject duplicate keys with different keynames, and duplicate keynames with different keys,
and different keys or keynames in upgrade packages. Safeguard your keys. Only generate them once.
<li>
Do not modify the plugin.config file at runtime as it will be overwritten on upgrade.
Use a different config file in the directory for storing runtime configuration.
<li>
In general, plugins should not require access to $I2P/lib/router.jar. Do not access router classes,
unless you are doing something special.
The router may in the future implement a restricted classpath for plugins that prevents
access to router classes.
<li>
Since each version must be higher than the one before, you could enhance your build
script to add a build number to the end of the version.
This helps for testing. Most of zzz's plugins have that feature, check build.xml for an example.
<li>
Plugins must never call System.exit().
<li>
Please respect licenses by meeting license requirements for any software you bundle.
</ul>
<h3>
Classpaths
</h3>
The following jars in $I2P/lib can be assumed to be in the standard classpath for all I2P installations,
no matter how old or how new the original installation:
<p>
i2p.jar, router.jar, jbigi.jar, sam.jar, mstreaming.jar, streaming.jar, i2ptunnel.jar,
org.mortbay.jetty.jar, javax.servlet.jar, jasper-compiler.jar, jasper-runtime.jar,
commons-logging.jar, commons-el.jar, wrapper.jar, systray.jar, systray4j.jar
<p>
Anything not listed above may not be present in everybody's classpath, even if you
have it in the classpath in YOUR version of i2p.
If you need any jar not listed above, add $I2P/lib/foo.jar to the classpath specified
in clients.config or webapps.config in your plugin.
<p>
Previously, a classpath entry specified in clients.config was added to the classpath for
the entire JVM.
However, as of 0.7.13-3, this was fixed using class loaders, and now, as originally intended,
the specified classpath in clients.config is only for the particular thread.
See the section on JVM crashes below, and
<a href="http://{{ i2pconv('zzz.i2p') }}/topics/633">this thread on zzz.i2p</a> for background.
Therefore, specify the full required classpath for each client.
<h3>
Java Version Notes
</h3>
While most I2P users are running a 1.6 (6.0) JVM, we support 1.5 (5.0) and higher JVMs.
Unless you require 1.6 features, you should create your plugin so it works on 1.5.
<p>
If your plugin <b>does not require 1.6</b>:
<ul>
<li>
Ensure that all java and jsp files are compiled with source="1.5" target="1.5".
<li>
Ensure that all bundled library jars are also for 1.5 or lower.
<li>
If you are using pack200, any 1.6 classes in a jar will
cause pack200 to create a 1.6 pack format, and
plugin installation will fail on a 1.5 system
with the misleading message "plugin is corrupt".
</ul>
<p>
If your plugin <b>requires 1.6</b>:
<ul>
<li>
Note that on your download page.
<li>
Add min-java-version=1.6 to your plugin.config
<li>
If you are using pack200, plugin installation will fail on a 1.5 system
with the misleading message "plugin is corrupt".
</ul>
<h3>
JVM Crashes When Updating
</h3>
Note - this should all be fixed now.
<p>
The JVM has a tendency to crash when updating jars in a plugin if that plugin was running
since i2p was started (even if the plugin was later stopped).
This may have been fixed with the class loader implementation in 0.7.13-3, but it may not.
For further testing.
<p>
The safest is to design your plugin with the jar inside the war (for a webapp), or to require a restart
after update, or don't update the jars in your plugin.
<p>
Due to the way class loaders work inside a webapp, it _may_ be safe to have external jars if
you specify the classpath in webapps.config.
More testing is required to verify this.
Don't specify the classpath with a 'fake' client in clients.config if it's only
needed for a webapp - use webapps.config instead.
<p>
The least safe, and apparently the source of most crashes, is clients with plugin jars specified
in the classpath in clients.config.
<p>
None of this should be a problem on initial install - you should not ever have to require a restart
for an initial install of a plugin.
{% endblock %}

View File

@@ -0,0 +1,929 @@
{% extends "global/layout.html" %}
{% block title %}SSU Protocol Specification{% endblock %}
{% block lastupdated %}July 2013{% endblock %}
{% block accuratefor %}0.9.7{% endblock %}
{% block content %}
Note: IPv6 information is preliminary.
<p>
<a href="{{ site_url('docs/transport/ssu') }}">See the SSU page for an overview of the SSU transport</a>.
<h1>Specification</h1>
<h2 id="DH">DH Key Exchange</h2>
<p>
The initial 2048-bit DH key exchange is described on the
<a href="{{ site_url('docs/transport/ssu') }}#keys">SSU page</a>.
This exchange uses the same shared prime as that used for I2P's
<a href="{{ site_url('docs/how/cryptography') }}#elgamal">ElGamal encryption</a>.
</p>
<h2 id="header">Message Header</h2>
<p>
All UDP datagrams begin with a 16 byte MAC (Message Authentication Code)
and a 16 byte IV (Initialization Vector)
followed by a variable-size
payload encrypted with the appropriate key. The MAC used is
HMAC-MD5, truncated to 16 bytes, while the key is a full 32 byte AES256
key. The specific construct of the MAC is the first 16 bytes from:</p>
<pre>
HMAC-MD5(payload || IV || (payloadLength ^ protocolVersion), macKey)
</pre>
where '||' means append.
The payload is the message starting with the flag byte.
The macKey is either the introduction key or is constructed from the
exchanged DH key (see details below), as specified for each message below.
Note that protocolVersion is 0, so the exclusive or is a no-op.
<b>WARNING</b> - the HMAC-MD5-128 used here is non-standard,
see <a href="{{ site_url('docs/how/cryptography') }}#udp">the cryptography page</a> for details.
<p>The payload itself (that is, the message starting with the flag byte)
is AES256/CBC encrypted with the IV and the
sessionKey, with replay prevention addressed within its body,
explained below. The payloadLength in the MAC is a 2 byte unsigned
integer.</p>
<p>The protocolVersion is a 2 byte unsigned integer
and is currently set to 0. Peers using a different protocol version will
not be able to communicate with this peer, though earlier versions not
using this flag are.</p>
<h3>Session Key Details</h3>
The 32-byte session key is created as follows:
<ol><li>
Take the exchanged DH key, represented as a positive minimal-length BigInteger byte array (two's complement big-endian)
</li><li>
If the most significant bit is 1 (i.e. array[0] & 0x80 != 0),
prepend a 0x00 byte, as in Java's BigInteger.toByteArray() representation
</li><li>
If the byte array is greater than or equal to 32 bytes, use the first (most significant) 32 bytes
</li><li>
If the byte array is less than 32 bytes, append 0x00 bytes to extend to 32 bytes.
<i>Won't happen - See note below</i>
</li></ol>
<h3>MAC Key Details</h3>
The 32-byte MAC key is created as follows:
<ol><li>
Take the exchanged DH key byte array, prepended with a 0x00 byte if necessary,
from step 2 in the Session Key Details above.
</li><li>
If that byte array is greater than or equal to 64 bytes, the MAC key is
bytes 33-64 from that byte array.
</li><li>
If that byte array is greater than 32 bytes but less than 64 bytes, the MAC key is formed from
the bytes starting at byte 33, followed by 0x00 bytes to extend the MAC key to 32 bytes.
<i>Broken - See note below</i>
</li><li>
If that byte array is equal to 32 bytes, the MAC key is all zeros.
<i>Broken - See note below</i>
</li><li>
If that byte array is less than 32 bytes, the MAC key is the SHA-256 Hash of the 32-bytes
from step 3 in the Session Key Details above.
<i>See note below</i>
</li></ol>
Important note: It appears that the existing code is buggy and does not correctly handle DH key byte arrays
between 32 and 63 bytes (steps 3 and 4 above) and the connection will fail.
As these cases won't ever work, they are subject to change (probably using SHA-256).
Since the nominal exchanged DH key is 256 bytes, the chances of the mininimal representation
being less than 64 bytes is vanishingly small.
<h3>Header Format</h3>
<p>Within the AES encrypted payload, there is a minimal common structure
to the various messages - a one byte flag and a four byte sending
timestamp (seconds since the unix epoch). The flag byte contains
the following bitfields:</p>
{% highlight %}
Bit order: 76543210 (bit 7 is MSB)
bits 7-4: payload type
bit 3: rekey?
bit 2: extended options included
bits 1-0: reserved
{% endhighlight %}
{% highlight lang='dataspec' %}
Header: 37+ bytes
Encryption starts with the flag byte.
+----+----+----+----+----+----+----+----+
| MAC |
+ +
| |
+----+----+----+----+----+----+----+----+
| IV |
+ +
| |
+----+----+----+----+----+----+----+----+
|flag| time | (optionally |
+----+----+----+----+----+ |
| this may have 64 byte keying material |
| and/or a one+N byte extended options) |
+---------------------------------------|
{% endhighlight %}
<h3 id="rekey">Rekeying</h3>
<p>If the rekey flag is set, 64 bytes of keying material follow the
timestamp.
<p>When rekeying, the first 32 bytes of the keying material is fed
into a SHA256 to produce the new MAC key, and the next 32 bytes are
fed into a SHA256 to produce the new session key, though the keys are
not immediately used. The other side should also reply with the
rekey flag set and that same keying material. Once both sides have
sent and received those values, the new keys should be used and the
previous keys discarded. It may be useful to keep the old keys
around briefly, to address packet loss and reordering.</p>
<p>NOTE: Rekeying is currently unimplemented.</p>
<h3 id="extend">Extended Options</h3>
<p>
If the extended options flag is set, a one byte option
size value is appended, followed by that many extended option
bytes.</p>
<p>NOTE: Extended options is currently unimplemented.</p>
<h2 id="padding">Padding</h2>
<p>
All messages contain 0 or more bytes of padding.
Each message must be padded to a 16 byte boundary, as required by the <a href="{{ site_url('docs/how/cryptography') }}#AES">AES256 encryption layer</a>.
Through release 0.9.7, messages were only padded to the next 16 byte boundary,
and messages not a multiple of 16 bytes could possibly be invalid.
As of release 0.9.7, messages may be padded to any length as long as the current MTU is honored.
Any extra 1-15 padding bytes beyond the last block of 16 bytes cannot be encrypted or decrypted and will be ignored.
However, the full length and all padding is included in the MAC calculation.
As of release 0.9.8, transmitted messages are not necessarily a multiple of 16 bytes.
The SessionConfirmed message is an exception, see below.
</p>
<h2 id="keys">Keys</h2>
<p>
DSA signatures in the SessionCreated and SessionConfirmed messages are generated using
the
<a href="{{ site_url('docs/spec/common-structures') }}#type_SigningPublicKey">signing public key</a>
from the
<a href="{{ site_url('docs/spec/common-structures') }}#struct_RouterIdentity">router identity</a>
which is distributed out-of-band by publishing in the network database, and the associated
<a href="{{ site_url('docs/spec/common-structures') }}#type_SigningPrivateKey">signing private key</a>.
</p><p>
Both introduction keys and session keys are 32 bytes,
and are defined by the
<a href="{{ site_url('docs/spec/common-structures') }}#type_SessionKey">Common structures specification</a>.
The key used for the MAC and encryption is specified for each message below.
</p>
<p>Introduction keys are delivered through an external channel
(the network database, where they are identical to the router Hash for now).
</p>
<h2 id="notes">Notes</h2>
<h3 id="ipv6">IPv6 Notes</h3>
While the protocol specification supports 16-byte IPv6 addresses,
IPv6 addressing is not currently supported within I2P.
All IP addresses are currently 4 bytes.
<h3 id="time">Timestamps</h3>
While most of I2P uses 8-byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Date">Date</a> timestamps with
millisecond resolution, SSU uses a 4-byte timestamp with one-second resolution.
<h2 id="messages">Messages</h2>
<p>
There are 10 messages (payload types) defined:
</p><p>
<table border="1">
<tr><th>Type<th>Message<th>Notes
<tr><td align="center">0<td>SessionRequest<td>
<tr><td align="center">1<td>SessionCreated<td>
<tr><td align="center">2<td>SessionConfirmed<td>
<tr><td align="center">3<td>RelayRequest<td>
<tr><td align="center">4<td>RelayResponse<td>
<tr><td align="center">5<td>RelayIntro<td>
<tr><td align="center">6<td>Data<td>
<tr><td align="center">7<td>PeerTest<td>
<tr><td align="center">8<td>SessionDestroyed<td>Implemented as of 0.8.9
<tr><td align="center">n/a<td>HolePunch<td>
</table>
</p>
<h3 id="sessionRequest">SessionRequest (type 0)</h3>
<p>
This is the first message sent to establish a session.
</p>
<table border="1">
<tr><td align="right" valign="top"><b>Peer:</b></td>
<td>Alice to Bob</td></tr>
<tr><td align="right" valign="top"><b>Data:</b></td>
<td><ul>
<li>256 byte X, to begin the DH agreement</li>
<li>1 byte IP address size</li>
<li>that many byte representation of Bob's IP address</li>
<li>N bytes, currently uninterpreted</li>
</ul></td></tr>
<tr><td align="right" valign="top"><b>Key used:</b></td>
<td>introKey</td></tr>
</table>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| X, as calculated from DH |
| |
. . .
| |
+----+----+----+----+----+----+----+----+
|size| that many byte IP address (4-16) |
+----+----+----+----+----+----+----+----+
| arbitrary amount |
| of uninterpreted data |
. . .
| |
+----+----+----+----+----+----+----+----+
{% endhighlight %}
<p>
Typical size including header, in current implementation: 304 (IPv4) or 320 (IPv6) bytes
</p>
<h4>Notes</h4>
<ul><li>
IPv4 and IPv6 addresses are supported.
</li><li>
The uninterpreted data could possibly be used in the future for challenges.
</li></ul>
<h3 id="sessionCreated">SessionCreated (type 1)</h3>
<p>
This is the response to a Session Request.
</p>
<table border="1">
<tr><td align="right" valign="top"><b>Peer:</b></td>
<td>Bob to Alice</td></tr>
<tr><td align="right" valign="top"><b>Data:</b></td>
<td><ul>
<li>256 byte Y, to complete the DH agreement</li>
<li>1 byte IP address size</li>
<li>that many byte representation of Alice's IP address</li>
<li>2 byte Alice's port number</li>
<li>4 byte relay (introduction) tag which Alice can publish (else 0x00000000)</li>
<li>4 byte timestamp (seconds from the epoch) for use in the DSA
signature</li>
<li>40 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Signature">DSA signature</a> of the critical exchanged data
(X + Y + Alice's IP + Alice's port + Bob's IP + Bob's port + Alice's
new relay tag + Bob's signed on time), encrypted with another
layer of encryption using the negotiated sessionKey. The IV
is reused here.</li>
<li>8 bytes padding, encrypted with an additional layer of encryption
using the negotiated session key as part of the DSA block</li>
<li>N bytes, currently uninterpreted</li>
</ul></td></tr>
<tr><td align="right" valign="top"><b>Key used:</b></td>
<td>introKey, with an additional layer of encryption over the 40 byte
signature and the following 8 bytes padding.</td></tr>
</table>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| Y, as calculated from DH |
| |
. . .
| |
+----+----+----+----+----+----+----+----+
|size| that many byte IP address (4-16) |
+----+----+----+----+----+----+----+----+
| Port (A)| public relay tag | signed
+----+----+----+----+----+----+----+----+
on time | |
+----+----+ |
| DSA signature |
+ +
| |
+ +
| |
+ +
| |
+ +----+----+----+----+----+----+
| | (8 bytes of padding)
+----+----+----+----+----+----+----+----+
| |
+----+----+ |
| arbitrary amount |
| of uninterpreted data |
. . .
| |
+----+----+----+----+----+----+----+----+
{% endhighlight %}
<p>
Typical size including header, in current implementation: 368 bytes (IPv4 or IPv6)
</p>
<h4>Notes</h4>
<ul><li>
IPv4 and IPv6 addresses are supported.
</li><li>
If the relay tag is nonzero, Bob is offering to act as an introducer for Alice.
Alice may subsequently publish Bob's address and the relay tag in the network database.
</li><li>
For the signature, Bob must use his external port, as that what Alice will use to verify.
If Bob's NAT/firewall has mapped his internal port to a different external port,
and Bob is unaware of it, the verification by Alice will fail.
</li><li>
See <a href="#keys">the Keys section above</a> for details on DSA signatures.
Alice already has Bob's public signing key, from the network database.
</li><li>
Signed-on time appears to be unused or unverified in the current implementation.
</li><li>
The uninterpreted data could possibly be used in the future for challenges.
</li></ul>
<h3 id="sessionConfirmed">SessionConfirmed (type 2)</h3>
<p>
This is the response to a Session Created message and the last step in establishing a session.
There may be multiple Session Confirmed messages required if the Router Identity must be fragmented.
</p>
<table border="1">
<tr><td align="right" valign="top"><b>Peer:</b></td>
<td>Alice to Bob</td></tr>
<tr><td align="right" valign="top"><b>Data:</b></td>
<td><ul>
<li>1 byte identity fragment info:<pre>
Bit order: 76543210 (bit 7 is MSB)
bits 7-4: current identity fragment # 0-14
bits 3-0: total identity fragments (F) 1-15</pre></li>
<li>2 byte size of the current identity fragment</li>
<li>that many byte fragment of Alice's
<a href="{{ site_url('docs/spec/common-structures') }}#struct_RouterIdentity">Router Identity</a>
</li>
<li>After the last identity fragment only:
<ul><li>4 byte signed-on time
</li></ul>
<li>N bytes padding, currently uninterpreted
<li>After the last identity fragment only:
<ul><li>The last 40
bytes contain the <a href="{{ site_url('docs/spec/common-structures') }}#type_Signature">DSA signature</a> of the critical exchanged
data (X + Y + Alice's IP + Alice's port + Bob's IP + Bob's port
+ Alice's new relay key + Alice's signed on time)</li>
</li></ul>
</ul></td></tr>
<tr><td align="right" valign="top"><b>Key used:</b></td>
<td>sessionKey</td></tr>
</table>
<b>Fragment 0 through F-2 (if F &gt; 1):</b>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
|info| cursize | |
+----+----+----+ |
| fragment of Alice's full |
| Router Identity |
. . .
| |
+----+----+----+----+----+----+----+----+
| arbitrary amount of uninterpreted |
| data |
+----+----+----+----+----+----+----+----+
{% endhighlight %}
<b>Fragment F-1 (last or only fragment):</b>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
|info| cursize | |
+----+----+----+ |
| last fragment of Alice's full |
| Router Identity |
. . .
| |
+----+----+----+----+----+----+----+----+
| signed on time | |
+----+----+----+----+ |
| arbitrary amount of uninterpreted |
| data, to 40 bytes prior to |
| end of the current packet |
| Packet length must be mult. of 16 |
+----+----+----+----+----+----+----+----+
| DSA signature |
+ +
| |
+ +
| |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
{% endhighlight %}
<p>
Typical size including header, in current implementation: 480 bytes
</p>
<h4>Notes</h4>
<ul><li>
In the current implementation, the maximum fragment size is 512 bytes.
</li><li>
The typical <a href="{{ site_url('docs/spec/common-structures') }}#struct_RouterIdentity">Router Identity</a>
is 387 bytes, so no fragmentation is ever necessary.
If new crypto extends the size of the RouterIdentity, the fragmentation scheme
must be tested carefully.
</li><li>
There is no mechanism for requesting or redelivering missing fragments.
</li><li>
The total fragments field F must be set identically in all fragments.
</li><li>
See <a href="#keys">the Keys section above</a> for details on DSA signatures.
</li><li>
Signed-on time appears to be unused or unverified in the current implementation.
</li><li>
Since the signature is at the end, the padding in the last or only packet must pad the total packet to
a multiple of 16 bytes, or the signature will not get decrypted correctly.
This is different from all the other message types, where the padding is at the end.
</li></ul>
<h3 id="sessionDestroyed">SessionDestroyed (type 8)</h3>
<p>
The Session Destroyed message was implemented (reception only) in release 0.8.1,
and is sent as of release 0.8.9.
</p>
<table border="1">
<tr><td align="right" valign="top"><b>Peer:</b></td>
<td>Alice to Bob or Bob to Alice</td></tr>
<tr><td align="right" valign="top"><b>Data:</b></td>
<td>none
</td></tr>
<tr><td align="right" valign="top"><b>Key used:</b></td>
<td>sessionKey or introKey</td></tr>
</table>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| no data |
+----+----+----+----+----+----+----+----+
{% endhighlight %}
<p>
Typical size including header, in current implementation: 48 bytes
</p>
<h3 id="relayRequest">RelayRequest (type 3)</h3>
<p>
This is the first message sent from Alice to Bob to request an introduction to Charlie.
</p>
<table border="1">
<tr><td align="right" valign="top"><b>Peer:</b></td>
<td>Alice to Bob</td></tr>
<tr><td align="right" valign="top"><b>Data:</b></td>
<td><ul>
<li>4 byte relay (introduction) tag, nonzero</li>
<li>1 byte IP address size</li>
<li>that many byte representation of Alice's IP address</li>
<li>2 byte port number (of Alice)</li>
<li>1 byte challenge size</li>
<li>that many bytes to be relayed to Charlie in the intro</li>
<li>Alice's 32-byte introduction key (so Bob can reply with Charlie's info)</li>
<li>4 byte nonce of Alice's relay request</li>
<li>N bytes, currently uninterpreted</li>
</ul></td></tr>
<tr><td align="right" valign="top"><b>Key used:</b></td>
<td>introKey (or sessionKey, if Alice/Bob is established)</td></tr>
</table>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| relay tag |size| Alice IP addr
+----+----+----+----+----+----+----+----+
| Port (A)|size| challenge bytes |
+----+----+----+----+ +
| to be delivered to Charlie |
+----+----+----+----+----+----+----+----+
| Alice's intro key |
+ +
| |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| nonce | |
+----+----+----+----+ |
| arbitrary amount of uninterpreted data|
+----+----+----+----+----+----+----+----+
{% endhighlight %}
<p>
Typical size including header, in current implementation: 96 bytes (no Alice IP included) or 112 bytes (4-byte Alice IP included)
</p>
<h4>Notes</h4>
<ul><li>
The IP address is only included if it is be different than the
packet's source address and port. In the current implementation, the
IP length is always 0 and the port is always 0, and the receiver should
use the packet's source address and port.
</li><li>
This message may be sent via IPv4 or IPv6. If IPv6, Alice must include her IPv4 address and port.
</li><li>
If Alice includes her address/port, Bob may perform additional validation before continuing.
</li><li>
Challenge is unimplemented, challenge size is always zero
</li><li>
There are no plans to implement relaying for IPv6.
</li></ul>
<h3 id="relayResponse">RelayResponse (type 4)</h3>
<p>
This is the response to a Relay Request and is sent from Bob to Alice.
</p>
<table border="1">
<tr><td align="right" valign="top"><b>Peer:</b></td>
<td>Bob to Alice</td></tr>
<tr><td align="right" valign="top"><b>Data:</b></td>
<td><ul>
<li>1 byte IP address size</li>
<li>that many byte representation of Charlie's IP address</li>
<li>2 byte Charlie's port number</li>
<li>1 byte IP address size</li>
<li>that many byte representation of Alice's IP address</li>
<li>2 byte Alice's port number</li>
<li>4 byte nonce sent by Alice</li>
<li>N bytes, currently uninterpreted</li>
</ul></td></tr>
<tr><td align="right" valign="top"><b>Key used:</b></td>
<td>introKey (or sessionKey, if Alice/Bob is established)</td></tr>
</table>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
|size| Charlie IP | Port (C)|size|
+----+----+----+----+----+----+----+----+
| Alice IP | Port (A)| nonce
+----+----+----+----+----+----+----+----+
| arbitrary amount of |
+----+----+ |
| uninterpreted data |
+----+----+----+----+----+----+----+----+
{% endhighlight %}
<p>
Typical size including header, in current implementation: 64 (Alice IPv4) or 80 (Alice IPv6) bytes
</p>
<h4>Notes</h4>
<ul><li>
This message may be sent via IPv4 or IPv6.
</li><li>
Alice's IP address/port are the apparent IP/port that Bob received the RelayRequest on
(not necessarily the IP Alice included in the RelayRequest),
and may be IPv4 or IPv6. Alice currently ignores these on receive.
</li><li>
Charlie's IP address must be IPv4, as that is the address that Alice will send
the SessionRequest to after the Hole Punch.
</li><li>
There are no plans to implement relaying for IPv6.
</li></ul>
<h3 id="relayIntro">RelayIntro (type 5)</h3>
<p>
This is the introduction for Alice, which is sent from Bob to Charlie.
</p>
<table border="1">
<tr><td align="right" valign="top"><b>Peer:</b></td>
<td>Bob to Charlie</td></tr>
<tr><td align="right" valign="top"><b>Data:</b></td>
<td><ul>
<li>1 byte IP address size</li>
<li>that many byte representation of Alice's IP address</li>
<li>2 byte port number (of Alice)</li>
<li>1 byte challenge size</li>
<li>that many bytes relayed from Alice</li>
<li>N bytes, currently uninterpreted</li>
</ul></td></tr>
<tr><td align="right" valign="top"><b>Key used:</b></td>
<td>sessionKey</td></tr>
</table>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
|size| Alice IP | Port (A)|size|
+----+----+----+----+----+----+----+----+
| that many bytes of challenge |
+ |
| data relayed from Alice |
+----+----+----+----+----+----+----+----+
| arbitrary amount of uninterpreted data|
+----+----+----+----+----+----+----+----+
{% endhighlight %}
<p>
Typical size including header, in current implementation: 48 bytes
</p>
<h4>Notes</h4>
<ul><li>
Alice's IP address is always 4 bytes in the current implementation, because Alice is trying to connect
to Charlie via IPv4.
</li><li>
This message must be sent via an established IPv4 connection, as that's the only way that
Bob knows Charlie's IPv4 address to return to Alice in the RelayResponse.
</li><li>
Challenge is unimplemented, challenge size is always zero
</li></ul>
<h3 id="data">Data (type 6)</h3>
<p>
This message is used for data transport and acknowledgment.
</p>
<table border="1">
<tr><td align="right" valign="top"><b>Peer:</b></td>
<td>Any</td></tr>
<tr><td align="right" valign="top"><b>Data:</b></td>
<td><ul>
<li>1 byte flags:<pre>
Bit order: 76543210 (bit 7 is MSB)
bit 7: explicit ACKs included
bit 6: ACK bitfields included
bit 5: reserved
bit 4: explicit congestion notification (ECN)
bit 3: request previous ACKs
bit 2: want reply
bit 1: extended data included (unused, never set)
bit 0: reserved</pre></li>
<li>if explicit ACKs are included:<ul>
<li>a 1 byte number of ACKs</li>
<li>that many 4 byte MessageIds being fully ACKed</li>
</ul></li>
<li>if ACK bitfields are included:<ul>
<li>a 1 byte number of ACK bitfields</li>
<li>that many 4 byte MessageIds + a 1 or more byte ACK bitfield.
The bitfield uses the 7 low bits of each byte, with the high
bit specifying whether an additional bitfield byte follows it
(1 = true, 0 = the current bitfield byte is the last). These
sequence of 7 bit arrays represent whether a fragment has been
received - if a bit is 1, the fragment has been received. To
clarify, assuming fragments 0, 2, 5, and 9 have been received,
the bitfield bytes would be as follows:<pre>
byte 0
Bit order: 76543210 (bit 7 is MSB)
bit 7: 1 (further bitfield bytes follow)
bit 6: 1 (fragment 0 received)
bit 5: 0 (fragment 1 not received)
bit 4: 1 (fragment 2 received)
bit 3: 0 (fragment 3 not received)
bit 2: 0 (fragment 4 not received)
bit 1: 1 (fragment 5 received)
bit 0: 0 (fragment 6 not received)
byte 1
Bit order: 76543210 (bit 7 is MSB)
bit 7: 0 (no further bitfield bytes)
bit 6: 0 (fragment 7 not received)
bit 5: 0 (fragment 8 not received)
bit 4: 1 (fragment 9 received)
bit 3: 0 (fragment 10 not received)
bit 2: 0 (fragment 11 not received)
bit 1: 0 (fragment 12 not received)
bit 0: 0 (fragment 13 not received)</pre></li>
</ul></li>
<li>If extended data included:<ul>
<li>1 byte data size</li>
<li>that many bytes of extended data (currently uninterpreted)</li></ul></li>
<li>1 byte number of fragments (can be zero)</li>
<li>If nonzero, that many message fragments. Each fragment contains:<ul>
<li>4 byte messageId</li>
<li>3 byte fragment info:<pre>
Bit order: 76543210 (bit 7 is MSB)
bits 23-17: fragment # 0 - 127
bit 16: isLast (1 = true)
bits 15-14: unused
bits 13-0: fragment size 0 - 16383</pre></li>
<li>that many bytes</li></ul>
<li>N bytes padding, uninterpreted</li>
</ul></td></tr>
<tr><td align="right" valign="top"><b>Key used:</b></td>
<td>sessionKey</td></tr>
</table>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
|flag| (additional headers, determined |
+----+ |
| by the flags, such as ACKs or |
| bitfields |
+----+----+----+----+----+----+----+----+
|#frg| messageId | frag info |
+----+----+----+----+----+----+----+----+
| that many bytes of fragment data |
. . .
| |
+----+----+----+----+----+----+----+----+
| messageId | frag info | |
+----+----+----+----+----+----+----+ |
| that many bytes of fragment data |
. . .
| |
+----+----+----+----+----+----+----+----+
| messageId | frag info | |
+----+----+----+----+----+----+----+ |
| that many bytes of fragment data |
. . .
| |
+----+----+----+----+----+----+----+----+
| arbitrary amount of uninterpreted data|
+----+----+----+----+----+----+----+----+
{% endhighlight %}
<h4>Notes</h4>
<ul><li>
The current implementation adds a limited number of duplicate acks for
messages previously acked, if space is available.
</li><li>
If the number of fragments is zero, this is an ack-only or keepalive message.
</li><li>
The ECN feature is unimplemented, and the bit is never set.
</li><li>
The want reply bit is always set in the current implementation.
</li><li>
Extended data is unimplemented and never present.
</li><li>
The current implementation does not pack multiple fragments into a single packet;
the number of fragments is always 0 or 1.
</li><li>
As currently implemented, maximum fragments is 64
(maximum fragment number = 63).
</li><li>
As currently implemented, maximum fragment size is of course
less than the MTU.
</li><li>
Take care not to exceed the maximum MTU even if there is a large number of
ACKs to send.
</li><li>
The protocol allows zero-length fragments but there's no reason to send them.
</li><li>
In SSU, the data uses a short 5-byte I2NP header followed by the payload
of the I2NP message instead of the standard 16-byte I2NP header.
The short I2NP header consists only of
the one-byte I2NP type and 4-byte expiration in seconds.
The I2NP message ID is used as the message ID for the fragment.
The I2NP size is assembled from the fragment sizes.
The I2NP checksum is not required as UDP message integrity is ensured by decryption.
</li><li>
Message IDs are not sequence numbers and are not consecutive.
SSU does not guarantee in-order delivery.
While we use the I2NP message ID as the SSU message ID, from the SSU
protocol view, they are random numbers.
In fact, since the router uses a single Bloom filter for all peers,
the message ID must be an actual random number.
</li><li>
Because there are no sequence numbers, there is no way to be sure an ACK was received.
The current implementation routinely sends a large amount of duplicate ACKs.
Duplicate ACKs should not be taken as an indication of congestion.
</li></ul>
<h3 id="peerTest">PeerTest (type 7)</h3>
<p>
See <a href="{{ site_url('docs/transport/ssu') }}#peerTesting">the SSU overview page</a> for details.
</p>
<table border="1">
<tr><td align="right" valign="top"><b>Peer:</b></td>
<td>Any</td></tr>
<tr><td align="right" valign="top"><b>Data:</b></td>
<td><ul>
<li>4 byte nonce</li>
<li>1 byte IP address size</li>
<li>that many byte representation of Alice's IP address</li>
<li>2 byte Alice's port number</li>
<li>Alice's 32-byte introduction key</li>
<li>N bytes, currently uninterpreted</li>
</ul></td></tr>
<tr><td align="right" valign="top"><b>Key used:</b></td>
<td>introKey (or sessionKey if the connection has already been established)</td></tr>
</table>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| test nonce |size| Alice IP addr
+----+----+----+----+----+----+----+----+
| Port (A)| |
+----+----+----+ +
| Alice or Charlie's |
+ introduction key (Alice's is sent to +
| Bob and Charlie, while Charlie's is |
+ sent to Alice) +
| |
| +----+----+----+----+----+
| | arbitrary amount of |
+----+----+----+ |
| uninterpreted data |
+----+----+----+----+----+----+----+----+
{% endhighlight %}
<p>
Typical size including header, in current implementation: 80 bytes
</p>
<h4>Notes</h4>
<ul><li>
When sent by Alice, IP address size is 0, IP address is not present, and port is 0,
as Bob and Charlie do not use the data;
the point is to determine Alice's true IP address/port and tell Alice;
Bob and Charlie don't care what Alice thinks her address is.
</li><li>
When sent by Bob or Charlie, IP and port are present, and
IP address is always 4 bytes in the current implementation.
IPv6 testing is not currently supported.
</li><li>
IPv6 Notes:
Only testing of IPv4 addresses is supported.
Therefore, all Alice-Bob and Alice-Charlie communication must be via IPv4.
Bob-Charlie communication, however, may be via IPv4 or IPv6.
Alice's address, when specified in the PeerTest message, must be 4 bytes.
</li></ul>
<h3 id="holePunch">HolePunch</h3>
<p>
A HolePunch is simply a UDP packet with no data.
It is unauthenticated and unencrypted.
It does not contain a SSU header, so it does not have a message type number.
It is sent from Charlie to Alice as a part of the Introduction sequence.
</p>
<h2><a name="sampleDatagrams">Sample datagrams</a></h2>
<b>Minimal data message (no fragments, no ACKs, no NACKs, etc)</b><br />
<i>(Size: 39 bytes)</i>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| MAC |
+ +
| |
+----+----+----+----+----+----+----+----+
| IV |
+ +
| |
+----+----+----+----+----+----+----+----+
|flag| time |flag|#frg| |
+----+----+----+----+----+----+----+ |
| padding to fit a full AES256 block |
+----+----+----+----+----+----+----+----+
{% endhighlight %}
<b>Minimal data message with payload</b><br />
<i>(Size: 46+fragmentSize bytes)</i>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| MAC |
+ +
| |
+----+----+----+----+----+----+----+----+
| IV |
+ +
| |
+----+----+----+----+----+----+----+----+
|flag| time |flag|#frg|
+----+----+----+----+----+----+----+----+
messageId | frag info | |
+----+----+----+----+----+----+ |
| that many bytes of fragment data |
. . .
| |
+----+----+----+----+----+----+----+----+
{% endhighlight %}
{% endblock %}

View File

@@ -0,0 +1,137 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Streaming Library Specification{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}July 2013{% endtrans %}{% endblock %}
{% block accuratefor %}0.9.6{% endblock %}
{% block content %}
<p><a href="{{ site_url('docs/api/streaming') }}">{% trans -%}
See the Streaming page for an overview of the Streaming Library.
{%- endtrans %}</a></p>
<h2>{% trans %}Protocol Specification{% endtrans %}</h2>
<h3>{% trans %}Packet Format{% endtrans %}</h3>
<p>{% trans -%}
The format of a single packet in the streaming protocol is:
{%- endtrans %}</p>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| send Stream ID | rcv Stream ID |
+----+----+----+----+----+----+----+----+
| sequence Num | ack Through |
+----+----+----+----+----+----+----+----+
| nc | NACKs ...
+----+----+----+----+----+----+----+----+
| rd | flags | opt size| opt data
+----+----+----+----+----+----+----+----+
... |
+----+----+----+----+----+----+----+----+
| payload ...
+----+----+----+-//
{% endhighlight %}
<table>
<tr><th>{{ _('Field') }}<th>{{ _('Length') }}<th>{{ _('Contents') }}
<tr><td>sendStreamId <td>4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td>Random number selected by the connection recipient
and constant for the life of the connection.
0 in the SYN message sent by the originator, and in subsequent messages, until a SYN reply is received,
containing the peer's stream ID.
<tr><td>receiveStreamId <td>4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td>Random number selected by the connection originator
and constant for the life of the connection. May be 0 if unknown, for example in a RESET packet.
<tr><td>sequenceNum <td>4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td>
The sequence for this message, starting at 0 in the SYN message,
and incremented by 1 in each message except for plain ACKs and retransmissions.
If the sequenceNum is 0 and the SYN flag is not set, this is a plain ACK
packet that should not be ACKed.
<tr><td>ackThrough <td>4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td>
The highest packet sequence number that was received
on the receiveStreamId. This field is ignored on the initial
connection packet (where receiveStreamId is the unknown id) or
if the NO_ACK flag set.
All packets up to and including this sequence number are ACKed,
EXCEPT for those listed in NACKs below.
<tr><td>NACK count<td>1 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td>
The number of 4-byte NACKs in the next field
<tr><td>NACKs <td>n * 4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integers</a><td>
Sequence numbers less than ackThrough that are not yet received.
Two NACKs of a packet is a request for a 'fast retransmit' of that packet.
<tr><td>resendDelay<td>1 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td>
How long is the creator of this packet going to wait before
resending this packet (if it hasn't yet been ACKed). The
value is seconds since the packet was created.
Currently ignored on receive.
<tr><td>flags <td>2 byte value<td>
See below.
<tr><td>option size<td>2 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td>
The number of bytes in the next field
<tr><td>option data<td>0 or more bytes<td>
As specified by the flags. See below.
<tr><td>payload <td>remaining packet size<td>
</table>
<h3>{% trans %}Flags and Option Data Fields{% endtrans %}</h3>
<p>{% trans -%}
The flags field above specifies some metadata about the packet, and in
turn may require certain additional data to be included. The flags are
as follows. Any data structures specified must be added to the options area
in the given order.
{%- endtrans %}</p>
<p>
Bit order: 15....0 (15 is MSB)
</p>
<table>
<tr><th>Bit<th>Flag<th>Option Data<th>Function
<tr><td>0<td>SYNCHRONIZE<td align="center">--<td>
Similar to TCP SYN. Set in the initial packet and in the first response.
FROM_INCLUDED and SIGNATURE_INCLUDED must be set also.
<tr><td>1<td>CLOSE<td align="center">--<td>
Similar to TCP FIN. If the response to a SYNCHRONIZE fits in a single message, the response
will contain both SYNCHRONIZE and CLOSE.
SIGNATURE_INCLUDED must be set also.
<tr><td>2<td>RESET<td align="center">--<td>
Abnormal close.
SIGNATURE_INCLUDED must be set also.
<tr><td>3<td>SIGNATURE_INCLUDED<td>40 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Signature">DSA Signature</a>
<td>
Currently sent only with SYNCHRONIZE, CLOSE, and RESET, where it is required.
The signature uses the Destination's <a href="{{ site_url('docs/spec/common-structures') }}#type_SigningPublicKey">DSA signing keys</a>
to sign the entire header and payload with the 40-byte space in the option data field
for the signature being set to all zeroes.
<tr><td>4<td>SIGNATURE_REQUESTED<td align="center">--<td>
Unused. Requests every packet in the other direction to have SIGNATURE_INCLUDED
<tr><td>5<td>FROM_INCLUDED<td>387+ byte <a href="{{ site_url('docs/spec/common-structures') }}#struct_Destination">Destination</a>
<td>
Currently sent only with SYNCHRONIZE, where it is required.
<tr><td>6<td>DELAY_REQUESTED<td>2 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td>
Optional delay.
How many milliseconds the sender of this packet wants the recipient
to wait before sending any more data.
A value greater than 60000 indicates choking.
<tr><td>7<td>MAX_PACKET_SIZE_INCLUDED<td>2 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td>
Currently sent with SYNCHRONIZE only.
Was also sent in retransmitted packets until release 0.9.1.
<tr><td>8<td>PROFILE_INTERACTIVE<td align="center">--<td>
Unused or ignored; the interactive profile is unimplemented.
<tr><td>9<td>ECHO<td align="center">--<td>
Unused except by ping programs
<tr><td>10<td>NO_ACK<td align="center">--<td>
This flag simply tells the recipient to ignore the ackThrough field in the header.
Currently set in the inital SYN packet, otherwise the ackThrough field is always valid.
Note that this does not save any space, the ackThrough field is before the flags
and is always present.
<tr><td>11-15<td>unused<td><td>
</table>
{% endblock %}

View File

@@ -0,0 +1,339 @@
{% extends "global/layout.html" %}
{% block title %}Tunnel Creation{% endblock %}
{% block lastupdated %}June 2013{% endblock %}
{% block accuratefor %}0.9.6{% endblock %}
{% block content %}
This page documents the current tunnel build implementation.
<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="{{ site_url('docs/tunnels/implementation') }}">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="{{ site_url('docs/how/cryptography') }}#elgamal">(ElGamal)</a>
encrypted to be
read only by a specific peer along the path, while an additional
symmetric layer of encryption
<a href="{{ site_url('docs/how/cryptography') }}#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="{{ site_url('docs/spec/i2np') }}#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="{{ site_url('docs/spec/i2np') }}#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="{{ site_url('docs/spec/i2np') }}#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, must set to 0 for compatibility with future options
</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.
Both cannot be set at once.
<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="{{ site_url('docs/how/cryptography') }}#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="{{ site_url('docs/how/cryptography') }}#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 16 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="{{ site_url('docs/how/cryptography') }}#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 495 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)
bytes 0-31 : SHA-256 of bytes 32-527
bytes 32-526 : Random padding
byte 527 : Reply value
</pre>
This is also described in the
<a href="{{ site_url('docs/spec/i2np') }}#struct_BuildResponseRecord">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="{{ site_url('docs/how/cryptography') }}#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="{{ site_url('docs/how/cryptography') }}#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="{{ site_url('docs/spec/i2np') }}#msg_TunnelBuildReply">TunnelBuildReplyMessage</a>
or
<a href="{{ site_url('docs/spec/i2np') }}#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="{{ site_url('docs/tunnels/implementation') }}#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="{{ site_url('docs/how/peer-selection') }}">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://forensics.umass.edu/pubs/wright-tissec.pdf">Predecessor
attack</a>
<li>
<a href="http://forensics.umass.edu/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><li>
The Build Request Record does not specify a tunnel lifetime or expiration;
each hop expires the tunnel after 10 minutes, which is a network-wide hardcoded constant.
We could use a bit in the flag field
and take 4 (or 8) bytes out of the padding to specify a lifetime or expiration.
The requestor would only specify this option if all participants supported it.
</li></ul>
{% endblock %}

View File

@@ -0,0 +1,310 @@
{% extends "global/layout.html" %}
{% block title %}Tunnel Message Specification{% endblock %}
{% block lastupdated %}October 2011{% endblock %}
{% block accuratefor %}0.8.10{% endblock %}
{% block content %}
<h1>Tunnel Message Specification</h1>
This document specifies the format of tunnel messages.
For general information about tunnels see
<a href="{{ site_url('docs/tunnels/implementation') }}">the tunnel documentation</a>.
<h2>Message preprocessing</h2>
A <i>tunnel gateway</i> is the entrance, or first hop, of a tunnel.
For an outbound tunnel, the gateway is the creator of the tunnel.
For an inbound tunnel, the gateway is at the opposite end from the creator of the tunnel.
<p>
A gateway <i>preprocesses</i> <a href="{{ site_url('docs/protocol/i2np') }}">I2NP messages</a>
by fragmenting and combining them into tunnel messages.
<p>
While I2NP messages are variable size from 0 to almost 64 KB,
tunnel messages are fixed-size, approximately 1 KB.
Fixed message size
restricts several types of attacks that are possible from
observing message size.
<p>
After the tunnel messages are created, they are encrypted as described in
<a href="{{ site_url('docs/tunnels/implementation') }}">the tunnel documentation</a>.
<h2 id="msg_Data">Tunnel Message (Encrypted)</h2>
These are the contents of a tunnel data message after encryption.
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| Tunnel_ID | IV |
+----+----+----+----+ +
| |
+ +----+----+----+----+
| | |
+----+----+----+----+ +
| |
+ Encrypted_Data +
~ ~
| |
+ +-------------------+
| |
+----+----+----+----+
{% endhighlight %}
<h4>Definition</h4>
{% highlight lang='dataspec' %}
Tunnel_ID ::
4 bytes
the ID of the next hop
IV ::
16 bytes
the initialization vector
Encrypted_Data ::
1008 bytes
the encrypted tunnel message
total size: 1028 Bytes
{% endhighlight %}
<h2 id="msg_Data">Tunnel Message (Decrypted)</h2>
These are the contents of a tunnel data message when decrypted.
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| Tunnel_ID | IV |
+----+----+----+----+ +
| |
+ +----+----+----+----+
| | Checksum |
+----+----+----+----+----+----+----+----+
| nonzero padding.. |
~ ~
| |
+ +----+
| |zero|
+----+----+----+----+----+----+----+----+
| |
| Delivery Instructions 1 |
~ ~
| |
+----+----+----+----+----+----+----+----+
| |
+ I2NP Message Fragment 1 +
| |
~ ~
| |
+----+----+----+----+----+----+----+----+
| |
| Delivery Instructions 2... |
~ ~
| |
+----+----+----+----+----+----+----+----+
| |
+ I2NP Message Fragment 2... +
| |
~ ~
| |
+ +-------------------+
| |
+----+----+----+----+
{% endhighlight %}
<h4>Definition</h4>
<pre>
Tunnel_ID ::
4 bytes
the ID of the next hop
IV ::
16 bytes
the initialization vector
Checksum ::
4 bytes
the first 4 bytes of the SHA256 hash of the remaining contents of the message concatenated with the IV
Nonzero_padding ::
0 or more bytes
random nonzero data for padding
Zero ::
1 byte
the value 0x00
Delivery_Instructions ::
length varies but is typically 7, 39, 43, or 47 bytes
Indicates the fragment and the routing for the fragment
See <a href="#delivery">below</a> for specification
Message_Fragment ::
1 to 996 bytes, actual maximum depends on delivery instruction size
A partial or full I2NP Message
total size: 1028 Bytes
</pre>
<p>Note that the padding, if any, must be before the instruction/message pairs.
there is no provision for padding at the end.</p>
<h2 id="delivery">Delivery Instructions</h2>
<p>The instructions are encoded with a single control byte, followed by any
necessary additional information. The first bit (MSB) in that control byte determines
how the remainder of the header is interpreted - if it is not set, the message
is either not fragmented or this is the first fragment in the message. If it is
set, this is a follow on fragment.</p>
<p>
Note that Delivery Instructions are also used inside
<a href="{{ site_url('docs/spec/i2np') }}#struct_GarlicClove">Garlic Cloves</a>,
where the format is slightly different. In a Garlic Clove,
messages are not fragmented, and the fragment bit in the flag byte is
redefined. See the
<a href="{{ site_url('docs/spec/i2np') }}#struct_GarlicClove">Garlic Clove documentation</a>
for more details.
<h3>First Fragment Delivery Instructions</h3>
<p>If the MSB of the first byte is 0, this is an initial I2NP message fragment,
or a complete I2NP message, and the instructions are:</p>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
|flag| Tunnel ID (opt) | |
+----+----+----+----+----+ +
| |
+ +
| To Hash (optional) |
+ +
| |
+ +--------------+
| |dly | Msg... |
+----+----+----+----+----+----+----+----+
|..ID(opt)| ext opts... (opt) | size |
+----+----+----+----+----+----+----+----+
{% endhighlight %}
<h4>Definition</h4>
<pre>
flag:
1 byte
Bit order: 76543210
bit 7: 0 to specify an initial fragment
bits 6-5: delivery type
For tunnel messages:
0x0 = LOCAL, 0x01 = TUNNEL, 0x02 = ROUTER, 0x03 = unused
For garlic cloves:
0x0 = LOCAL, 0x01 = DESTINATION, 0x02 = ROUTER, 0x03 = TUNNEL
bit 4: delay included? Unimplemented, always 0
If 1, a delay byte is included
bit 3: fragmented? If 0, the message is not fragmented, what follows is the entire message
If 1, the message is fragmented, and the instructions contain a Message ID
bit 2: extended options? Unimplemented, always 0
If 1, extended options are included
bits 1-0: reserved
Tunnel ID:
4 bytes
Optional, present if delivery type is TUNNEL
The destination tunnel ID
To Hash:
32 bytes
Optional, present if delivery type is DESTINATION, ROUTER, or TUNNEL
If DESTINATION, the SHA256 Hash of the destination
If ROUTER, the SHA256 Hash of the router
If TUNNEL, the SHA256 Hash of the gateway router
Delay:
1 byte (tunnel message) or 4 bytes (garlic clove)
Optional, present if delay included flag is set
In tunnel messages: Unimplemented, never present; original specification:
bit 7: type (0 = strict, 1 = randomized)
bits 6-0: delay exponent (2^value minutes)
In garlic cloves: Not fully implemented. A 4 byte integer specifying the delay in seconds.
Message ID:
4 bytes
Optional, present if this message is the first of 2 or more fragments
An ID that uniquely identifies all fragments as belonging to a single message
(the current implementation uses the <a href="{{ site_url('docs/spec/i2np') }}#struct_header">I2NP Message ID</a>)
Extended Options:
2 or more bytes
Optional, present if extend options flag is set
Unimplemented, never present; original specification:
One byte length and then that many bytes
size:
2 bytes
The length of the fragment that follows
Valid values: 1 to approx. 960 in a tunnel message; 1 to 64K - 1 in a garlic clove
Total length: Typical length is:
3 bytes for LOCAL delivery (garlic clove);
35 bytes for ROUTER / DESTINATION delivery or 39 bytes for TUNNEL delivery (unfragmented or garlic clove);
39 bytes for ROUTER delivery or 43 bytes for TUNNEL delivery (first fragment)
</pre>
<h3>Follow-on Fragment Delivery Instructions</h3>
<p>If the MSB of the first byte is 1, this is a follow-on fragment, and the instructions are:</p>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+
|frag| Message_ID | size |
+----+----+----+----+----+----+----+
{% endhighlight %}
<h4>Definition</h4>
{% highlight lang='dataspec' %}
frag ::
1 byte
binary 1nnnnnnd
the first bit is 1 to indicate this is a follow-on fragment
nnnnnn is the 6 bit fragment number from 1 to 63
d is 1 to indicate the last fragment, 0 otherwise
Message_ID ::
4 bytes
the same ID specified in the first fragment
size ::
2 bytes
the length of the fragment that follows
valid values: 1 to 996
total length: 7 bytes
{% endhighlight %}
<h3><a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/i2np/DeliveryInstructions.html">Delivery Instructions Javadoc</a></h3>
<h2 id="notes">Notes</h2>
<h3>I2NP Message Maximum Size</h3>
<p>
While the maximum I2NP message size is nominally 64 KB, the size is further constrained by the
method of fragmenting I2NP messages into multiple 1 KB tunnel messages.
The maximum number of fragments is 64, and the initial fragment may not
be perfectly aligned at the start of a tunnel message.
So the message must nominally fit in 63 fragments.
<p>
The maximum size of an initial fragment is 956 bytes (assuming TUNNEL delivery mode);
the maximum size of a follow-on fragment is 996 bytes.
Therefore the maximum size is approximately 956 + (62 * 996) = 62708 bytes, or 61.2 KB.
</p>
<h3>Ordering, Batching, Packing</h3>
Tunnel messages may be dropped or reordered.
The tunnel gateway, who creates tunnel messages, is free to implement any
batching, mixing, or reordering strategy to fragment I2NP messages and
efficiently pack fragments into tunnel messages.
In general, an optimal packing is not possible (the "packing problem").
The gateways may implement various delay and reordering strategies.
<h3>Cover Traffic</h3>
Tunnel messages may contain only padding (i.e. no delivery instructions or message fragments at all)
for cover traffic. This is unimplemented.
{% endblock %}

View File

@@ -0,0 +1,237 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}I2P Software Update Specification{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}July 2013{% endtrans %}{% endblock %}
{% block accuratefor %}0.9.7{% endblock %}
{% block content %}
<h3>{% trans %}Overview{% endtrans %}</h3>
<p>{% trans -%}
I2P uses a simple, yet secure, system for automated software update.
The router console periodically pulls a news file from a configurable I2P URL.
There is a hardcoded backup URL pointing to the project website, in case
the default project news host goes down.
{%- endtrans %}</p>
<p>{% trans -%}
The contents of the news file are displayed on the home page of the router console.
In addition, the news file contains the most recent version number of the software.
If the version is higher than the router's version number, it will
display an indication to the user that an update is available.
{%- endtrans %}</p>
<p>{% trans -%}
The router may optionally download, or download and install, the new version
if configured to do so.
{%- endtrans %}</p>
<h3>{% trans %}News File Specification{% endtrans %}</h3>
<p>{% trans -%}
The news.xml file may contain the following elements:
{%- endtrans %}</p>
<pre>
&lt;i2p.news date="$Date: 2010-01-22 00:00:00 $" /&gt;
&lt;i2p.release version="0.7.14" date="2010/01/22" minVersion="0.6" /&gt;
</pre>
<p>{% trans -%}
The elements may be included inside XML comments to prevent interpretation by browsers.
The i2p.release element and version are required. All others are optional and are
currently unused.
{%- endtrans %}</p>
<p>{% trans -%}
The news source is trusted only to indicate that a new version is available.
It does not specify the URL of the update, the checksum, or any other information.
{%- endtrans %}</p>
<h3>{% trans %}Update File Specification{% endtrans %}</h3>
<p>{% trans -%}
The signed update file, traditionally named i2pupdate.sud,
is simply a zip file with a prepended 56 byte header.
The header contains:
{%- endtrans %}</p>
<ul>
<li>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
A 40-byte <a href="{{ commonstructures }}#type_signature">DSA signature</a>
{%- endtrans %}</li>
<li>{% trans -%}
A 16-byte I2P version in UTF-8, padded with trailing zeroes if necessary
{%- endtrans %}</li>
</ul>
<p>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
The signature covers only the zip archive - not the prepended version.
The signature must match one of the <a href="{{ commonstructures }}#type_SigningPublicKey">DSA public keys</a> configured into the router,
which has a hardcoded default list of keys of the current project release managers.
{%- endtrans %}</p>
<p>{% trans -%}
For version comparison purposes, version fields contain [0-9]*, field separators are
'-', '_', and '.', and all other characters are ignored.
{%- endtrans %}</p>
<p>{% trans -%}
As of version 0.8.8, the version must also be specified as a zip file comment in UTF-8,
without the trailing zeroes.
The updating router verifes that the version in the header (not covered by the signature)
matches the version in the zip file comment, which is covered by the signature.
This prevents spoofing of the version number in the header.
{%- endtrans %}</p>
<h3>{% trans %}Download and Installation{% endtrans %}</h3>
<p>{% trans -%}
The router first downloads the header of the update file from one in a configurable list of I2P URLs,
using the built-in HTTP client and proxy,
and checks that the version is newer.
This prevents the problem of update hosts that do not have the latest file.
The router then downloads the full update file.
The router verifies that the update file version is newer before installation.
It also, of course, verifies the signature, and
verifes that the zip file comment matches the header version, as explained above.
{%- endtrans %}</p>
<p>{% trans -%}
The zip file is extracted in the base $I2P installation directory.
{%- endtrans %}</p>
<p>{% trans -%}
As of release 0.7.12, the router supports Pack200 decompression.
Files inside the zip archive with a .jar.pack or .war.pack suffix
are transparently decompressed to a .jar or .war file.
Update files containing .pack files are traditionally named with a '.su2' suffix.
Pack200 shrinks the update files by about 60&#37;.
{%- endtrans %}</p>
<p>{% trans -%}
As of release 0.8.7, the router will delete the libjbigi.so and libjcpuid.so files
if the zip archive contains a lib/jbigi.jar file, so that the new files will
be extracted from jbigi.jar.
{%- endtrans %}</p>
<p>{% trans -%}
As of release 0.8.12, if the zip archive contains a file deletelist.txt, the router will
delete the files listed there. The format is:
{%- endtrans %}</p>
<ul>
<li>{% trans %}One file name per line{% endtrans %}</li>
<li>{% trans %}All file names are relative to the installation directory; no absolute file names allowed, no files starting with ".."{% endtrans %}</li>
<li>{% trans %}Comments start with '#'{% endtrans %}</li>
</ul>
<p>{% trans -%}
The router will then delete the deletelist.txt file.
{%- endtrans %}</p>
<h3>{% trans %}New "su3" Update File Specification{% endtrans %}</h3>
<p>{% trans -%}
This specification is preliminary and is not yet implemented.
{%- endtrans %}</p>
<h4>{% trans %}Issues with existing .sud/.su2 format:{% endtrans %}</h4>
<ul>
<li>{% trans -%}
No magic number or flags
{%- endtrans %}</li>
<li>{% trans -%}
No way to specify compression, pack200 or not, or signing algo
{%- endtrans %}</li>
<li>{% trans -%}
Version is not covered by signature, so it is enforced by requiring it
to be in the zip file comment (for router files) or in the plugin.config
file (for plugins)
{%- endtrans %}</li>
<li>{% trans -%}
Signer not specified so verifier must try all known keys
{%- endtrans %}</li>
<li>{% trans -%}
Signature-before-data format requires two passes to generate file
{%- endtrans %}</li>
</ul>
<h4>{% trans %}Goals:{% endtrans %}</h4>
<ul>
<li>{% trans -%}
Fix above problems
{%- endtrans %}</li>
<li>{% trans -%}
Migrate to more secure signature algorithm
{%- endtrans %}</li>
<li>{% trans -%}
Keep version info in same format and offset for compatibility with
existing version checkers
{%- endtrans %}</li>
</ul>
<h4>{% trans %}Specification:{% endtrans %}</h4>
<table><tr>
<th>Bytes<th>Contents
<tr><td>
0-5 <td>Magic number "I2Psu3"
<tr><td>
6 <td>unused = 0
<tr><td>
7 <td>su3 file format version = 0
<tr><td>
8 <td>unused
<tr><td>
9 <td>Signature type 0x00 = DSA-160, 0x01 = new algo
<tr><td>
10-11 <td>Signature length 40 (0x0028) = DSA-160
<tr><td>
12 <td>unused
<tr><td>
13 <td>Version length (in bytes not chars, including padding)
must be at least 16 (0x10) for compatibility
<tr><td>
14 <td>unused
<tr><td>
15 <td>Signer ID length (in bytes not chars)
<tr><td>
16-23 <td>Compressed content length (not including header or sig)
<tr><td>
24 <td>unused
<tr><td>
25 <td>Compressed type 0x00 = zip
<tr><td>
26 <td>unused
<tr><td>
27 <td>Content type 0x00 = router w/o pack200, 0x01 = router w/ pack200, 0x02 = plugin
<tr><td>
28-39 <td>unused
<tr><td>
40-55+ <td>Version, UTF-8 padded with trailing 0x00, 16 bytes min.
<tr><td>
xx+ <td>ID of signer, (e.g. "zzz@mail.i2p") UTF-8, not padded
<tr><td>
xx+ <td>Compressed content, length and format specified in header
No requirement on the zip file comment since the sig covers the version.
<tr><td>
xx+ <td>Signature, length specified in header, covers everything starting at byte 0
</table>
<p>{% trans -%}
All unused fields must be set to 0 for compatibility with future versions.
{%- endtrans %}</p>
<h3>{% trans %}Future Work{% endtrans %}</h3>
<ul>
<li>{% trans -%}
The network will eventually grow too large for update over HTTP.
The built-in BitTorrent client, i2psnark, may be used as a distributed update method.
This development effort is ongoing and should be completed by late 2013.
{%- endtrans %}</li>
<li>{% trans -%}
The router update mechanism is part of the web router console.
There is currently no provision for updates of an embedded router lacking the router console.
{%- endtrans %}</li>
</ul>
{% endblock %}

View File

@@ -0,0 +1,168 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Transport Overview{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}April 2013{% endtrans %}{% endblock %}
{% block accuratefor %}0.9.5{% endblock %}
{% block content %}
<h1>{% trans %}Transports in I2P{% endtrans %}</h1>
<p>{% trans -%}
A "transport" in I2P is a method for direct, point-to-point communication
between two routers.
Transports must provide confidentiality and integrity
against external adversaries while authenticating that the router contacted
is the one who should receive a given message.
{%- endtrans %}</p>
<p>{% trans -%}
I2P supports multiple transports simultaneously.
There are two transports currently implemented:
{%- endtrans %}</p>
<ol>
<li>{% trans ntcp=site_url('docs/transport/ntcp') %}<a href="{{ ntcp }}">NTCP</a>, a Java New I/O (NIO) TCP transport{% endtrans %}</li>
<li>{% trans ssu=site_url('docs/transport/ssu') %} <a href="{{ ssu }}">SSU</a>, or Secure Semireliable UDP{% endtrans %}</li>
</ol>
<p>{% trans -%}
Each provides a "connection" paradigm, with authentication,
flow control, acknowledgments and retransmission.
{%- endtrans %}</p>
<h2>{% trans %}Transport Services{% endtrans %}</h2>
<p>{% trans -%}
The transport subsystem in I2P provides the following services:
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
Maintain a set of router addresses, one or more for each transport,
that the router publishes as its global contact information (the RouterInfo)
{%- endtrans %}</li>
<li>{% trans %}Selection of the best transport for each outgoing message{% endtrans %}</li>
<li>{% trans %}Queueing of outbound messages by priority{% endtrans %}</li>
<li>{% trans %}Bandwidth limiting, both outbound and inbound, according to router configuration{% endtrans %}</li>
<li>{% trans %}Setup and teardown of transport connections{% endtrans %}</li>
<li>{% trans %}Encryption of point-to-point communications{% endtrans %}</li>
<li>{% trans -%}
Maintenance of connection limits for each transport, implementation of various thresholds for these limits,
and communication of threshold status to the router so it may make operational changes based on the status
{%- endtrans %}</li>
<li>{% trans %}Firewall port opening using UPnP (Universal Plug and Play){% endtrans %}</li>
<li>{% trans %}Cooperative NAT/Firewall traversal{% endtrans %}</li>
<li>{% trans %}Local IP detection by various methods, including UPnP, inspection of incoming connections, and enumeration of network devices{% endtrans %}</li>
<li>{% trans %}Coordination of firewall status and local IP, and changes to either, among the transports{% endtrans %}</li>
<li>{% trans %}Communication of firewall status and local IP, and changes to either, to the router and the user interface{% endtrans %}</li>
<li>{% trans %}Determination of a consensus clock, which is used to periodically update the router's clock, as a backup for NTP{% endtrans %}</li>
<li>{% trans -%}
Maintenance of status for each peer, including whether it is connected, whether it was recently connected,
and whether it was reachable in the last attempt
{%- endtrans %}</li>
<li>{% trans %}Qualification of valid IP addresses according to a local rule set{% endtrans %}</li>
<li>{% trans -%}
Honoring the automated and manual lists of banned peers maintained by the router,
and refusing outbound and inbound connections to those peers
{%- endtrans %}</li>
</ul>
<h2>{% trans %}Transport Addresses{% endtrans %}</h2>
<p>{% trans -%}
The transport subsystem maintains a set of router addresses, each of which lists a transport method, IP, and port.
These addresses constitute the advertised contact points, and are published by the router to the network database.
{%- endtrans %}</p>
<p>{% trans %}Typical scenarios are:{% endtrans %}
<ul>
<li>{% trans %}A router has no published addresses, so it is considered "hidden" and cannot receive incoming connections{% endtrans %}</li>
<li>{% trans ssu=site_url('docs/transport/ssu') -%}
A router is firewalled, and therefore publishes an SSU address which contains a list of cooperating
peers or "introducers" who will assist in NAT traversal (see <a href="{{ ssu }}">the SSU spec</a> for details)
{%- endtrans %}</li>
<li>{% trans -%}
A router is not firewalled or its NAT ports are open; it publishes both NTCP and SSU addresses containing
directly-accessible IP and ports.
{%- endtrans %}</li>
</ul>
<h2>{% trans %}Transport Selection{% endtrans %}</h2>
<p>{% trans i2np=site_url('docs/protocol/i2np'),
streaming=site_url('docs/api/streaming'),
datagrams=site_url('docs/api/datagrams') -%}
The transport system delivers <a href="{{ i2np }}">I2NP messages</a>. The transport selected for any message is
independent of the upper-layer protocols and contents (router or client messages, whether an external application was using
TCP or UDP to connect to I2P, whether the upper layer was using
<a href="{{ streaming }}">the streaming library</a>
streaming
or
<a href="{{ datagrams }}">datagrams</a>,
datagrams
etc.).
{%- endtrans %}</p>
<p>{% trans -%}
For each outgoing message, the transport system solicits "bids" from each transport.
The transport bidding the lowest (best) value wins the bid and receives the message for delivery.
A transport may refuse to bid.
{%- endtrans %}</p>
<p>{% trans -%}
Whether a transport bids, and with what value, depend on numerous factors:
{%- endtrans %}</p>
<ul>
<li>{% trans %}Configuration of transport preferences{% endtrans %}</li>
<li>{% trans %}Whether the transport is already connected to the peer{% endtrans %}</li>
<li>{% trans %}The number of current connections compared to various connection limit thresholds{% endtrans %}</li>
<li>{% trans %}Whether recent connection attempts to the peer have failed{% endtrans %}</li>
<li>{% trans %}The size of the message, as different transports have different size limits{% endtrans %}</li>
<li>{% trans %}Whether the peer can accept incoming connections for that transport, as advertised in its RouterInfo{% endtrans %}</li>
<li>{% trans %}Whether the connection would be indirect (requiring introducers) or direct{% endtrans %}</li>
<li>{% trans %}The peer's transport preference, as advertised in its RouterInfo{% endtrans %}</li>
</ul>
<p>{% trans -%}
In general, the bid values are selected so that two routers are only connected by a single transport
at any one time. However, this is not a requirement.
{%- endtrans %}</p>
<h2>{% trans %}New Transports and Future Work{% endtrans %}</h2>
<p>{% trans -%}
Additional transports may be developed, including:
{%- endtrans %}</p>
<ul>
<li>{% trans %}A TLS/SSH look-alike transport{% endtrans %}</li>
<li>{% trans %}An "indirect" transport for routers that are not reachable by all other routers (one form of "restricted routes"){% endtrans %}</li>
</ul>
<p>{% trans thread='http://'+i2pconv('zzz.i2p')+'/topics/109' -%}
IPv6: The existing transports must be enhanced to support multiple addresses within a single transport,
including IPV6 addresses. Currently, a transport may only advertise a single IPV4 address.
See <a href="{{ thread }}">this thread</a> for discussion.
{%- endtrans %}</p>
<p>{% trans -%}
Work continues on adjusting default connection limits for each transport.
I2P is designed as a "mesh network", where it is assumed that any router can connect to any other router.
This assumption may be broken by routers that have exceeded their connection limits, and by
routers that are behind restrictive state firewalls (restricted routes).
{%- endtrans %}</p>
<p>{% trans -%}
The current connection limits are higher for SSU than for NTCP, based on the assumption that
the memory requirements for an NTCP connection are higher than that for SSU.
However, as NTCP buffers are partially in the kernel and SSU buffers are on the Java heap,
that assumption is difficult to verify.
{%- endtrans %}</p>
<p>{% trans pdf='http://www.iis.se/docs/hjelmvik_breaking.pdf' -%}
Analyze <a href="{{ pdf }}">Breaking and Improving Protocol Obfuscation</a>
and see how transport-layer padding may improve things.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,471 @@
{% extends "global/layout.html" %}
{% block title %}NTCP{% endblock %}
{% block lastupdated %}{% trans %}August 2010{% endtrans %}{% endblock %}
{% block accuratefor %}0.8{% endblock %}
{% block content %}
<h2>{% trans %}NTCP (NIO-based TCP){% endtrans %}</h2>
<p>{% trans transports=site_url('docs/transport'), ssu=site_url('docs/transport/ssu') -%}
NTCP is one of two <a href="{{ transports }}">transports</a> currently implemented in I2P.
The other is <a href="{{ ssu }}">SSU</a>.
NTCP is a Java NIO-based transport introduced in I2P release 0.6.1.22.
Java NIO (new I/O) does not suffer from the 1 thread per connection issues of the old TCP transport.
{%- endtrans %}</p>
<p>{% trans -%}
By default, NTCP uses the IP/Port
auto-detected by SSU. When enabled on config.jsp,
SSU will notify/restart NTCP when the external address changes
or when the firewall status changes.
Now you can enable inbound TCP without a static IP or dyndns service.
{%- endtrans %}</p>
<p>{% trans -%}
The NTCP code within I2P is relatively lightweight (1/4 the size of the SSU code)
because it uses the underlying Java TCP transport for reliable delivery.
{%- endtrans %}</p>
<h2>{% trans %}NTCP Protocol Specification{% endtrans %}</h2>
<h3>{% trans %}Standard Message Format{% endtrans %}</h3>
<p>{% trans -%}
After establishment,
the NTCP transport sends individual I2NP messages, with a simple checksum.
The unencrypted message is encoded as follows:
{%- endtrans %}</p>
{% highlight lang='dataspec' %}
+-------+-------+--//--+---//----+-------+-------+-------+-------+
| sizeof(data) | data | padding | Adler checksum of sz+data+pad |
+-------+-------+--//--+---//----+-------+-------+-------+-------+
{% endhighlight %}
<p>{% trans -%}
The data is then AES/256/CBC encrypted. The session key for the encryption
is negotiated during establishment (using Diffie-Hellman 2048 bit).
The establishment between two routers is implemented in the EstablishState class
and detailed below.
The IV for AES/256/CBC encryption is the last 16 bytes of the previous encrypted message.
{%- endtrans %}</p>
<p>{% trans -%}
0-15 bytes of padding are required to bring the total message length
(including the six size and checksum bytes) to a multiple of 16.
The maximum message size is currently 16 KB.
Therefore the maximum data size is currently 16 KB - 6, or 16378 bytes.
The minimum data size is 1.
{%- endtrans %}</p>
<h3>{% trans %}Time Sync Message Format{% endtrans %}</h3>
<p>{% trans -%}
One special case is a metadata message where the sizeof(data) is 0. In
that case, the unencrypted message is encoded as:
{%- endtrans %}</p>
{% highlight lang='dataspec' %}
+-------+-------+-------+-------+-------+-------+-------+-------+
| 0 | timestamp in seconds | uninterpreted
+-------+-------+-------+-------+-------+-------+-------+-------+
uninterpreted | Adler checksum of bytes 0-11 |
+-------+-------+-------+-------+-------+-------+-------+-------+
{% endhighlight %}
<p>{% trans -%}
Total length: 16 bytes. The time sync message is sent at approximately 15 minute intervals.
The message is encrypted just as standard messages are.
{%- endtrans %}</p>
<h3>{% trans %}Checksums{% endtrans %}</h3>
<p>{% trans rfc1950='http://tools.ietf.org/html/rfc1950' -%}
The standard and time sync messages use the Adler-32 checksum
as defined in the <a href="{{ rfc1950 }}">ZLIB Specification</a>.
{%- endtrans %}</p>
<h3>{% trans %}Establishment Sequence{% endtrans %}</h3>
<p>{% trans -%}
In the establish state, there is a 4-phase message sequence to exchange DH keys and signatures.
In the first two messages there is a 2048-bit Diffie Hellman exchange.
Then, DSA signatures of the critical data are exchanged to confirm the connection.
{%- endtrans %}</p>
{% highlight %}
Alice contacts Bob
=========================================================
X+(H(X) xor Bob.identHash)-----------------------------&gt;
&lt;----------------------------------------Y+E(H(X+Y)+tsB+padding, sk, Y[239:255])
E(sz+Alice.identity+tsA+padding+S(X+Y+Bob.identHash+tsA+tsB), sk, hX_xor_Bob.identHash[16:31])---&gt;
&lt;----------------------E(S(X+Y+Alice.identHash+tsA+tsB)+padding, sk, prev)
{% trans %}Legend:{% endtrans %}
X, Y: {% trans %}256 byte DH public keys{% endtrans %}
H(): 32 byte SHA256 Hash
E(data, session key, IV): AES256 Encrypt
S(): 40 byte DSA Signature
tsA, tsB: {% trans %}timestamps (4 bytes, seconds since epoch){% endtrans %}
sk: {% trans %}32 byte Session key{% endtrans %}
sz: {% trans %}2 byte size of Alice identity to follow{% endtrans %}
{% endhighlight %}
<h4 id="DH">{% trans %}DH Key Exchange{% endtrans %}</h4>
<p>{% trans cryptography=site_url('docs/how/cryptography') -%}
The initial 2048-bit DH key exchange
uses the same shared prime (p) and generator (g) as that used for I2P's
<a href="{{ cryptography }}#elgamal">ElGamal encryption</a>.
{%- endtrans %}</p>
<p>{% trans -%}
The DH key exchange consists of a number of steps, displayed below.
The mapping between these steps and the messages sent between I2P routers,
is marked in bold.
{%- endtrans %}</p>
<ol>
<li>{% trans %}Alice generates a secret 226-bit integer x. She then calculates <code>X = g^x mod p</code>.{% endtrans %}</li>
<li>{% trans %}Alice sends X to Bob <b>(Message 1)</b>.{% endtrans %}</li>
<li>{% trans %}Bob generates a secret 226-bit integer y. He then calculates <code>Y = g^y mod p</code>.{% endtrans %}</li>
<li>{% trans %}Bob sends Y to Alice.<b>(Message 2)</b>{% endtrans %}</li>
<li>{% trans %}Alice can now compute <code>sessionKey = Y^x mod p</code>.{% endtrans %}</li>
<li>{% trans %}Bob can now compute <code>sessionKey = X^y mod p</code>.{% endtrans %}</li>
<li>{% trans %}Both Alice and Bob now have a shared key <code>sessionKey = g^(x*y) mod p</code>.{% endtrans %}</li>
</ol>
<p>{% trans -%}
The sessionKey is then used to exchange identities in <b>Message 3</b> and <b>Message 4</b>.
{%- endtrans %}</p>
<h4>{% trans %}Message 1 (Session Request){% endtrans %}</h4>
<p>{% trans commonstructures=site_url('docs/spec/common-structures'),
netdb=site_url('docs/how/network-database') -%}
This is the DH request. Alice already has Bob's
<a href="{{ commonstructures }}#struct_RouterIdentity">Router Identity</a>,
IP address, and port, as contained in his
<a href="{{ commonstructures }}#struct_RouterInfo">Router Info</a>,
which was published to the
<a href="{{ netdb }}">network database</a>.
Alice sends Bob:
{%- endtrans %}</p>
{% highlight %}
X+(H(X) xor Bob.identHash)-----------------------------&gt;
{% trans %}Size:{% endtrans %} 288 bytes
{% endhighlight %}
<p>{% trans %}Contents:{% endtrans %}</p>
<pre>
+----+----+----+----+----+----+----+----+
| X, as calculated from DH |
+ +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
| |
+ +
| HXxorHI |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
X: {% trans %}256 byte X from Diffie Hellman{% endtrans %}
HXxorHI: {% trans commonstructures=site_url('docs/spec/common-structures') -%}
SHA256 Hash(X) xored with SHA256 Hash(Bob's <a href="{{ commonstructures }}#struct_RouterIdentity">Router Identity</a>)
{%- endtrans %}
(32 bytes)
</pre>
<p><b>{% trans %}Notes:{% endtrans %}</b>
<ul><li>{% trans -%}
Bob verifies HXxorHI using his own router hash. If it does not verify,
Alice has contacted the wrong router, and Bob drops the connection.
{%- endtrans %}</li></ul>
<h4>{% trans %}Message 2 (Session Created){% endtrans %}</h4>
<p>{% trans -%}
This is the DH reply. Bob sends Alice:
{%- endtrans %}</p>
{% highlight %}
&lt;----------------------------------------Y+E(H(X+Y)+tsB+padding, sk, Y[239:255])
{% trans %}Size:{% endtrans %} 304 bytes
{% endhighlight %}
<p>{% trans %}Unencrypted Contents:{% endtrans %}</p>
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| Y as calculated from DH |
+ +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
| |
+ +
| HXY |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| tsB | padding |
+----+----+----+----+ +
| |
+----+----+----+----+----+----+----+----+
Y: {% trans %}256 byte Y from Diffie Hellman{% endtrans %}
HXY: {% trans %}SHA256 Hash(X concatenated with Y){% endtrans %}
(32 bytes)
tsB: {% trans %}4 byte timestamp (seconds since the epoch){% endtrans %}
padding: {% trans %}12 bytes random data{% endtrans %}
{% endhighlight %}
<p>{% trans %}Encrypted Contents:{% endtrans %}</p>
<pre>
+----+----+----+----+----+----+----+----+
| Y as calculated from DH |
+ +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
| |
+ +
| encrypted data |
+ +
| |
+ +
| |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
Y: {% trans %}256 byte Y from Diffie Hellman{% endtrans %}
encrypted data: {% trans cryptography=site_url('docs/how/cryptography') -%}
48 bytes <a href="{{ cryptography }}#AES">AES encrypted</a> using the DH session key and
the last 16 bytes of Y as the IV{% endtrans %}
</pre>
<p><b>{% trans %}Notes:{% endtrans %}</b></p>
<ul><li>{% trans -%}
Alice may drop the connection if the clock skew with Bob is too high as calculated using tsB.
{%- endtrans %}</li></ul>
<h4>{% trans %}Message 3 (Session Confirm A){% endtrans %}</h4>
<p>{% trans -%}
This contains Alice's router identity, and a DSA signature of the critical data. Alice sends Bob:
{%- endtrans %}</p>
{% highlight %}
E(sz+Alice.identity+tsA+padding+S(X+Y+Bob.identHash+tsA+tsB), sk, hX_xor_Bob.identHash[16:31])---&gt;
{% trans %}Size:{% endtrans %} 448 bytes (typ. for 387 byte identity)
{% endhighlight %}
<p>{% trans %}Unencrypted Contents:{% endtrans %}</p>
<pre>
+----+----+----+----+----+----+----+----+
| sz | Alice's Router Identity |
+----+----+ +
| |
~ . . . ~
| |
+ +----+----+----+
| | tsA
+----+----+----+----+----+----+----+----+
| padding |
+----+ +
| |
+----+----+----+----+----+----+----+----+
| |
+ +
| signature |
+ +
| |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
sz: {% trans %}2 byte size of Alice's router identity to follow (should always be 387){% endtrans %}
ident: {% trans commonstructures=site_url('docs/spec/common-structures') -%}
Alice's 387 byte <a href="{{ commonstructures }}#struct_RouterIdentity">Router Identity</a>
{%- endtrans %}
tsA: {% trans %}4 byte timestamp (seconds since the epoch){% endtrans %}
padding: {% trans %}15 bytes random data{% endtrans %}
signature: {% trans commonstructures=site_url('docs/spec/common-structures') -%}
the 40 byte <a href="{{ commonstructures }}#type_Signature">DSA signature</a> of the following concatenated data:
X, Y, Bob's <a href="{{ commonstructures }}#struct_RouterIdentity">Router Identity</a>, tsA, tsB.
Alice signs it with the <a href="{{ commonstructures }}#type_SigningPrivateKey">private signing key</a> associated with the <a href="{{ commonstructures }}#type_SigningPublicKey">public signing key</a> in her <a href="{{ commonstructures }}#struct_RouterIdentity">Router Identity</a>
{%- endtrans %}
</pre>
<p>{% trans %}Encrypted Contents:{% endtrans %}</p>
<pre>
+----+----+----+----+----+----+----+----+
| |
+ +
| encrypted data |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
encrypted data: {% trans cryptography=site_url('docs/how/cryptography') -%}
448 bytes <a href="{{ cryptography }}#AES">AES encrypted</a> using the DH session key and
the last 16 bytes of HXxorHI (i.e., the last 16 bytes of message #1) as the IV
{%- endtrans %}
</pre>
<p><b>{% trans %}Notes:{% endtrans %}</b></p>
<ul>
<li>{% trans -%}
Bob verifies the signature, and on failure, drops the connection.
{%- endtrans %}</li>
<li>{% trans -%}
Bob may drop the connection if the clock skew with Alice is too high as calculated using tsA.
{%- endtrans %}</li>
</ul>
<h4>{% trans %}Message 4 (Session Confirm B){% endtrans %}</h4>
<p>{% trans -%}
This is a DSA signature of the critical data. Bob sends Alice:
{%- endtrans %}</p>
{% highlight %}
* &lt;----------------------E(S(X+Y+Alice.identHash+tsA+tsB)+padding, sk, prev)
{% trans %}Size:{% endtrans %} 48 bytes
{% endhighlight %}
<p>{% trans %}Unencrypted Contents:{% endtrans %}</p>
<pre>
+----+----+----+----+----+----+----+----+
| |
+ +
| signature |
+ +
| |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| padding |
+----+----+----+----+----+----+----+----+
signature: {% trans commonstructures=site_url('docs/spec/common-structures') -%}
the 40 byte <a href="{{ commonstructures }}#type_Signature">DSA signature</a> of the following concatenated data:
X, Y, Alice's <a href="{{ commonstructures }}#struct_RouterIdentity">Router Identity</a>, tsA, tsB.
Bob signs it with the <a href="{{ commonstructures }}#type_SigningPrivateKey">private signing key</a> associated with the <a href="{{ commonstructures }}#type_SigningPublicKey">public signing key</a> in his <a href="{{ commonstructures }}#struct_RouterIdentity">Router Identity</a>
{%- endtrans %}
padding: {% trans %}8 bytes random data{% endtrans %}
</pre>
<p>{% trans %}Encrypted Contents:{% endtrans %}</p>
<pre>
+----+----+----+----+----+----+----+----+
| |
+ +
| encrypted data |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
encrypted data: {% trans cryptography=site_url('docs/how/cryptography') -%}
48 bytes <a href="{{ cryptography }}#AES">AES encrypted</a> using the DH session key and
the last 16 bytes of the encrypted contents of message #2 as the IV
{%- endtrans %}
</pre>
<p><b>Notes:</b></p>
<ul><li>{% trans -%}
Alice verifies the signature, and on failure, drops the connection.
{%- endtrans %}</li></ul>
<h4>{% trans %}After Establishment{% endtrans %}</h4>
<p>{% trans -%}
The connection is established, and standard or time sync messages may be exchanged.
All subsequent messages are AES encrypted using the negotiated DH session key.
Alice will use the last 16 bytes of the encrypted contents of message #3 as the next IV.
Bob will use the last 16 bytes of the encrypted contents of message #4 as the next IV.
{%- endtrans %}</p>
<h3>{% trans %}Check Connection Message{% endtrans %}</h3>
<p>{% trans -%}
Alternately, when Bob receives a connection, it could be a
check connection (perhaps prompted by Bob asking for someone
to verify his listener).
Check Connection is not currently used.
However, for the record, check connections are formatted as follows.
A check info connection will receive 256 bytes containing:
{%- endtrans %}</p>
<ul>
<li>{% trans %}32 bytes of uninterpreted, ignored data{% endtrans %}</li>
<li>{% trans %}1 byte size{% endtrans %}</li>
<li>{% trans %}that many bytes making up the local router's IP address (as reached by the remote side){% endtrans %}</li>
<li>{% trans %}2 byte port number that the local router was reached on{% endtrans %}</li>
<li>{% trans %}4 byte i2p network time as known by the remote side (seconds since the epoch){% endtrans %}</li>
<li>{% trans %}uninterpreted padding data, up to byte 223{% endtrans %}</li>
<li>{% trans %}xor of the local router's identity hash and the SHA256 of bytes 32 through bytes 223{% endtrans %}</li>
</ul>
</pre>
<h2>{% trans %}Discussion{% endtrans %}</h2>
<p>{% trans ntcpdisc=site_url('docs/discussions/ntcp') -%}
Now on the <a href="{{ ntcpdisc }}">NTCP Discussion Page</a>.
{%- endtrans %}</p>
<h2><a name="future">{% trans %}Future Work{% endtrans %}</a></h2>
<ul>
<li>{% trans -%}
The maximum message size should be increased to approximately 32 KB.
{%- endtrans %}</li>
<li>{% trans -%}
A set of fixed packet sizes may be appropriate to further hide the data
fragmentation to external adversaries, but the tunnel, garlic, and end to
end padding should be sufficient for most needs until then.
However, there is currently no provision for padding beyond the next 16-byte boundary,
to create a limited number of message sizes.
{%- endtrans %}</li>
<li>{% trans -%}
Memory utilization (including that of the kernel) for NTCP should be compared to that for SSU.
{%- endtrans %}</li>
<li>{% trans -%}
Can the establishment messages be randomly padded somehow, to frustrate
identification of I2P traffic based on initial packet sizes?
{%- endtrans %}</li>
<li>{% trans -%}
Review and possibly disable 'check connection'
{%- endtrans %}</li>
</ul>
{% endblock %}

View File

@@ -0,0 +1,571 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}SSU Transport{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}May 2013{% endtrans %}{% endblock %}
{% block accuratefor %}0.9.6{% endblock %}
{% block content %}
<h1>{% trans %}Secure Semireliable UDP{% endtrans %} (SSU)</h1>
Note: IPv6 information is preliminary.
<p>{% trans transports=site_url('docs/transport'), ntcp=site_url('docs/transport/ntcp') -%}
SSU (also called "UDP" in much of the I2P documentation and user interfaces)
is one of two <a href="{{ transports }}">transports</a> currently implemented in I2P.
The other is <a href="{{ ntcp }}">NTCP</a>.
{%- endtrans %}</p>
<p>{% trans -%}
SSU is the newer of the two transports,
introduced in I2P release 0.6.
In a standard I2P installation, the router uses both NTCP and SSU for outbound connections.
{%- endtrans %}</p>
<h2>{% trans %}SSU Services{% endtrans %}</h2>
<p>{% trans -%}
Like the NTCP transport, SSU provides reliable, encrypted, connection-oriented, point-to-point data transport.
Unique to SSU, it also provides IP detection and NAT traversal services, including:
{%- endtrans %}</p>
<ul>
<li>{% trans %}Cooperative NAT/Firewall traversal using <a href="#introduction">introducers</a>{% endtrans %}</li>
<li>{% trans %}Local IP detection by inspection of incoming packets and <a href="#peerTesting">peer testing</a>{% endtrans %}</li>
<li>{% trans %}Communication of firewall status and local IP, and changes to either to NTCP{% endtrans %}</li>
<li>{% trans %}Communication of firewall status and local IP, and changes to either, to the router and the user interface{% endtrans %}</li>
</ul>
<h1>{% trans %}Protocol Details{% endtrans %}</h1>
<h2><a name="congestioncontrol">{% trans %}Congestion control{% endtrans %}</a></h2>
<p>{% trans -%}
SSU's need for only semireliable delivery, TCP-friendly operation,
and the capacity for high throughput allows a great deal of latitude in
congestion control. The congestion control algorithm outlined below is
meant to be both efficient in bandwidth as well as simple to implement.
{%- endtrans %}</p>
<p>{% trans -%}
Packets are scheduled according to the router's policy, taking care
not to exceed the router's outbound capacity or to exceed the measured
capacity of the remote peer. The measured capacity operates along the
lines of TCP's slow start and congestion avoidance, with additive increases
to the sending capacity and multiplicative decreases in face of congestion.
Unlike for TCP, routers may give up on some messages after
a given period or number of retransmissions while continuing to transmit
other messages.
{%- endtrans %}</p>
<p>{% trans -%}
The congestion detection techniques vary from TCP as well, since each
message has its own unique and nonsequential identifier, and each message
has a limited size - at most, 32KB. To efficiently transmit this feedback
to the sender, the receiver periodically includes a list of fully ACKed
message identifiers and may also include bitfields for partially received
messages, where each bit represents the reception of a fragment. If
duplicate fragments arrive, the message should be ACKed again, or if the
message has still not been fully received, the bitfield should be
retransmitted with any new updates.
{%- endtrans %}</p>
<p>{% trans -%}
The current implementation does not pad the packets to
any particular size, but instead just places a single message fragment into
a packet and sends it off (careful not to exceed the MTU).
{%- endtrans %}</p>
<h3><a name="mtu">MTU</a></h3>
<p>{% trans -%}
As of router version 0.8.12,
two MTU values are used for IPv4: 620 and 1484.
The MTU value is adjusted based on the percentage of packets that are retransmitted.
{%- endtrans %}</p>
<p>{% trans -%}
For both MTU values, it is desirable that (MTU &#37; 16) == 12, so that
the payload portion after the 28-byte IP/UDP header is a multiple of
16 bytes, for encryption purposes.
{%- endtrans %}</p>
<p>{% trans -%}
For the small MTU value, it is desirable to pack a 2646-byte
Variable Tunnel Build Message efficiently into multiple packets;
with a 620-byte MTU, it fits into 5 packets with nicely.
{%- endtrans %}</p>
<p>{% trans -%}
Based on measurements, 1492 fits nearly all reasonably small I2NP messages
(larger I2NP messages may be up to 1900 to 4500 bytes, which isn't going to fit
into a live network MTU anyway).
{%- endtrans %}</p>
<p>{% trans -%}
The MTU values were 608 and 1492 for releases 0.8.9 - 0.8.11.
The large MTU was 1350 prior to release 0.8.9.
{%- endtrans %}</p>
<p>{% trans -%}
The maximum receive packet size
is 1571 bytes as of release 0.8.12.
For releases 0.8.9 - 0.8.11 it was 1535 bytes.
Prior to release 0.8.9 it was 2048 bytes.
{%- endtrans %}</p>
<p>{% trans -%}
As of release 0.9.2, if a router's network interface MTU is less than 1484,
it will publish that in the network database, and other routers should
honor that when a connection is established.
{%- endtrans %}</p>
<p>{% trans -%}
For IPv6, the minimum MTU is 1280. The IPv6 IP/UDP header is 48 bytes,
so we use an MTU where (MTN &#37; 16 == 0), which is true for 1280.
{%- endtrans %}</p>
<h3><a name="max">{% trans %}Message Size Limits{% endtrans %}</a></h3>
<p>{% trans -%}
While the maximum message size is nominally 32KB, the practical
limit differs. The protocol limits the number of fragments to 7 bits, or 128.
The current implementation, however, limits each message to a maximum of 64 fragments,
which is sufficient for 64 * 534 = 33.3 KB when using the 608 MTU.
Due to overhead for bundled LeaseSets and session keys, the practical limit
at the application level is about 6KB lower, or about 26KB.
Further work is necessary to raise the UDP transport limit above 32KB.
For connections using the larger MTU, larger messages are possible.
{%- endtrans %}</p>
<h2><a name="keys">{% trans %}Keys{% endtrans %}</a></h2>
<p>{% trans -%}
All encryption used is AES256/CBC with 32 byte keys and 16 byte IVs.
The MAC and session keys are negotiated as part of the DH exchange, used
for the HMAC and encryption, respectively. Prior to the DH exchange,
the publicly knowable introKey is used for the MAC and encryption.
{%- endtrans %}</p>
<p>{% trans -%}
When using the introKey, both the initial message and any subsequent
reply use the introKey of the responder (Bob) - the responder does
not need to know the introKey of the requester (Alice). The DSA
signing key used by Bob should already be known to Alice when she
contacts him, though Alice's DSA key may not already be known by
Bob.
{%- endtrans %}</p>
<p>{% trans -%}
Upon receiving a message, the receiver checks the "from" IP address and port
with all established sessions - if there are matches,
that session's MAC keys are tested in the HMAC. If none
of those verify or if there are no matching IP addresses, the
receiver tries their introKey in the MAC. If that does not verify,
the packet is dropped. If it does verify, it is interpreted
according to the message type, though if the receiver is overloaded,
it may be dropped anyway.
{%- endtrans %}</p>
<p>{% trans -%}
If Alice and Bob have an established session, but Alice loses the
keys for some reason and she wants to contact Bob, she may at any
time simply establish a new session through the SessionRequest and
related messages. If Bob has lost the key but Alice does not know
that, she will first attempt to prod him to reply, by sending a
DataMessage with the wantReply flag set, and if Bob continually
fails to reply, she will assume the key is lost and reestablish a
new one.
{%- endtrans %}</p>
<p>{% trans rfc3526='http://www.faqs.org/rfcs/rfc3526.html' -%}
For the DH key agreement,
<a href="{{ rfc3526 }}">RFC3526</a> 2048bit
MODP group (#14) is used:
{%- endtrans %}</p>
<pre>
p = 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 }
g = 2
</pre>
<p>{% trans cryptography=site_url('docs/how/cryptography') -%}
These are the same p and g used for I2P's
<a href="{{ cryptography }}#elgamal">ElGamal encryption</a>.
{%- endtrans %}</p>
<h2><a name="replay">{% trans %}Replay prevention{% endtrans %}</a></h2>
<p>{% trans -%}
Replay prevention at the SSU layer occurs by rejecting packets
with exceedingly old timestamps or those which reuse an IV. To
detect duplicate IVs, a sequence of Bloom filters are employed to
"decay" periodically so that only recently added IVs are detected.
{%- endtrans %}</p>
<p>{% trans -%}
The messageIds used in DataMessages are defined at layers above
the SSU transport and are passed through transparently. These IDs
are not in any particular order - in fact, they are likely to be
entirely random. The SSU layer makes no attempt at messageId
replay prevention - higher layers should take that into account.
{%- endtrans %}</p>
<h2 id="addressing">{% trans %}Addressing{% endtrans %}</h2>
<p>{% trans -%}
To contact an SSU peer, one of two sets of information is necessary:
a direct address, for when the peer is publicly reachable, or an
indirect address, for using a third party to introduce the peer.
There is no restriction on the number of addresses a peer may have.
{%- endtrans %}</p>
{% highlight %}
Direct: host, port, introKey, options
Indirect: tag, relayhost, port, relayIntroKey, targetIntroKey, options
{% endhighlight %}
<p>{% trans -%}
Each of the addresses may also expose a series of options - special
capabilities of that particular peer. For a list of available
capabilities, see <a href="#capabilities">below</a>.
{%- endtrans %}</p>
<p>{% trans netdb=site_url('docs/how/network-database') -%}
The addresses, options, and capabilities are published in the <a href="{{ netdb }}">network database</a>.
{%- endtrans %}</p>
<h2><a name="direct">{% trans %}Direct Session Establishment{% endtrans %}</a></h2>
<p>{% trans -%}
Direct session establishment is used when no third party is required for NAT traversal.
The message sequence is as follows:
{%- endtrans %}</p>
<h3><a name="establishDirect">{% trans %}Connection establishment (direct){% endtrans %}</a></h3>
<p>{% trans -%}
Alice connects directly to Bob.
{%- endtrans %}</p>
{% highlight %}
Alice Bob
SessionRequest ---------------------&gt;
&lt;--------------------- SessionCreated
SessionConfirmed -------------------&gt;
&lt;--------------------- DeliveryStatusMessage
&lt;--------------------- DatabaseStoreMessage
DatabaseStoreMessage ---------------&gt;
Data &lt;---------------------------&gt; Data
{% endhighlight %}
<p>{% trans i2npspec=site_url('docs/spec/i2np') -%}
After the SessionConfirmed message is received, Bob sends a small
<a href="{{ i2npspec }}#msg_DeliveryStatus">DeliveryStatus message</a>
as a confirmation.
In this message, the 4-byte message ID is set to a random number, and the
8-byte "arrival time" is set to the current network-wide ID, which is 2
(i.e. 0x0000000000000002).
{%- endtrans %}</p>
<p>{% trans i2npspec=site_url('docs/spec/i2np'),
commonstructures=site_url('docs/spec/common-structures') -%}
After the status message is sent, the peers exchange
<a href="{{ i2npspec }}#msg_DatabaseStore">DatabaseStore messages</a>
containing their
<a href="{{ commonstructures }}#struct_RouterInfo">RouterInfos</a>.
{%- endtrans %}</p>
<p>{% trans -%}
It does not appear that the type of the status message or its contents matters.
It was originally added becasue the DatabaseStore message was delayed
several seconds; since the store is now sent immediately, perhaps
the status message can be eliminated.
{%- endtrans %}</p>
<h2><a name="introduction">{% trans %}Introduction{% endtrans %}</a></h2>
<p>{% trans -%}
Introduction keys are delivered through an external channel
(the network database, where they are identical to the router Hash for now)
and must be used when establishing a session key. For the indirect
address, the peer must first contact the relayhost and ask them for
an introduction to the peer known at that relayhost under the given
tag. If possible, the relayhost sends a message to the addressed
peer telling them to contact the requesting peer, and also gives
the requesting peer the IP and port on which the addressed peer is
located. In addition, the peer establishing the connection must
already know the public keys of the peer they are connecting to (but
not necessary to any intermediary relay peer).
{%- endtrans %}</p>
<p>{% trans -%}
Indirect session establishment by means of a third party introduction
is necessary for efficient NAT traversal. Charlie, a router behind a
NAT or firewall which does not allow unsolicited inbound UDP packets,
first contacts a few peers, choosing some to serve as introducers. Each
of these peers (Bob, Bill, Betty, etc) provide Charlie with an introduction
tag - a 4 byte random number - which he then makes available to the public
as methods of contacting him. Alice, a router who has Charlie's published
contact methods, first sends a RelayRequest packet to one or more of the
introducers, asking each to introduce her to Charlie (offering the
introduction tag to identify Charlie). Bob then forwards a RelayIntro
packet to Charlie including Alice's public IP and port number, then sends
Alice back a RelayResponse packet containing Charlie's public IP and port
number. When Charlie receives the RelayIntro packet, he sends off a small
random packet to Alice's IP and port (poking a hole in his NAT/firewall),
and when Alice receives Bob's RelayResponse packet, she begins a new
full direction session establishment with the specified IP and port.
{%- endtrans %}</p>
<!--
should Bob wait for Charlie to ack the RelayIntro packet to avoid
situations where that packet is lost yet Alice gets Charlie's IP with
Charlie not yet punching a hole in his NAT for her to get through?
Perhaps Alice should send to multiple Bobs at once, hoping that at
least one of them gets through
-->
<h3><a name="establishIndirect">{% trans %}Connection establishment (indirect using an introducer){% endtrans %}</a></h3>
<p>{% trans -%}
Alice first connects to introducer Bob, who relays the request to Charlie.
{%- endtrans %}</p>
{% highlight %}
Alice Bob Charlie
RelayRequest ----------------------&gt;
&lt;-------------- RelayResponse RelayIntro -----------&gt;
&lt;-------------------------------------------- HolePunch (data ignored)
SessionRequest --------------------------------------------&gt;
&lt;-------------------------------------------- SessionCreated
SessionConfirmed ------------------------------------------&gt;
&lt;-------------------------------------------- DeliveryStatusMessage
&lt;-------------------------------------------- DatabaseStoreMessage
DatabaseStoreMessage --------------------------------------&gt;
Data &lt;--------------------------------------------------&gt; Data
{% endhighlight %}
<p>{% trans -%}
After the hole punch, the session is established between Alice and Charlie as in a direct establishment.
{%- endtrans %}</p>
<p>
IPv6 notes:
Alice-Bob communication may be via IPv4 or IPv6.
Bob-Charlie and Alice-Charlie communication is via IPv4.
</p>
<h2><a name="peerTesting">{% trans %}Peer testing{% endtrans %}</a></h2>
<p>{% trans -%}
The automation of collaborative reachability testing for peers is
enabled by a sequence of PeerTest messages. With its proper
execution, a peer will be able to determine their own reachability
and may update its behavior accordingly. The testing process is
quite simple:
{%- endtrans %}</p>
{% highlight %}
Alice Bob Charlie
PeerTest -------------------&gt;
PeerTest--------------------&gt;
&lt;-------------------PeerTest
&lt;-------------------PeerTest
&lt;------------------------------------------PeerTest
PeerTest------------------------------------------&gt;
&lt;------------------------------------------PeerTest
{% endhighlight %}
<p>{% trans -%}
Each of the PeerTest messages carry a nonce identifying the
test series itself, as initialized by Alice. If Alice doesn't
get a particular message that she expects, she will retransmit
accordingly, and based upon the data received or the messages
missing, she will know her reachability. The various end states
that may be reached are as follows:
{%- endtrans %}</p>
<ul>
<li>{% trans -%}
If she doesn't receive a response from Bob, she will retransmit
up to a certain number of times, but if no response ever arrives,
she will know that her firewall or NAT is somehow misconfigured,
rejecting all inbound UDP packets even in direct response to an
outbound packet. Alternately, Bob may be down or unable to get
Charlie to reply.
{%- endtrans %}</li>
<li>{% trans -%}
If Alice doesn't receive a PeerTest message with the
expected nonce from a third party (Charlie), she will retransmit
her initial request to Bob up to a certain number of times, even
if she has received Bob's reply already. If Charlie's first message
still doesn't get through but Bob's does, she knows that she is
behind a NAT or firewall that is rejecting unsolicited connection
attempts and that port forwarding is not operating properly (the
IP and port that Bob offered up should be forwarded).
{%- endtrans %}</li>
<li>{% trans -%}
If Alice receives Bob's PeerTest message and both of Charlie's
PeerTest messages but the enclosed IP and port numbers in Bob's
and Charlie's second messages don't match, she knows that she is
behind a symmetric NAT, rewriting all of her outbound packets with
different 'from' ports for each peer contacted. She will need to
explicitly forward a port and always have that port exposed for
remote connectivity, ignoring further port discovery.
{%- endtrans %}</li>
<li>{% trans -%}
If Alice receives Charlie's first message but not his second,
she will retransmit her PeerTest message to Charlie up to a
certain number of times, but if no response is received she knows
that Charlie is either confused or no longer online.
{%- endtrans %}</li>
</ul>
<p>{% trans -%}
Alice should choose Bob arbitrarily from known peers who seem
to be capable of participating in peer tests. Bob in turn should
choose Charlie arbitrarily from peers that he knows who seem to be
capable of participating in peer tests and who are on a different
IP from both Bob and Alice. If the first error condition occurs
(Alice doesn't get PeerTest messages from Bob), Alice may decide
to designate a new peer as Bob and try again with a different nonce.
{%- endtrans %}</p>
<p>{% trans -%}
Alice's introduction key is included in all of the PeerTest
messages so that she doesn't need to already have an established
session with Bob and so that Charlie can contact her without knowing
any additional information. Alice may go on to establish a session
with either Bob or Charlie, but it is not required.
{%- endtrans %}</p>
<p>
IPv6 Notes:
Only testing of IPv4 addresses is supported.
Therefore, all Alice-Bob and Alice-Charlie communication must be via IPv4.
Bob-Charlie communication, however, may be via IPv4 or IPv6.
Alice's address, when specified in the PeerTest message, must be 4 bytes.
</p>
<h2><a name="acks">{% trans %}Transmission window, ACKs and Retransmissions{% endtrans %}</a></h2>
<p>{% trans ssuspec=site_url('docs/spec/ssu') -%}
The DATA message may contain ACKs of full messages and
partial ACKs of individual fragments of a message. See
the data message section of
<a href="{{ ssuspec }}">the protocol specification page</a>
for details.
{%- endtrans %}</p>
<p>{% trans streaming=site_url('docs/api/streaming') -%}
The details of windowing, ACK, and retransmission strategies are not specified
here. See the Java code for the current implementation.
During the establishment phase, and for peer testing, routers
should implement exponential backoff for retransmission.
For an established connection, routers should implement
an adjustable transmission window, RTT estimate and timeout, similar to TCP
or <a href="{{ streaming }}">streaming</a>.
See the code for initial, min and max parameters.
{%- endtrans %}</p>
<h2><a name="security">{% trans %}Security{% endtrans %}</a></h2>
<p>{% trans -%}
UDP source addresses may, of course, be spoofed.
Additionally, the IPs and ports contained inside specific
SSU messages (RelayRequest, RelayResponse, RelayIntro, PeerTest)
may not be legitimate.
Also, certain actions and responses may need to be rate-limited.
{%- endtrans %}</p>
<p>{% trans -%}
The details of validation are not specified
here. Implementers should add defenses where appropriate.
{%- endtrans %}</p>
<h2><a name="capabilities">{% trans %}Peer capabilities{% endtrans %}</a></h2>
<dl>
<dt>B</dt>
<dd>{% trans -%}
If the peer address contains the 'B' capability, that means
they are willing and able to participate in peer tests as
a 'Bob' or 'Charlie'.
{%- endtrans %}</dd>
<dt>C</dt>
<dd>{% trans -%}
If the peer address contains the 'C' capability, that means
they are willing and able to serve as an introducer - serving
as a Bob for an otherwise unreachable Alice.
{%- endtrans %}</dd>
</dl>
<h1><a name="future">{% trans %}Future Work{% endtrans %}</a></h1>
<ul>
<li>{% trans -%}
Analysis of current SSU performance, including assessment of window size adjustment
and other parameters, and adjustment of the protocol implementation to improve
performance, is a topic for future work.
{%- endtrans %}</li>
<li>{% trans -%}
The current implementation repeatedly sends acknowledgments for the same packets,
which unnecessarily increases overhead.
{%- endtrans %}</li>
<li>{% trans -%}
The default small MTU value of 620 should be analyzed and possibly increased.
The current MTU adjustment strategy should be evaluated.
Does a streaming lib 1730-byte packet fit in 3 small SSU packets? Probably not.
{%- endtrans %}</li>
<li>{% trans -%}
The protocol should be extended to exchange MTUs during the setup.
{%- endtrans %}</li>
<li>{% trans -%}
Rekeying is currently unimplemented and may never be.
{%- endtrans %}</li>
<li>{% trans -%}
The potential use of the 'challenge' fields in RelayIntro and RelayResponse,
and use of the padding field in SessionRequest and SessionCreated, is undocumented.
{%- endtrans %}</li>
<li>{% trans -%}
Instead of a single fragment per packet, a more efficient
strategy may be to bundle multiple message fragments into the same packet,
so long as it doesn't exceed the MTU.
{%- endtrans %}</li>
<li>{% trans -%}
A set of fixed packet sizes may be appropriate to further hide the data
fragmentation to external adversaries, but the tunnel, garlic, and end to
end padding should be sufficient for most needs until then.
{%- endtrans %}</li>
<li>{% trans -%}
Why are introduction keys the same as the router hash, should it be changed, would there be any benefit?
{%- endtrans %}</li>
<li>{% trans -%}
Capacities appear to be unused.
{%- endtrans %}</li>
<li>{% trans -%}
Signed-on times in SessionCreated and SessionConfirmed appear to be unused or unverified.
{%- endtrans %}</li>
</ul>
<h1>{% trans %}Implementation Diagram{% endtrans %}</h1>
<p>{% trans -%}
This diagram
should accurately reflect the current implementation, however there may be small differences.
{%- endtrans %}</p>
<p>
<img src="{{ url_for('static', filename='images/udp.png') }}">
<h1><a name="spec">{% trans %}Specification{% endtrans %}</a></h1>
<a href="{{ site_url('docs/spec/ssu') }}">{% trans %}Now on the SSU specification page{% endtrans %}</a>.
{% endblock %}

View File

@@ -0,0 +1,532 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Tunnel Implementation{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}October 2010{% endtrans %}{% endblock %}
{% block accuratefor %}0.8{% endblock %}
{% block content %}
{% trans %}This page documents the current tunnel implementation.{% endtrans %}
<h2 id="tunnel.overview">{% trans %}Tunnel overview{% endtrans %}</h2>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans -%}
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).
{%- endtrans %}</p>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans tunnelrouting=site_url('docs/how/tunnel-routing') -%}
An overview of I2P tunnel terminology is
<a href="{{ tunnelrouting }}">on the tunnel overview page</a>.
{%- endtrans %}</p>
<h2 id="tunnel.operation">{% trans %}Tunnel Operation (Message Processing){% endtrans %}</h2>
<h3>{% trans %}Overview{% endtrans %}</h3>
<p>{% trans i2np=site_url('docs/spec/i2np') -%}
After a tunnel is built, <a href="{{ i2np }}">I2NP messages</a> are processed and passed through it.
Tunnel operation has four distinct processes, taken on by various
peers in the tunnel.
{%- endtrans %}</p>
<ol>
<li>{% trans -%}
First, the tunnel gateway accumulates a number
of I2NP messages and preprocesses them into tunnel messages for
delivery.
{%- endtrans %}</li>
<li>{% trans -%}
Next, that gateway encrypts that preprocessed data, then
forwards it to the first hop.
{%- endtrans %}</li>
<li>{% trans -%}
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.
{%- endtrans %}</li>
<li>{% trans -%}
Eventually, the tunnel messages arrive at the endpoint where the I2NP messages
originally bundled by the gateway are reassembled and forwarded on as
requested.
{%- endtrans %}</li>
</ol>
<p>{% trans -%}
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.
{%- endtrans %}</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>{% trans %}Role{% endtrans %}</th>
<th>{% trans %}Preprocessing{% endtrans %}</th>
<th>{% trans %}Encryption Operation{% endtrans %}</th>
<th>{% trans %}Postprocessing{% endtrans %}</th>
</tr>
<tr>
<td>{% trans %}Outbound Gateway (Creator){% endtrans %}</td>
<td>{% trans %}Fragment, Batch, and Pad{% endtrans %}</td>
<td>{% trans %}Iteratively encrypt (using decryption operations){% endtrans %}</td>
<td>{% trans %}Forward to next hop{% endtrans %}</td>
</tr>
<tr>
<td>{% trans %}Participant{% endtrans %}</td>
<td>&nbsp;</td>
<td>{% trans %}Decrypt (using an encryption operation){% endtrans %}</td>
<td>{% trans %}Forward to next hop{% endtrans %}</td>
</tr>
<tr>
<td>{% trans %}Outbound Endpoint{% endtrans %}</td>
<td>&nbsp;</td>
<td>{% trans %}Decrypt (using an encryption operation) to reveal plaintext tunnel message{% endtrans %}</td>
<td>{% trans %}Reassemble Fragments, Forward as instructed to Inbound Gateway or Router{% endtrans %}</td>
</tr>
<tr><td colspan="4"><hr></td></tr>
<tr>
<td>{% trans %}Inbound Gateway{% endtrans %}</td>
<td>{% trans %}Fragment, Batch, and Pad{% endtrans %}</td>
<td>{% trans %}Encrypt{% endtrans %}</td>
<td>{% trans %}Forward to next hop{% endtrans %}</td>
</tr>
<tr>
<td>{% trans %}Participant{% endtrans %}</td>
<td>&nbsp;</td>
<td>{% trans %}Encrypt{% endtrans %}</td>
<td>{% trans %}Forward to next hop{% endtrans %}</td>
</tr>
<tr>
<td>{% trans %}Inbound Endpoint (Creator){% endtrans %}</td>
<td>&nbsp;</td>
<td>{% trans %}Iteratively decrypt to reveal plaintext tunnel message{% endtrans %}</td>
<td>{% trans %}Reassemble Fragments, Receive data{% endtrans %}</td>
</tr>
</table>
<h3 id="tunnel.gateway">{% trans %}Gateway Processing{% endtrans %}</h3>
<h4 id="tunnel.preprocessing">{% trans %}Message Preprocessing{% endtrans %}</h4>
<p>{% trans i2np=site_url('docs/spec/i2np'), tunnelmessage=site_url('docs/spec/tunnel-message') -%}
A tunnel gateway's function is to fragment and pack
<a href="{{ i2np }}">I2NP messages</a> into fixed-size
<a href="{{ tunnelmessage }}">tunnel messages</a>
and encrypt the tunnel messages.
Tunnel messages contain the following:
{%- endtrans %}</p>
<ul>
<li>{% trans %}A 4 byte Tunnel ID{% endtrans %}</li>
<li>{% trans %}A 16 byte IV (initialization vector){% endtrans %}</li>
<li>{% trans %}A checksum{% endtrans %}</li>
<li>{% trans %}Padding, if necessary{% endtrans %}</li>
<li>{% trans %}One or more { delivery instruction, I2NP message fragment } pairs{% endtrans %}</li>
</ul>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans tunnelmessage=site_url('docs/spec/tunnel-message') -%}
Details are in the
<a href="{{ tunnelmessage }}">tunnel message specification</a>.
{%- endtrans %}</p>
<h3>{% trans %}Gateway Encryption{% endtrans %}</h3>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<h3 id="tunnel.participant">{% trans %}Participant Processing{% endtrans %}</h3>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<h3 id="tunnel.endpoint">{% trans %}Endpoint Processing{% endtrans %}</h3>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<h2 id="tunnel.building">{% trans %}Tunnel Building{% endtrans %}</h2>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<h3 id="tunnel.peerselection">{% trans %}Peer Selection{% endtrans %}</h3>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<h4 id="tunnel.selection.exploratory">{% trans %}Exploratory tunnel peer selection{% endtrans %}</h4>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans peerselection=site_url('docs/how/peer-selection') -%}
Exploratory peer selection is discussed further on the
<a href="{{ peerselection }}">Peer Profiling and Selection page</a>.
{%- endtrans %}</p>
<h4 id="tunnel.selection.client">{% trans %}Client tunnel peer selection{% endtrans %}</h4>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans peerselection=site_url('docs/how/peer-selection') -%}
Client peer selection is discussed further on the
<a href="{{ peerselection }}">Peer Profiling and Selection page</a>.
{%- endtrans %}</p>
<h4 id="ordering">{% trans %}Peer Ordering within Tunnels{% endtrans %}</h4>
<p>{% trans pdf='http://forensics.umass.edu/pubs/wright-tissec.pdf',
pdf2008='http://forensics.umass.edu/pubs/wright.tissec.2008.pdf' -%}
Peers are ordered within tunnels to deal with the
<a href="{{ pdf }}">predecessor attack</a>
<a href="{{ pdf2008 }}">(2008 update)</a>.
{%- endtrans %}</p>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans -%}
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
{%- endtrans %}</p>
<pre>
p = peer hash
k = random key
d = XOR(H(p+k), k)
</pre>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<h3 id="tunnel.request">{% trans %}Request delivery{% endtrans %}</h3>
<p>{% trans pdf='http://www-users.cs.umn.edu/~hopper/hashing_it_out.pdf' -%}
A multi-hop tunnel is built using a single build message which is repeatedly
decrypted and forwarded. In the terminology of
<a href="{{ pdf }}">Hashing it out in Public</a>,
this is "non-interactive" telescopic tunnel building.
{%- endtrans %}</p>
<p>{% trans tunnelcreation=site_url('docs/spec/tunnel-creation') -%}
This tunnel request preparation, delivery, and response method is
<a href="{{ tunnelcreation }}">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.)
{%- endtrans %}</p>
<p>{% trans tunnelcreation=site_url('docs/spec/tunnel-creation') -%}
The details of tunnel request and response messages, and their encryption,
<a href="{{ tunnelcreation }}">are specified here</a>.
{%- endtrans %}</p>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans peerselection=site_url('docs/how/peer-selection') -%}
For more information on peer profiling, see the
<a href="{{ peerselection }}">Peer Profiling and Selection page</a>.
{%- endtrans %}</p>
<h3 id="tunnel.pooling">{% trans %}Tunnel Pools{% endtrans %}</h3>
<p>{% trans i2cp=site_url('docs/spec/i2cp') -%}
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="{{ i2cp }}">I2CP</a>, or the router's defaults if
not specified.
{%- endtrans %}</p>
<p>{% trans i2cp=site_url('docs/spec/i2cp') -%}
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 }}">I2CP page</a>.
{%- endtrans %}</p>
<h3 id="length">{% trans %}Tunnel Lengths and Defaults{% endtrans %}</h3>
<a href="{{ site_url('docs/how/tunnel-routing') }}#length">{% trans %}On the tunnel overview page{% endtrans %}</a>.
<h3 id="strategy">{% trans %}Anticipatory Build Strategy and Priority{% endtrans %}</h3>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<h2 id="tunnel.throttling">{% trans %}Tunnel Message Throttling{% endtrans %}</h2>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<h2 id="future">{% trans %}Future Work{% endtrans %}</h2>
<h3 id="tunnel.mixing">{% trans %}Mixing/batching{% endtrans %}</h3>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<h3>{% trans %}Padding{% endtrans %}</h3>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<h3>WRED</h3>
<p>{% trans -%}
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.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,536 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Old Tunnel Implementation{% endtrans %}{% endblock %}
{% block content %}
<b>{% trans tunnelimpl=site_url('docs/tunnels/implementation') -%}
Note: Obsolete - NOT used! Replaced in 0.6.1.10 - see <a href="{{ tunnelimpl }}">here</a> for the current implementation
{%- endtrans %}</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="https://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="{{ site_url('get-involved/roadmap') }}#v3.0">I2P 3.0</a></p>
{% endblock %}

View File

@@ -0,0 +1,145 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Unidirectional Tunnels{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}July 2011{% endtrans %}{% endblock %}
{% block accuratefor %}0.8.7{% endblock %}
{% block content %}
<h2>{% trans %}Overview{% endtrans %}</h2>
<p>{% trans -%}
This page describes the origins and design of I2P's unidirectional tunnels.
For further infomrmation see:
{%- endtrans %}</p>
<ul>
<li>
<a href="{{ site_url('docs/how/tunnel-routing') }}">{% trans %}Tunnel overview page{% endtrans %}</a>
<li>
<a href="{{ site_url('docs/tunnels/implementation') }}">{% trans %}Tunnel specification{% endtrans %}</a>
</li><li>
<a href="{{ site_url('docs/spec/tunnel-creation') }}">{% trans %}Tunnel creation specification{% endtrans %}</a>
</li><li>
<a href="{{ site_url('docs/discussions/tunnel') }}">{% trans %}Tunnel design discussion{% endtrans %}</a>
</li><li>
<a href="{{ site_url('docs/how/peer-selection') }}">{% trans %}Peer selection{% endtrans %}</a>
</li><li>
<a href="{{ get_url('meetings_show', id=125) }}">{% trans %}Meeting 125 (~13:12-13:30){% endtrans %}</a>
</li>
</ul>
</p>
<h2>{% trans %}Review{% endtrans %}</h2>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<h2>{% trans %}Anonymity{% endtrans %}</h2>
<p>{% trans pdf='http://grothoff.org/christian/i2p.pdf' -%}
A recent <a href="{{ pdf }}">paper by Hermann and Grothoff</a>
declared that I2P's unidirectional tunnels "seems to be a bad design decision".
{%- endtrans %}</p>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans -%}
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.
{%- endtrans %}</p>
<p>{% trans -%}
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?
{%- endtrans %}</p>
<p>{% trans -%}
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.
{%- endtrans %}</p>
{% endblock %}

853
i2p2www/pages/site/faq.html Normal file
View File

@@ -0,0 +1,853 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Frequently Asked Questions') }}{% endblock %}
{% block content %}
<h3 id="index">{{ _('Index') }}</h3>
<ol>
<li style="list-style: none; display: inline">
<h4>{{ _('General') }}</h4>
</li>
<li><a href="#systems">{% trans %}What systems will I2P run on?{% endtrans %}</a></li>
<li><a href="#eepsite">{% trans %}Whats an "eepsite" and how do I configure my browser so I can use them?{% endtrans %}</a></li>
<li><a href="#peers">{% trans %}My router has very few active peers, is this OK?{% endtrans %}</a></li>
<li><a href="#active">{% trans %}What do the Active x/y numbers mean in the router console?{% endtrans %}</a></li>
<li><a href="#vary">{% trans %}My active peers / known peers / participating tunnels / connections / bandwidth vary dramatically over time! Is anything wrong?{% endtrans %}</a></li>
<li><a href="#proxy_safe">{% trans %}Is using an outproxy safe?{% endtrans %}</a></li>
<li><a href="#down">{% trans %}Most of the eepsites within I2P are down?{% endtrans %}</a></li>
<li><a href="#ports">{% trans %}What ports does I2P use?{% endtrans %}</a></li>
<li><a href="#port32000">{% trans %}Why is I2P listening for connections on port 32000?{% endtrans %}</a></li>
<li><a href="#bug">{% trans %}I think I found a bug, where can I report it?{% endtrans %}</a></li>
<li><a href="#jrandom">{% trans %}What happened to *.i2p.net? What happened to jrandom? Is I2P dead?{% endtrans %}</a></li>
<li><a href="#question">{% trans %}I have a question!{% endtrans %}</a></li>
<li style="list-style: none; display: inline">
<h4>{{ _('Setup') }}</h4>
</li>
<li><a href="#reseed">{% trans %}My router has been up for several minutes and has zero or very few connections{% endtrans %}</a></li>
<li><a href="#slow">{% trans %}Why is I2P so slow?{% endtrans %}</a></li>
<li><a href="#subscriptions">{% trans %}I'm missing lots of hosts in my addressbook. What are some good subscription links?{% endtrans %}</a></li>
<li><a href="#myeepsite">{% trans %}How do I set up my own eepsite?{% endtrans %}</a></li>
<li><a href="#snark">{% trans %}Bittorrent / I2PSnark / Azureus I2P Plugin Questions?{% endtrans %}</a></li>
<li><a href="#irc">{% trans %}How do I connect to IRC within I2P?{% endtrans %}</a></li>
<li><a href="#outproxy">{% trans %}I can't access regular Internet sites through I2P.{% endtrans %}</a></li>
<li><a href="#https">{% trans %}I can't access https:// or ftp:// sites through I2P.{% endtrans %}</a></li>
<li><a href="#socks">{% trans %}Is it possible to use I2P as a SOCKS proxy?{% endtrans %}</a></li>
<li><a href="#browserproxy">{% trans %}How do I configure my browser?{% endtrans %}</a></li>
<li><a href="#remote_webconsole">{% trans %}How can I access the web console from my other machines or password protect it?{% endtrans %}</a></li>
<li><a href="#remote_i2cp">{% trans %}How can I use applications from my other machines?{% endtrans %}</a></li>
<li><a href="#manual_reseed">{% trans %}How do I reseed manually?{% endtrans %}</a></li>
<li><a href="#cpu">{% trans %}My router is using too much CPU?!?{% endtrans %}</a></li>
<li style="list-style: none; display: inline">
<h4>{{ _('Misconception') }}</h4>
</li>
<li><a href="#proxy_other">{% trans %}How do I access IRC, BitTorrent, or other services on the regular Internet?{% endtrans %}</a></li>
<li><a href="#exit">{% trans %}Is my router an "exit node"(outproxy) to the regular Internet? I don't want it to be.{% endtrans %}</a></li>
<li><a href="#content">{% trans %}I am opposed to certain types of content. How do I keep from distributing, storing, or accessing them?{% endtrans %}</a></li>
<li style="list-style: none; display: inline">
<h4>{{ _('Errors and Their Solutions') }}</h4>
</li>
<li><a href="#compat6x">{% trans %}I'm using FreeBSD and when I start I2P I receive an error about <code>libm.so.4</code>!{% endtrans %}</a></li>
<li><a href="#protocolfamily">{% trans %}In <code>wrapper.log</code> I see an error stating <code>Protocol family unavailable</code> when I2P is loading{% endtrans %}</a></li>
</ol>
<h3 id="systems">{% trans %}What systems will I2P run on?{% endtrans %}
<span class="permalink">(<a href="#systems">{{ _('link') }}</a>)</span></h3>
<p>{% trans trac=i2pconv('trac.i2p2.i2p') -%}
While I2P has been reported to run PCs as meagre as a low-end Pentium II with 64 MB of RAM, you'll have a much better experience on a Pentium III (or better) with 128MB of RAM (or more). A <a href="http://{{ trac }}/wiki/java">chart comparing the performance</a> of the various JREs can be found at <a href="http://{{ trac }}/wiki/java">http://{{ trac }}/wiki/java</a>, but in short: it's at all possible, use Sun/Oracle Java or OpenJDK.
{%- endtrans %}</p>
<p>{% trans -%}
I2P has been tested on Windows, Linux, FreeBSD (see the note <a href="#compat6x">below</a>), OSX, and OpenSolaris. There is work underway to bring I2P to the Android platform.
{%- endtrans %}</p>
<h3 id="bug">{% trans %}I think I found a bug, where can I report it?{% endtrans %}
<span class="permalink">(<a href="#bug">{{ _('link') }}</a>)</span></h3>
{% trans -%}
Here are some places, pick one or more.
{%- endtrans %}
<ul>
<li><a href="http://{{ i2pconv('trac.i2p2.i2p') }}/report/1">{{ i2pconv('trac.i2p2.i2p') }}</a> ticket (preferred method)</li>
<li><a href="http://{{ i2pconv('pastethis.i2p') }}/">{{ i2pconv('pastethis.i2p') }}</a> and follow up on IRC in #i2p</li>
<li>{% trans -%}
Discuss with the developers on IRC in #i2p-dev
{%- endtrans %}</li></ul>
<p>{% trans -%}
Please include relevant information from the router logs and wrapper logs.
{%- endtrans %}</p>
<h3 id="subscriptions">{% trans %}I'm missing lots of hosts in my addressbook. What are some good subscription links?{% endtrans %}
<span class="permalink">(<a href="#subscriptions">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
The default subscription is to http://www.i2p2.i2p/hosts.txt which is updated rarely.
If you don't have another subscription, you may often have to use "jump" links which
is annoying.
{%- endtrans %}</p>
<p>{% trans -%}
Here are some other public addressbook subscription links. You may wish to add one or two
to your <a href="http://localhost:7657/susidns/subscriptions.jsp">susidns subscription list</a>.
You don't need to add all of them, as they sync with each other periodically.
The links using a cgi-bin application employ various strategies to minimize
the number of duplicate addresses delivered, so they should be more efficient.
Note that subscribing to a hosts.txt service is an act of "trust", as a malicious
subscription could give you incorrect addresses. So think about whether you
want to trust any of these.
The operators of these services may have various policies for listing hosts.
Presence on this list does not imply endorsement.
{%- endtrans %}</p>
<div class="links">
<ul>
<li><a href="http://i2host.i2p/cgi-bin/i2hostetag">http://i2host.i2p/cgi-bin/i2hostetag</a></li>
<li><a href="http://stats.i2p/cgi-bin/newhosts.txt">http://stats.i2p/cgi-bin/newhosts.txt</a></li>
</div>
<h3 id="jrandom">{% trans %}What happened to *.i2p.net? What happened to jrandom? Is I2P dead?{% endtrans %}
<span class="permalink">(<a href="#jrandom">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
Jrandom was the lead developer of I2P and
<a href="http://syndie.i2p2.de/">Syndie</a> for several years.
We do not know if or when jrandom will return.
The *.i2p.net domains were left in a non-functioning state after a power
outage at the hosting company.
{%- endtrans %}</p>
<p>{% trans jrandom=site_url('misc/jrandom-awol'), index=site_url() -%}
See <a href="{{ jrandom }}">this page</a> for jrandom's parting message and additional information
on the migration of *.i2p.net to <a href="{{ index }}">this website</a>.
{%- endtrans %}</p>
<p>{% trans %}I2P remains in active development.{% endtrans %}</p>
<h3 id="cpu">{% trans %}My router is using too much CPU?!?{% endtrans %}
<span class="permalink">(<a href="#cpu">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
There are many possible causes of high CPU usage. Here is a checklist:
{%- endtrans %}</p>
<ul>
<li>
{% trans -%}
Try to use either OpenJDK or Sun/Oracle Java if it's available for your system. You can check
which version of java you have installed by typing <code>java -version</code> at a
command/shell prompt. Performance tends to suffer with other implementations of java.
{%- endtrans %}
</li>
<li>
{% trans -%}
Are you running a BitTorrent client over I2P? Try reducing the number of torrents, the bandwidth limits,
or try turning it off completely to see if that helps.
{%- endtrans %}
</li>
<li>
{% trans -%}
Are your bandwidth limits set too high? It is possible that too much traffic is going through your
I2P router and it is overloaded. Try reducing the setting for <em>share bandwidth percentage</em> on the <a href="http://localhost:7657/config">configuration</a> page.
{%- endtrans %}</li>
<li>
{% trans -%}
Make sure that you're running the latest version of I2P to get the benefits of increased performance and bug fixes.
{%- endtrans %}
</li>
<li>
{% trans -%}
Has enough memory been set aside for use by I2P? Look at the memory graph on <a href="http://localhost:7657/graphs">the graphs page</a> to see
if the memory usage is "pegged"&mdash;the JVM is spending most of its time in
garbage collection. Increase the setting <code>wrapper.java.maxmemory</code> in <code>wrapper.config</code>.
{%- endtrans %}
</li>
<li>
{% trans -%}
Is the CPU usage simply higher than you would like, or is it pegged at 100&#37; for a long time?
If it's pegged, this could be a bug. Look in the logs for clues.
{%- endtrans %}
</li>
<li>
{% trans jbigi=site_url('misc/jbigi') -%}
You may be using the Java-based BigInteger library instead of the native version,
especially if you are running on a new or unusual OS or hardware (OpenSolaris, mipsel, etc.).
See the <a href="{{ jbigi }}">jbigi page</a> for instructions on
diagnosing, building, and testing methods.
{%- endtrans %}
</li>
<li>
{% trans -%}
If your native jbigi library is working fine, the biggest user of
CPU may be routing traffic for participating tunnels. This uses CPU
because at each hop a layer of encryption must be decoded.
You can limit participating traffic in two ways - by reducing the
share bandwidth on
<a href="http://localhost:7657/confignet.jsp">confignet.jsp</a>,
or by setting <tt>router.maxParticipatingTunnels=nnn</tt> on
<a href="http://localhost:7657/configadvanced.jsp">configadvanced.jsp</a>.
{%- endtrans %}
</li>
</ul>
<h3 id="content">{% trans %}I am opposed to certain types of content. How do I keep from distributing, storing, or accessing them?{% endtrans %}
<span class="permalink">(<a href="#content">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
Hmm. I2P is an anonymous network, so that's a tricky one.
I2P is designed to withstand censorship, providing a means for everyone to communicate freely.
The best way to keep your PC free of (encrypted) traffic that you dislike is to not use I2P.
Freedom of speech has some costs.
But let's address your question in three parts:
{%- endtrans %}</p>
<ul>
<li>
{% trans -%}
<b>Distribution</b> - All traffic on I2P is encrypted in multiple layers. You don't know
a message's contents, source, or destination.
All traffic you route is internal to the I2P network, you are not an <a href="#exit">exit node</a> (outproxy).
Your only alternative is to refuse to route
<i>any</i> traffic, by setting your share bandwidth or maximum participating tunnels to 0 (see above).
It would be nice if you didn't do this, you should help the network by routing traffic for others.
Over 95&#37; of users route traffic for others.
{%- endtrans %}
</li>
<li>
{% trans -%}
<b>Storage</b> - I2P does not do distributed storage of content. You must be thinking of
<a href="http://freenetproject.org/">Freenet</a>.
Nobody's content is being stored on your computer by running I2P.
{%- endtrans %}
</li>
<li>
{% trans -%}
<b>Access</b> - If there are some eepsites you don't like, don't go there.
Or, use a blocking proxy like Privoxy or some type of "net nanny".
{%- endtrans %}
</li>
</ul>
<h3 id="vary">{% trans %}My active peers / known peers / participating tunnels / connections / bandwidth vary dramatically over time! Is anything wrong?{% endtrans %}
<span class="permalink">(<a href="#vary">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
No. This is normal.
All routers adjust dynamically to changing network conditions and demands.
{%- endtrans %}</p>
<h3 id="reseed">{% trans %}My router has been up for several minutes and has zero or very few connections{% endtrans %}
<span class="permalink">(<a href="#reseed">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
You may need to reseed your I2P router. With recent versions of I2P you can go to <a href="http://localhost:7657/configreseed">http://localhost:7657/configreseed</a> and click the <em>Save Changes and Reseed Now</em> button. If this method doesn't work&mdash;or you're using a very old version&mdash;you may need to <a href="#manual_reseed">reseed manually</a>.
{%- endtrans %}</p>
<p>{% trans -%}
The reseed URL changed a few years ago. If this is your first install and you have installed
an old (0.6.1.30 or earlier) release, or
you have not run I2P in a long time, you must change the URL and then
click "Reseed" on the console to find other routers.
After your router is running,
on <a href="http://localhost:7657/configadvanced.jsp">configadvanced.jsp</a>,
add the line <tt>i2p.reseedURL=http://netdb.i2p2.de/</tt>
OR <tt>i2p.reseedURL=http://i2pdb.tin0.de/netDb/</tt> (either should work),
then click "Apply", then click the "reseed" link on the left.
{%- endtrans %}</p>
<p>{% trans downloadslist=get_url('downloads_list') -%}
This works if you are running 0.6.1.27 or later.
If you are running release 0.6.1.31 or later, you probably don't need to do this.
If you are running release 0.6.1.26 or earlier, either follow the
<a href="#manual_reseed">manual reseed instructions</a> below
or install the <a href="{{ downloadslist }}">latest release</a>.
Possible alternate method - add
<tt>wrapper.java.additional.5=-Di2p.reseedURL=http://netdb.i2p2.de/</tt>
to wrapper.config, shutdown the router completely, then start again, then click "reseed".
Let us know if this works.
{%- endtrans %}</p>
<p>{% trans downloadslist=get_url('downloads_list') -%}
...but you *really* should <a href="{{ downloadslist }}">upgrade</a> to the latest version.
{%- endtrans %}</p>
<h3 id="peers">{% trans %}My router has very few active peers, is this OK?{% endtrans %}
<span class="permalink">(<a href="#peers">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
If your router has 10 or more active peers, everything is fine. Changes in releases 0.6.1.31 and 0.6.1.32 improved the
efficiency of the router and effectively reduced the number of active peers.
The router <i>should</i> maintain connections to a few peers at all times.
The best way to stay "better-connected" to the network is to <a href="http://localhost:7657/config">share more bandwidth</a>.
{%- endtrans %}</p>
<h3 id="exit">{% trans %}Is my router an "exit node" to the regular Internet? I don't want it to be.{% endtrans %}
<span class="permalink">(<a href="#exit">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
No. Unlike <a href="https://www.torproject.org/">Tor</a>,
"exit nodes" or "outproxies" are not an inherent part of the network.
Only volunteers who set up and run separate applications will relay traffic to the regular Internet.
There are very, very few of these.
{%- endtrans %}</p>
<h3 id="outproxy">{% trans %}I can't access regular Internet sites through I2P.{% endtrans %}
<span class="permalink">(<a href="#outproxy">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
See above. There are very few HTTP "outproxies", they are not an inherent part of the network,
and they may not be up.
In addition, the old outproxies squid.i2p, true.i2p, and krabs.i2p have vanished.
The only outproxy at the moment is false.i2p.
To use it, edit your <a href="http://localhost:7657/i2ptunnel/edit.jsp?tunnel=0">i2ptunnel settings for eepProxy</a>
and set your outproxy list to 'false.i2p' (only).
Then stop and restart the eepProxy.
If it doesn't work, the outproxy is not up. It is not I2P's fault.
If your primary reason to use an anonymous network is to anonymously access sites
on the regular Internet, you should probably try <a href="https://www.torproject.org/">Tor</a>.
{%- endtrans %}</p>
<h3 id="https">{% trans %}I can't access https:// or ftp:// sites through I2P.{% endtrans %}
<span class="permalink">(<a href="#https">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
Within I2P, there is no need for HTTPS, as all traffic is encrypted end-to-end.
FTP is not supported for technical reasons.
{%- endtrans %}</p>
<p>{% trans -%}
There are no FTP "outproxies" to the Internet&mdash;it may not even be possible to set up one.
Any other kind of outproxy may work if it's set up with a standard tunnel.
If you would like to set up some type of outproxy, carefully research the potential risks.
The I2P community may or may not be able to help with the technical aspects, feel free to ask.
{%- endtrans %}</p>
<p>{% trans -%}
As explained several times above, any existing outproxy isn't a core part of the network.
They are services run by individuals and they may or may not
be operational at any given time.
{%- endtrans %}</p>
<p>{% trans -%}
<b>Update</b>: Thanks to the work of h2ik, there is an https outproxy available for use via I2P. Starting with I2P 0.8.4 <a href="http://localhost:7657/i2ptunnel/edit?tunnel=6">the tunnel</a> is configured out of the box.<br />
In case the https outproxy is not available in your version of I2P, you can add it easily by doing the following:
{%- endtrans %}</p>
<ol>
<li>
{% trans -%}
Open <a href="http://localhost:7657/i2ptunnel/index.jsp">i2p tunnel manager</a>. Scroll down to the bottom.
{%- endtrans %}
</li>
<li>
{% trans -%}
Choose <b>CONNECT</b> from <b>New Client Tunnel</b> dropdown list, click <b>Create</b>
{%- endtrans %}
</li>
<li>
{% trans forum=i2pconv('forum.i2p') -%}
In the new page, <b>name</b> and <b>describe</b> your new https tunnel as you like.
The <b>Access Point</b> is your local port for the new https proxy recommended port's <b>4445</b>.
<b>Outproxy</b> should be the outproxy's .i2p address which supports https.
See this forum post of <a href="http://{{ forum }}/viewtopic.php?p=31356#31356">h2ik</a>'s for the address.
Make sure <b>Shared Client</b>, <b>Delay Connect</b>, <b>AutoStart</b> are checked.
Other options should be left at the defaults. Click Save. In tunnel manger, click the <b>Start</b> button next to your new tunnel.
{%- endtrans %}
</li>
<li>
{% trans -%}
In firefox, click through <b>Tools</b>><b>Options</b>><b>Advanced</b>><b>Network</b>><b>Setting</b>.
Untick <b>Use this proxy for all protocol</b>, set <b>SSL proxy:</b> to localhost:4445.
{%- endtrans %}
</li>
<li>{{ _('Done.') }}</li>
</ol>
<h3 id="proxy_safe">{% trans %}Is using an outproxy safe?{% endtrans %}
<span class="permalink">(<a href="#proxy_safe">{{ _('link') }}</a>)</span></h3>
<p>{% trans threatmodel=site_url('docs/how/threat-model') %}
This is a question that only you can answer because the correct answer depends on your behaviours, your
<a href="{{ threatmodel }}">threat model</a>, and how much you trust the outproxy operator.
{%- endtrans %}</p>
<p>{% trans -%}
Like Tor, I2P does not magically encrypt the Internet.
You are vulnerable to snooping by the outproxy operators.
The <a href="https://wiki.torproject.org/noreply/TheOnionRouter/TorFAQ#ExitEavesdroppers">Tor FAQ</a>
does a good job of explaining this.
{%- endtrans %}</p>
<p>{% trans zzz=i2pconv('zzz.i2p') -%}
In addition, you may be vulnerable to collusion between the outproxy operator
and operators of other I2P services, if you use the same tunnels ("shared clients").
There is additional discussion about this on <a href="http://{{ zzz }}/topics/217">{{ zzz }}</a>.
{%- endtrans %}</p>
<h3 id="proxy_other">{% trans %}How do I access IRC, BitTorrent, or other services on the regular Internet?{% endtrans %}
<span class="permalink">(<a href="#proxy_other">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
Unless an outproxy has been set up for the service you want to connect to, this cannot be done.
There are only three types of outproxies running right now: HTTP, HTTPS, and email. Note that there is not a SOCKS outproxy.
If this type of service is required, try <a href="https://www.torproject.org/">Tor</a>.
{%- endtrans %}</p>
<h3 id="down">{% trans %}Most of the eepsites within I2P are down?{% endtrans %}
<span class="permalink">(<a href="#down">{{ _('link') }}</a>)</span></h3>
<p>{% trans eepstatus='http://'+i2pconv('identiguy.i2p') -%}
If you consider every eepsite that has ever been created, yes, most of them are down.
People and eepsites come and go.
A good way to get started in I2P is check out a list of eepsites that are currently up.
<a href="{{ eepstatus }}">{{ eepstatus }}</a> tracks active eepsites.
{%- endtrans %}</p>
<h3 id="myeepsite">{% trans %}How do I set up my own eepsite?{% endtrans %}
<span class="permalink">(<a href="#myeepsite">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
Click on the <a href="http://localhost:7658/">Website</a> link
at the top of your router console for instructions.
{%- endtrans %}</p>
<h3 id="slow">{% trans %}Why is I2P so slow?{% endtrans %}
<span class="permalink">(<a href="#slow">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
Why are downloads, torrents, web browsing, and everything else so slow on I2P?
The encryption and routing within the I2P network adds a substantial amount of overhead and limits bandwidth.
Anonymity isn't free.
{%- endtrans %}</p>
<p>{% trans -%}
In addition, you and everybody else probably need to increase your bandwidth limits.
Two key settings are the inbound and outbound bandwidth limiters on
<a href="http://localhost:7657/config.jsp">the configuration page</a>.
With the default settings of 32KBps you will generally get no better than 15KBps data transfer in I2PSnark.
Increasing the settings (but keeping within your actual connection limitations)
will increase the potential transfer rate for I2PSnark and all other applications.
{%- endtrans %}</p>
<p>{% trans -%}
Also, do you have sufficient share bandwidth configured to allow participating tunnels
to route through your router? Believe it or not, allowing participating traffic
keeps you well-integrated in the network and helps your own transfer speeds.
{%- endtrans %}</p>
<p>{% trans downloadslist=get_url('downloads_list') -%}
I2P is a work in progress. Lots of improvements and fixes are being implemented, and
generally speaking, running the latest release will help your performance.
If you haven't, <a href="{{ downloadslist }}">install the latest release</a>.
{%- endtrans %}</p>
<h3 id="snark">{% trans %}Bittorrent / I2PSnark / Azureus I2P Plugin Questions?{% endtrans %}
<span class="permalink">(<a href="#snark">{{ _('link') }}</a>)</span></h3>
<p>{% trans forum=i2pconv('forum.i2p') -%}
See the
<a href="http://{{ forum }}/viewtopic.php?t=2068">I2P Bittorrent FAQ</a>
{%- endtrans %}</p>
<h3 id="irc">{% trans %}How do I connect to IRC within I2P?{% endtrans %}
<span class="permalink">(<a href="#irc">{{ _('link') }}</a>)</span></h3>
<p>{% trans %}
A tunnel to the main IRC server within I2P, Irc2P, is created when I2P is installed (see
the <a href="http://localhost:7657/i2ptunnel/index.jsp">I2PTunnel configuration page</a>),
and is automatically started when the I2P router starts. To connect to it, tell your IRC
client to connect to <code>localhost 6668</code>. XChat-like client users can create a
new network with the server <code>localhost/6668</code> (remember to tick &quot;Bypass
proxy server&quot; if you have a proxy server configured).
{%- endtrans %}</p>
<h3 id="remote_webconsole">{% trans %}How can I access the web console from my other machines or password protect it?{% endtrans %}
<span class="permalink">(<a href="#remote_webconsole">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
For security purposes, the router's admin console by default only listens
for connections on the local interface. However, with a little hacking,
you can make it reachable remotely:
{%- endtrans %}</p>
<ol>
<li>
{% trans -%}
Open <code>~/.i2p/clients.config</code> and replace<br />
<code>clientApp.0.args=7657 ::1,127.0.0.1 ./webapps/</code><br />
with <br />
<code>clientApp.0.args=7657 0.0.0.0 ./webapps/</code>
{%- endtrans %}
</li>
<li>
{% trans -%}
Go to <a href="http://localhost:7657/configui">http://localhost:7657/configui</a>
and add a console username and password if desired.
{%- endtrans %}
</li>
<li>
{% trans -%}
Go to <a href="http://localhost:7657/index.jsp">http://localhost:7657/index.jsp</a>
and hit "Graceful restart", which restarts the JVM and reloads the client applications
{%- endtrans %}
</li>
</ol>
<p>{% trans -%}
After that fires up, you should now be able to reach your console remotely. Reload the router at
http://127.0.0.1:7657 and you will be prompted for the username and password you specified in step 2
above if your browser supports the authentication popup. Note: the
<code>0.0.0.0</code> above specifies an <i>interface</i>, not a network or netmask. 0.0.0.0
means "bind to all interfaces", so it can be reachable on 127.0.0.1:7657 as well as
any LAN/WAN IP.
{%- endtrans %}</p>
<h3 id="remote_i2cp">{% trans %}How can I use applications from my other machines?{% endtrans %}
<span class="permalink">(<a href="#remote_i2cp">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
By default, the router I2CP interface (port 7654) binds to address 127.0.0.1. To bind to 0.0.0.0, set the
router advanced configuration option <tt>i2cp.tcp.bindAllInterfaces=true</tt> and restart.
{%- endtrans %}</p>
<h3 id="eepsite">{% trans %}Whats an "eepsite"?{% endtrans %}
<span class="permalink">(<a href="#eepsite">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
An eepsite is a website that is hosted anonymously - you can access it by
setting your web browser's HTTP proxy to use the web proxy (typically it
listens on localhost port 4444), and browsing to the site.
{%- endtrans %}</p>
<h3 id="browserproxy">{% trans %}How do I configure my browser?{% endtrans %}
<span class="permalink">(<a href="#browserproxy">{{ _('link') }}</a>)</span></h3>
<p>{% trans browserconfig=site_url('about/browser-config') -%}
The proxy config for different browsers is on a <a href="{{ browserconfig }}">
separate page</a> with screenshots. More advanced configs with external tools
are possible but could introduce leaks in your setup.
{%- endtrans %}</p>
<h3 id="active">{% trans %}What do the Active x/y numbers mean in the router console?{% endtrans %}
<span class="permalink">(<a href="#active">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
x is the number of peers you've sent or received a message from
successfully in the last minute, y is the number of peers seen in the last
hour or so.
{%- endtrans %}</p>
<h3 id="socks">{% trans %}Is it possible to use I2P as a SOCKS proxy?{% endtrans %}
<span class="permalink">(<a href="#socks">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
The SOCKS proxy is working as of release 0.7.1. SOCKS 4/4a/5 are supported.
There is no SOCKS outproxy so it is of limited use.
{%- endtrans %}</p>
<p>{% trans -%}
In addition, many applications leak sensitive
information that could identify you on the Internet. I2P only filters
connection data, but if the program you intend to run sends this
information as content, I2P has no way to protect your anonymity. For
example, some mail applications will send the IP address of the machine
they are running on to a mail server. There is no way for I2P to filter
this, thus using I2P to 'socksify' existing applications is possible, but
extremely dangerous.
{%- endtrans %}</p>
<p>{% trans socks=site_url('docs/api/socks') -%}
If you would like more information on the socks proxy application anyway,
there are some helpful hints on the <a href="{{ socks }}">socks page</a>.
{%- endtrans %}</p>
<h3 id="ports">{% trans %}What ports does I2P use?{% endtrans %}
<span class="permalink">(<a href="#ports">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
Okay, here's a rundown of the default ports (everything is configurable
through various settings, of course):
{%- endtrans %}</p>
<ul>
<li>
{% trans -%}
<b>Internet-facing ports</b>
Note: New installs as of release 0.7.8 do not use port 8887; they select a random port
between 9000 and 31000 when the program is run for the first time.
The selected port is shown on the router <a href="http://127.0.0.1:7657/confignet.jsp">configuration page.</a>
{%- endtrans %}
<ul>
<li>
{% trans -%}
<b>Outbound UDP from the random port noted on the <a href="http://127.0.0.1:7657/confignet.jsp">configuration page</a> to arbitrary remote UDP ports, allowing replies</b>
{% endtrans %}
</li>
<li>
{% trans -%}
<b>Outbound TCP from random high ports to arbitrary remote TCP ports</b>
{% endtrans %}
</li>
<li>
{% trans -%}
<b>(optional, but recommended) Inbound UDP to the port noted on <a href="http://127.0.0.1:7657/confignet.jsp">configuration page</a> from arbitrary locations</b>
{% endtrans %}
</li>
<li>
{% trans -%}
<b>(optional, but recommended) Inbound TCP to the port noted on <a href="http://127.0.0.1:7657/confignet.jsp">configuration page</a> from arbitrary locations</b><br />
Inbound TCP may be disabled on the <a href="http://127.0.0.1:7657/confignet.jsp">configuration page.</a>
{%- endtrans %}
</li>
<li>
{% trans -%}
<b>Outbound UDP on port 123, allowing replies</b><br />
This is necessary for I2P's internal time sync (via SNTP -
querying a random SNTP host in pool.ntp.org or another
server you specify)
{%- endtrans %}
</li>
</ul>
</li>
<li>
{% trans -%}
<b>Local I2P ports</b>, listening only to local connections by default,
except where noted:
{%- endtrans %}
<ul>
<li>
{% trans -%}
<b>1900:</b> UPnP SSDP UDP multicast listener.
<i>Cannot be changed. Binds to all interfaces.
May be disabled on <a href="http://localhost:7657/confignet.jsp">confignet.jsp</a>.</i>
{%- endtrans %}
</li>
<li>
{% trans -%}
<b>2827:</b> BOB bridge, a higher level socket API for clients
<i>Disabled by default.
May be enabled/disabled on <a href="http://localhost:7657/configclients.jsp">configclients.jsp</a>.
May be changed in the bob.config file.</i>
{%- endtrans %}
</li>
<li>
{% trans -%}
<b>4444:</b> HTTP proxy
<i>May be disabled or changed on the i2ptunnel page in the router console.
May also be configured to be bound to a specific interface or all interfaces.</i>
{%- endtrans %}
</li>
<li>
{% trans -%}
<b>4445:</b> HTTPS proxy
<i>May be disabled or changed on the i2ptunnel page in the router console.
May also be configured to be bound to a specific interface or all interfaces.</i>
{%- endtrans %}
</li>
<li>
{% trans -%}
<b>6668:</b> IRC proxy
<i>May be disabled or changed on the i2ptunnel page in the router console.
May also be configured to be bound to a specific interface or all interfaces.</i>
{%- endtrans %}
</li>
<li>
{% trans -%}
<b>7652:</b> UPnP HTTP TCP event listener.
<i>Binds to the LAN address.
May be changed with advanced config i2np.upnp.HTTPPort=nnnn.
May be disabled on <a href="http://localhost:7657/confignet.jsp">confignet.jsp</a>.</i>
{%- endtrans %}
</li>
<li>
{% trans -%}
<b>7653:</b> UPnP SSDP UDP search response listener.
<i>Binds to all interfaces.
May be changed with advanced config i2np.upnp.SSDPPort=nnnn.
May be disabled on <a href="http://localhost:7657/confignet.jsp">confignet.jsp</a>.</i>
{%- endtrans %}
</li>
<li>
{% trans -%}
<b>7654:</b> I2P Client Protocol port, used by client apps.
<i>May be changed to a different port on
<a href="http://localhost:7657/configclients.jsp">configclients.jsp</a>
but this is not recommended.
May be to bind to a different interface or all interfaces, or disabled, on
<a href="http://localhost:7657/configclients.jsp">configclients.jsp</a>.</i>
{%- endtrans %}
</li>
<li>
{% trans -%}
<b>7655:</b> UDP for SAM bridge, a higher level socket API for clients
<i>Only opened when a SAM V3 client requests a UDP session.
May be enabled/disabled on <a href="http://localhost:7657/configclients.jsp">configclients.jsp</a>.
May be changed in the clients.config file with the SAM command line option sam.udp.port=nnnn.</i>
{%- endtrans %}
</li>
<li>
{% trans -%}
<b>7656:</b> SAM bridge, a higher level socket API for clients
<i>Disabled by default for new installs as of release 0.6.5.
May be enabled/disabled on <a href="http://localhost:7657/configclients.jsp">configclients.jsp</a>.
May be changed in the clients.config file.</i>
{%- endtrans %}
</li>
<li>
{% trans -%}
<b>7657:</b> Your router console
<i>May be disabled in the clients.config file.
May also be configured to be bound to a specific interface or all interfaces in that file.</i>
{%- endtrans %}
</li>
<li>
{% trans -%}
<b>7658:</b> Your eepsite
<i>May be disabled in the clients.config file.
May also be configured to be bound to a specific interface or all interfaces in the jetty.xml file.</i>
{%- endtrans %}
</li>
<li>
{% trans -%}
<b>7659:</b> Outgoing mail to smtp.postman.i2p
<i>May be disabled or changed on the i2ptunnel page in the router console.
May also be configured to be bound to a specific interface or all interfaces.</i>
{%- endtrans %}
</li>
<li>
{% trans -%}
<b>7660:</b> Incoming mail from pop.postman.i2p
<i>May be disabled or changed on the i2ptunnel page in the router console.
May also be configured to be bound to a specific interface or all interfaces.</i>
{%- endtrans %}
</li>
<li>
{% trans -%}
<b>8998:</b> mtn.i2p2.i2p (Monotone - disabled by default)
<i>May be disabled or changed on the i2ptunnel page in the router console.
May also be configured to be bound to a specific interface or all interfaces.</i>
{%- endtrans %}
</li>
<li>
{% trans -%}
<b>31000:</b> Local connection to the wrapper control channel port.
<i>Outbound to 32000 only, does not listen on this port.
Starts at 31000 and will increment until 31999 looking for a free port.
To change, see the
<a href="http://wrapper.tanukisoftware.com/doc/english/prop-port.html">wrapper documentation</a>.
For more information see <a href="#port32000">below</a>.</i>
{%- endtrans %}
</li>
<li>
{% trans -%}
<b>32000:</b> Local control channel for the service wrapper.
<i>To change, see the
<a href="http://wrapper.tanukisoftware.com/doc/english/prop-port.html">wrapper documentation</a>.
For more information see <a href="#port32000">below</a>.</i>
{%- endtrans %}
</li>
</ul>
</li>
</ul>
<p>{% trans -%}
The local I2P ports and the I2PTunnel ports do not need to be reachable from
remote machines, but *should* be reachable locally. You can also create
additional ports for I2PTunnel instances via http://localhost:7657/i2ptunnel/
(and in turn, would need to get your firewall to allow you local access, but
not remote access, unless desired).
{%- endtrans %}</p>
<p>{% trans -%}
So, to summarize, nothing needs to be reachable by unsolicited remote peers, but
if you can configure your NAT/firewall to allow inbound UDP and TCP the <a href="http://localhost:7657/config">outbound facing port</a>, you'll
get better performance. You will also need to be able to send outbound UDP packets
to arbitrary remote peers (blocking IPs randomly with something like PeerGuardian
only hurts you - don't do it).
{%- endtrans %}</p>
<h3 id="port32000">{% trans %}Why is I2P listening on port 32000?{% endtrans %}
<span class="permalink">(<a href="#port32000">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
The Tanuki java service wrapper that we use opens this port&mdash;bound to localhost&mdash;in order
to communicate with software running inside the JVM. When the JVM is launched it is given a key
so it can connect to the wrapper. After the JVM establishes its connection
to the wrapper, the wrapper refuses any additional connections.
{%- endtrans %}</p>
<p>{% trans -%}
More information can be found in the
<a href="http://wrapper.tanukisoftware.com/doc/english/prop-port.html">wrapper documentation</a>.
{%- endtrans %}</p>
<h3 id="manual_reseed">{% trans %}How do I reseed manually?{% endtrans %}
<span class="permalink">(<a href="#manual_reseed">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
An I2P router only needs to be seeded once, to join the network for the first time.
Reseeding is nothing more than sending plain HTTP GET requests
to fetch a directory listing and download multiple "routerInfo" files
from a predefined reseed URL.
{%- endtrans %}</p>
<p>{% trans -%}
A typical symptom of a failed reseed is the "Known" indicator
(on the left sidebar of the router console) displaying a very small value
(often less than 5) which does not increase. This can occur, among other things,
if your firewall limits outbound traffic, and blocked the reseed request.
{%- endtrans %}</p>
{% trans %}To reseed an I2P router manually, do the following:{% endtrans %}
<ul>
<li>
{% trans %}Stop your I2P router{% endtrans %}
</li>
<li>
{% trans %}Open <a href="http://netdb.i2p2.de/">http://netdb.i2p2.de/</a> using a web browser{% endtrans %}
<!-- DOWN <a href="http://i2pdb.tin0.de/netDb/">http://i2pdb.tin0.de/netDb/</a> or -->
</li>
<li>{% trans %}Save a dozen "routerInfo" files to your I2P "netDb" directory{% endtrans %}
<!-- DOWN
</li><li>Alternate method (easier): Download <a href="http://i2pdb.tin0.de/latest.zip">http://i2pdb.tin0.de/latest.zip</a>
and unzip it into your I2P "netDb" directory.
-->
</li>
<li>
{% trans %}Start your I2P router{% endtrans %}
</li>
</ul>
<h3 id="compat6x">{% trans %}I'm using FreeBSD and when I start I2P I receive an error about <code>libm.so.4</code>!{% endtrans %}
<span class="permalink">(<a href="#compat6x">{{ _('link') }}</a>)</span></h3>
{% trans %}When trying to start the router using "i2prouter start", you may see output like the following:{% endtrans %}<br />
<code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$ ./i2prouter start<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Starting I2P Service...<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/libexec/ld-elf.so.1: Shared object "libm.so.4" not found, required by "i2psvc"
</code>
<p>{% trans %}
In order to be inclusive and try to ensure that I2P will run on as many systems
as possible, up until I2P 0.8.9 we used a <a href="http://wrapper.tanukisoftware.com/">java wrapper</a>
compiled for FreeBSD 6.x. If you're receiving this error you most likely are missing the necessary compatibility libraries.
These libraries may be installed by performing the following steps:
{%- endtrans %}</p>
<ul>
<li>
{% trans %}Switch to the root user with <code>su</code> or log in as <code>root</code>.{% endtrans %}
</li>
<li><code>cd /usr/ports/misc/compat6x</code></li>
<li><code>make install</code></li>
</ul>
<p>{% trans manualwrapper=site_url('misc/manual-wrapper') -%}
If you cannot install these compatibility libraries (or do not want to), other
possibilities would be to compile the wrapper for <a href="{{ manualwrapper }}">your
system</a>, starting I2P with the <code>runplain.sh</code> script, or you can
replace the wrapper with one from the source tarball.
{%- endtrans %}</p>
<p>{% trans -%}
For the 0.8.9 release of I2P, the wrapper was upgraded to v3.5.12 and compiled on systems running FreeBSD 7.2.
{%- endtrans %}</p>
<h3 id="protocolfamily">{% trans %}In <code>wrapper.log</code> I see an error that states "<code>Protocol family unavailable</code>" when loading the Router Console{% endtrans %}
<span class="permalink">(<a href="#protocolfamily">{{ _('link') }}</a>)</span></h3>
<p>{% trans -%}
Often this error will occur with any network enabled java software on some systems that are configured to use IPv6 by default. There are a few ways to solve this:
{%- endtrans %}</p>
<ul>
<li>
{% trans %}On Linux based systems, you can <code>echo 0 > /proc/sys/net/ipv6/bindv6only</code>{% endtrans %}
</li>
<li>{% trans %}Look for the following lines in <code>wrapper.config</code>.{% endtrans %}<br />
<code>#wrapper.java.additional.5=-Djava.net.preferIPv4Stack=true<br />
#wrapper.java.additional.6=-Djava.net.preferIPv6Addresses=false<br />
</code><br />
{% trans %}If the lines are there, uncomment them by removing the "#"s. If the lines are not there, add them without the "#"s.{% endtrans %}
</li>
</ul>
{% trans -%}
Another option would be to remove the <strong>::1</strong> from <code>~/.i2p/clients.config</code>
{%- endtrans %}
<p>{% trans -%}
<strong>WARNING</strong>: For any changes to <code>wrapper.config</code> to take effect, you must completely
stop the router and the wrapper. Clicking <em>Restart</em> on your
router console will NOT reread this file! You must
click <em>Shutdown</em>, wait 11 minutes, then start I2P.
{%- endtrans %}</p>
<hr />
<h3 id="question">{% trans %}I have a question!{% endtrans %}
<span class="permalink">(<a href="#question">{{ _('link') }}</a>)</span></h3>
<p>{% trans forum=i2pconv('forum.i2p') -%}
Great! Find us on IRC irc.freenode.net #i2p or post to
the <a href="http://{{ forum }}/">forum</a> and we'll post it here (with
the answer, hopefully).
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,39 @@
{% extends "global/bounty.html" %}
{% block title %}{{ _('Bounty Arabic translation of webpage and router console') }}{% endblock %}
{% block donatename %}{{ _('Arabic translation') }}{% endblock %}
{% block bountydetails %}
<p>{% trans -%}
To improve I2P usage and attract more people
into I2P echelon set out this bounty for translation
of the I2P web page and I2P router console into Arabic.
{%- endtrans %}</p>
<p>
{{ _('This bounty is set into 2 subparts:') }}
<br>
{{ _('Part 1 is translation of the webpage.') }}<br>
</p>
<p>
{{ _('For collecting the bounty of 20 BTC you need to translate the following pages:') }}<br>
http://www.i2p2.de/index.html<br>
http://www.i2p2.de/download.html<br>
http://www.i2p2.de/intro.html<br>
http://www.i2p2.de/faq.html<br>
http://www.i2p2.de/bounties.html<br>
http://www.i2p2.de/getinvolved.html<br>
http://www.i2p2.de/donate.html<br>
{{ _('This job was done by hamada and the bounty of 20 BTC was paid to hamada.') }}<br>
</p>
<p>{% trans -%}
Part 2 is the translation of the router console. The router console was
partly translated and the bounty of 80 BTC was paid to hamada.
{%- endtrans %}</p>
{% endblock %}
{% block bountyjudge %}
<p>{% trans -%}
Judge is echelon.
{%- endtrans %}</p>
{% endblock %}
{% block bountynotesouter %}{% endblock %}

View File

@@ -0,0 +1,18 @@
{% extends "global/bounty.html" %}
{% block title %}{{ _('Bounty creating a I2P native Bitcoin client') }}{% endblock %}
{% block donatename %}{{ _('BTC I2P native client') }}{% endblock %}
{% block bountydetails %}
<p>{% trans -%}
For a future of I2P and attract more people
into I2P this bounty is to create a I2P native Bitcoin client.
It should integrate with other client via the I2P network and via gateways to
the existant bitcoin network.
{%- endtrans %}</p>
{% endblock %}
{% block bountyjudge %}
<p>{% trans -%}
Judge is psychonaut who donated the first 30 &euro; to this bounty.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,42 @@
{% extends "global/bounty.html" %}
{% block title %}{{ _('Bounty datastorage') }}{% endblock %}
{% block donatename %}{{ _('datastore') }}{% endblock %}
{% block bountydetails %}
<p>{% trans -%}
To improve I2P's usage and to be independent of routers
online status we want a datastorage as a extension to I2P.
Like in Freenet the datastorage should be distributed and every
participating node should be able to configure his options.
The files should be saved in chunks and at least 2-3 times to
obtain redundancy. Usage of storage space should be auto balanced.
As it is a extra application, it should work flawless within I2P and
cooperate nice with the I2P router. Maybe a integration within the
webpage/router could be done.
{%- endtrans %}</p>
<p>{% trans -%}
This bounty cooperates with the 2 other bounties "frost for I2P" and
"eepsites in datastorage".
{%- endtrans %}</p>
<p>{% trans -%}
The frost for I2P datastorage bounty is paid for a frost like program
with which files/messages are stored into database and got from database.
It needs to work with a GUI.
{%- endtrans %}</p>
<p>{% trans -%}
The eepsite served out of I2P datastorage extends a I2P router to send
out eepsites out of the I2P datastorage. All files for eepsites need to be
saved inside of datastorage and are taken from it.
Extension:
For better integration all datastorage participants could serve that eepsite.
{%- endtrans %}</p>
{% endblock %}
{% block bountynotes %}
<li>{% trans -%}
For bounties to be declared done and paid, we need the program AND the source.
Source and code need to be licensed under a free license (free to change and
free to distribute).
{%- endtrans %}</li>
{{ super() }}
{% endblock %}

View File

@@ -0,0 +1,15 @@
{% extends "global/bounty.html" %}
{% block title %}{{ _('Bounty I2P package in Debian and Ubuntu mirrors') }}{% endblock %}
{% block donatename %}{{ _('I2P Ubuntu/Debian package') }}{% endblock %}
{% block bountydetails %}
<p>{% trans -%}
For the future of I2P and in order to attract more people
to I2P, this bounty was set for including an I2P package into the Ubuntu and Debian
archive mirrors.
To claim this bounty, the I2P router package needs to be available from
Ubuntu and Debian archive mirrors and Debian bug
<a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=448638">448638</a>
needs to be closed successfully.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,13 @@
{% extends "global/bounty.html" %}
{% block title %}{{ _('Bounty I2PHex code implementation') }}{% endblock %}
{% block donatename %}{{ _('i2phex code implementation') }}{% endblock %}
{% block bountydetails %}
<p>{% trans -%}
To improve I2P usage and attract more people
into I2PHex P2P ArneBab setout the bounty for implementing actual
Phex code onto I2PHex.
{%- endtrans %}</p>
{% endblock %}
{% block bountynotesouter %}{% endblock %}

View File

@@ -0,0 +1,167 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Bounties') }}{% endblock %}
{% block content %}
<!-- file version 2013.03.31.01 -->
<h1>{{ _('Bounties for I2P') }}</h1>
<p>{% trans -%}
While we always gratefully accept any contributions of code,
documentation, and the like, there are other ways to help I2P move
forward. As with any open source project, our goals would be achieved more
rapidly if we were able to support all of our contributors to work on
I2P full time. However, as with any open source project, that's not a
possibility. Instead, we are making use of a bounty system, whereby
anyone can get support for working on something that people want
implemented, and people who want to contribute to I2P can be assured that
their support goes to what they care about.
{%- endtrans %}</p>
<p>{% trans -%}
We are also keeping open the ability for people who want to support I2P
but don't have strong feelings about the bounties available. Those people
can simply put their trust in the I2P team to do what we feel is best by
donating to a catch-all general fund that will be used as deemed
necessary - allocated to various bounties, covering incidentals (hosting,
etc), and the like.
{%- endtrans %}</p>
<h2>{{ _('Current bounties') }}</h2>
<table border="1">
<tr><td><p><b>{{ _('Name') }}</b></p></td><td><p><b>{{ _('Status') }}</b></p></td><td><p><b>{{ _('Judge') }}</b></p></td><td><p><b>{{ _('Dev') }} <sup>*</sup></b></p></td><td><p><b>{{ _('Bounty') }}</b></p></td></tr>
<tr>
<td><p><b><a href="{{ site_url('get-involved/bounties/datastore') }}">{{ _('Frost for I2P datastorage') }}</a></b></p></td>
<td><p>{{ _('Proposal in development') }}</p></td>
<td><p>echelon</p></td>
<td><p>[{{ _('vacant') }}]</p></td>
<td><p>&euro;50 EUR</p></td>
</tr>
<tr>
<td><p><b><a href="{{ site_url('get-involved/bounties/datastore') }}">{{ _('Eepsites served out of I2P datastorage') }}</a></b></p></td>
<td><p>{{ _('Proposal in development') }}</p></td>
<td><p>echelon</p></td>
<td><p>[{{ _('vacant') }}]</p></td>
<td><p>&euro;65 EUR and 2 BTC</p></td>
</tr>
<tr>
<td><p><b><a href="{{ site_url('get-involved/bounties/i2phex') }}">{{ _('Backporting Phex code onto I2PHex') }}</a></b></p></td>
<td><p>{{ _('Proposal in development') }}</p></td>
<td><p>Arne Bab</p></td>
<td><p>[{{ _('vacant') }}]</p></td>
<td><p>&euro;100 EUR</p></td>
</tr>
<tr>
<td><p><b><a href="{{ site_url('get-involved/bounties/ipv6') }}">{{ _('Make I2P IPv6 native') }}</a></b></p></td>
<td><p>{{ _('Proposal in development') }}</p></td>
<td><p>Amiga4000</p></td>
<td><p>[{{ _('vacant') }}]</p></td>
<td><p>&euro;100 EUR and 50BTC</p></td>
</tr>
<tr>
<td><p><b><a href="{{ site_url('get-involved/bounties/deb-pack') }}">{{ _('I2P package in Debian and Ubuntu mirrors') }}</a></b></p></td>
<td><p>{{ _('Proposal in development') }}</p></td>
<td><p>h2ik</p></td>
<td><p>[{{ _('vacant') }}]</p></td>
<td><p>&euro;113 EUR</p></td>
</tr>
<tr>
<td><p><b><a href="{{ site_url('get-involved/bounties/btc-client') }}">{{ _('Bitcoin client for I2P') }}</a></b></p></td>
<td><p>{{ _('Done, phase of verification') }}</p></td>
<td><p>psychonaut</p></td>
<td><p>giv</p></td>
<td><p>&euro;30 EUR and 118,34BTC, of which 30 EUR and 68BTC paid to giv</p></td>
</tr>
<tr>
<td><p><b><a href="{{ site_url('get-involved/bounties/unit-tests') }}">{{ _('Unit tests and Multi-router Simulation') }}</a></b></p></td>
<td><p>{{ _('Partly done, partly in work, partly still open') }}</p></td>
<td><p>anonymous</p></td>
<td><p>str4d,hottuna,zzz,sponge,dg</p></td>
<td><p>3000 &euro;, of which 700 &euro; already paid for done jobs</p></td>
</tr>
<tr>
<td><p><b><a href="{{ site_url('get-involved/bounties/syndie-2012') }}">Syndie</a></b></p></td>
<td><p>{{ _('Proposal in development') }}</p></td>
<td><p>I2P team</p></td>
<td><p>[{{ _('vacant') }}]</p></td>
<td><p>18 BTC</p></td>
</tr>
<tr>
<td><p><b><a href="{{ site_url('get-involved/bounties/netdb') }}">NetDB</a></b></p></td>
<td><p>{{ _('Proposal in development') }}</p></td>
<td><p>I2P team</p></td>
<td><p>hottuna</p></td>
<td><p>325 &euro; per sub-bounty</p></td>
</tr>
</table>
<h2>{{ _('Hold bounties, set on hold due to jrandom AWOL and missing funding') }}</h2>
<table border="1">
<tr><td><p><b>{{ _('Name') }}</b></p></td><td><p><b>{{ _('Status') }}</b></p></td><td><p><b>{{ _('Judge') }}</b></p></td><td><p><b>{{ _('Dev') }} <sup>*</sup></b></p></td><td><p><b>{{ _('Bounty') }}</b></p></td></tr>
<tr>
<td><p><b><a href="http://{{ i2pconv('forum.i2p') }}/viewtopic.php?t=1136">{{ _('Bundling bounties') }}</a></b></p></td>
<td><p>{{ _('Proposed') }}</p></td>
<td><p>jrandom</p></td>
<td><p>[{{ _('vacant') }}]</p></td>
<td><p>$0 USD each, or $0 for all</p></td>
</tr>
</table>
<h2>{{ _('Claimed bounties') }}</h2>
<table border="1">
<tr><td><p><b>{{ _('Name') }}</b></p></td><td><p><b>{{ _('Status') }}</b></p></td><td><p><b>{{ _('Dev team') }}<sup>*</sup></b></p></td></tr>
<tr>
<td><p><b><a href="{{ site_url('get-involved/bounties/silc') }}">{{ _('Setting up a SILC server') }}</a></b></p></td>
<td><p>withdrawn and bounty divided between ReturningNovice and the general fund</p></td>
<td><p>An Anonymous Secret Society, society@mail.i2p</p></td>
</tr>
<tr>
<td><p><b><a href="{{ site_url('get-involved/bounties/arabic-trans') }}">{{ _('Arabic translation') }}</a></b></p></td>
<td><p>both parts were taken by hamada for 100 BTC</p></td>
<td><p>hamada</p></td>
</tr>
<tr>
<td><p><b><a href="{{ site_url('get-involved/bounties/datastore') }}">{{ _('Datastore over I2P') }}</a></b></p></td>
<td><p><a href="http://{{ i2pconv('killyourtv.i2p') }}/tahoe-lafs/install/">CLAIMED</a> for 700 &euro;</p></td>
<td><p>duck, smeghead</p></td>
</tr>
<tr>
<td> <p><b><a href="{{ site_url('get-involved/bounties/russian-trans') }}">{{ _('Russian translation') }}</a></b></p></td>
<td><p>claimed for $230 USD sponsored by russian sponsor</p></td>
<td><p>4get</p></td>
</tr>
<tr>
<td><p><b>{{ _('Swarming file transfer') }}</b></p></td>
<td><p><a href="http://{{ i2pconv('i2p-bt.postman.i2p') }}">CLAIMED</a> for &euro;250 EUR</p></td>
<td><p>duck, ragnarok, dinoman, connelly, drwoo</p></td>
</tr>
<tr>
<td><p><b>{{ _('Streaming library window size') }}</b></p></td>
<td><p><a href="http://web.archive.org/web/20070404110818/http://dev.i2p.net/pipermail/i2p/2004-November/000491.html">Claimed (archived link)</a></p></td>
<td><p>jrandom</p></td>
</tr>
<tr>
<td><p><b>{{ _('IRC connect time monitor') }}</b></p></td>
<td>CLAIMED for $10 USD</td>
<td><p>hypercubus</p></td>
</tr>
<tr>
<td><p><b>{{ _('Unit tests (part 1)') }}</b></p></td>
<td>CLAIMED for $300 USD</td>
<td><p>Comwiz</p></td>
</tr>
<tr>
<td><p><b><a href="http://gcc.gnu.org/java/">GCJ</a> support</b></p></td>
<td><p><a href="http://{{ i2pconv('trac.i2p2.i2p') }}/browser/Makefile.gcj">Claimed</a></p></td>
<td><p>jrandom</p></td>
</tr>
</table>
<p><i><sup>*</sup> {% trans -%}
Dev lists anyone who may already be working on the bounty - collaboration is
preferred, so if you're interested in working on it, please contact one of the
people listed!
{%- endtrans %}</i></p>
{% endblock %}

View File

@@ -0,0 +1,21 @@
{% extends "global/bounty.html" %}
{% block title %}{{ _('Bounty I2P IPv6 native') }}{% endblock %}
{% block donatename %}{{ _('native IPv6 I2P') }}{% endblock %}
{% block bountydetails %}
<p>{% trans -%}
For a future of I2P and attract more people
into I2P I withdrawal the vuze bounty and offer a IPv6 bounty.
To claim this bounty, the I2P router needs to run full on native
IPv6 connections like it does on IPv4.
{%- endtrans %}</p>
{% endblock %}
{% block bountynotes %}
<li>{% trans -%}
For bounties to be declared done and paid, we need the plugin AND the source.
Source and code need to be licensed under a free license (free to change and
free to distribute).
{%- endtrans %}</li>
{{ super() }}
{% endblock %}

Some files were not shown because too many files have changed in this diff Show More