Added translation tags to docs/transport/*

This commit is contained in:
str4d
2013-02-05 04:39:24 +00:00
parent ad0f759014
commit 98b90ec20a
3 changed files with 505 additions and 331 deletions

View File

@@ -1,126 +1,158 @@
{% extends "global/layout.html" %}
{% block title %}Transport Overview{% endblock %}
{% block lastupdated %}July 2010{% endblock %}
{% block title %}{% trans %}Transport Overview{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}July 2010{% endtrans %}{% endblock %}
{% block accuratefor %}0.8{% endblock %}
{% block content %}
<h1>Transports in I2P</h1>
<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> I2P supports multiple transports simultaneously.
<p>{% trans -%}
I2P supports multiple transports simultaneously.
There are two transports currently implemented:
{%- endtrans %}</p>
<ol>
<li> <a href="{{ site_url('docs/transport/ntcp') }}">NTCP</a>, a Java New I/O (NIO) TCP transport
<li> <a href="{{ site_url('docs/transport/ssu') }}">SSU</a>, or Secure Semireliable UDP
<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>Transport Services</h2>
<h2>{% trans %}Transport Services{% endtrans %}</h2>
<p>{% trans -%}
The transport subsystem in I2P provides the following services:
{%- endtrans %}</p>
<ul>
<li>Maintain a set of router addresses, one or more for each transport,
that the router publishes as its global contact information (the RouterInfo)
<li>Selection of the best transport for each outgoing message
<li>Queueing of outbound messages by priority
<li>Bandwidth limiting, both outbound and inbound, according to router configuration
<li>Setup and teardown of transport connections
<li>Encryption of point-to-point communications
<li>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
<li>Firewall port opening using UPnP (Universal Plug and Play)
<li>Cooperative NAT/Firewall traversal
<li>Local IP detection by various methods, including UPnP, inspection of incoming connections, and enumeration of network devices
<li>Coordination of firewall status and local IP, and changes to either, among the transports
<li>Communication of firewall status and local IP, and changes to either, to the router and the user interface
<li>Determination of a consensus clock, which is used to periodically update the router's clock, as a backup for NTP
<li>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
<li>Qualification of valid IP addresses according to a local rule set
<li>Honoring the automated and manual lists of banned peers maintained by the router,
and refusing outbound and inbound connections to those peers
<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>Transport Addresses</h2>
<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.
<p>
Typical scenarios are:
{%- endtrans %}</p>
<p>{% trans %}Typical scenarios are:{% endtrans %}
<ul>
<li>A router has no published addresses, so it is considered "hidden" and cannot receive incoming connections
<li>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="{{ site_url('docs/transport/ssu') }}">the SSU spec</a> for details)
<li>A router is not firewalled or its NAT ports are open; it publishes both NTCP and SSU addresses containing
directly-accessible IP and ports.
<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>Transport Selection</h2>
<h2>{% trans %}Transport Selection{% endtrans %}</h2>
The transport system delivers <a href="i2np.html">I2NP messages</a>. The transport selected for any message is
<p>{% trans i2np=site_url('docs/protocol/i2np') -%}
The transport system delivers <a href="{{ i2np }}">I2NP messages</a>. The transport selected for any message is
independent of the application-layer protocol (TCP or UDP).
<p>
{%- 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.
<p>
{%- endtrans %}</p>
<p>{% trans -%}
Whether a transport bids, and with what value, depend on numerous factors:
{%- endtrans %}</p>
<ul>
<li>Configuration of transport preferences
<li>Whether the transport is already connected to the peer
<li>The number of current connections compared to various connection limit thresholds
<li>Whether recent connection attempts to the peer have failed
<li>The size of the message, as different transports have different size limits
<li>Whether the peer can accept incoming connections for that transport, as advertised in its RouterInfo
<li>Whether the connection would be indirect (requiring introducers) or direct
<li>The peer's transport preference, as advertised in its RouterInfo
<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>
<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>New Transports and Future Work</h2>
<h2>{% trans %}New Transports and Future Work{% endtrans %}</h2>
<p>{% trans -%}
Additional transports may be developed, including:
{%- endtrans %}</p>
<ul>
<li>A TLS/SSH look-alike transport
<li>An "indirect" transport for routers that are not reachable by all other routers (one form of "restricted routes")
<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>
<p>{% trans -%}
Also, the existing transports will be enhanced to support multiple addresses within a single transport,
including IPV6 addresses. Currently, a transport may only advertise a single IPV4 address.
{%- endtrans %}</p>
<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>
<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><p>
Analyze
<a href="http://www.cse.chalmers.se/%7Ejohnwolf/publications/hjelmvik_breaking.pdf">Breaking and Improving Protocol Obfuscation</a>
<p>{% trans pdf='http://www.cse.chalmers.se/%7Ejohnwolf/publications/hjelmvik_breaking.pdf' -%}
Analyze <a href="{{ pdf }}">Breaking and Improving Protocol Obfuscation</a>
and see how transport-layer padding may improve things.
</p>
{%- endtrans %}</p>
{% endblock %}

View File

@@ -1,64 +1,65 @@
{% extends "global/layout.html" %}
{% block title %}NTCP{% endblock %}
{% block lastupdated %}August 2010{% endblock %}
{% block lastupdated %}{% trans %}August 2010{% endtrans %}{% endblock %}
{% block accuratefor %}0.8{% endblock %}
{% block content %}
<h2>NTCP (NIO-based TCP)</h2>
<h2>{% trans %}NTCP (NIO-based TCP){% endtrans %}</h2>
<p>
NTCP
is one of two <a href="{{ site_url('docs/transport') }}">transports</a> currently implemented in I2P.
The other is <a href="{{ site_url('docs/transport/ssu') }}">SSU</a>.
NTCP
is a Java NIO-based transport
introduced in I2P release 0.6.1.22.
<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.
</p><p>
{%- endtrans %}</p>
By default,
NTCP uses the IP/Port
<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.
</p><p>
{%- 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.
</p>
{%- endtrans %}</p>
<h2>NTCP Protocol Specification</h2>
<h2>{% trans %}NTCP Protocol Specification{% endtrans %}</h2>
<h3>Standard Message Format</h3>
<p>
After establishment,
the NTCP transport sends individual I2NP messages, with a simple checksum.
The unencrypted message is encoded as follows:
<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>
<pre>
* +-------+-------+--//--+---//----+-------+-------+-------+-------+
* | sizeof(data) | data | padding | Adler checksum of sz+data+pad |
* +-------+-------+--//--+---//----+-------+-------+-------+-------+
</pre>
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.
</p>
<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>
<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.
</p>
{%- endtrans %}</p>
<h3>Time Sync Message Format</h3>
<p>
One special case is a metadata message where the sizeof(data) is 0. In
that case, the unencrypted message is encoded as:
<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>
<pre>
* +-------+-------+-------+-------+-------+-------+-------+-------+
* | 0 | timestamp in seconds | uninterpreted
@@ -66,19 +67,25 @@ The minimum data size is 1.
* uninterpreted | Adler checksum of bytes 0-11 |
* +-------+-------+-------+-------+-------+-------+-------+-------+
</pre>
<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>Checksums</h3>
<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="http://tools.ietf.org/html/rfc1950">ZLIB Specification</a>.
as defined in the <a href="{{ rfc1950 }}">ZLIB Specification</a>.
{%- endtrans %}</p>
<h3>Establishment Sequence</h3>
<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>
<pre>
* Alice contacts Bob
* =========================================================
@@ -90,57 +97,58 @@ Then, DSA signatures of the critical data are exchanged to confirm the connectio
</pre>
<pre>
Legend:
X, Y: 256 byte DH public keys
{% 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: timestamps (4 bytes, seconds since epoch)
sk: 32 byte Session key
sz: 2 byte size of Alice identity to follow
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 %}
</pre>
<h4 id="DH">DH Key Exchange</h4>
<p>
<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="how_cryptography.html#elgamal">ElGamal encryption</a>.
</p>
<a href="{{ cryptography }}#elgamal">ElGamal encryption</a>.
{%- endtrans %}</p>
<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>Alice generates a secret 226-bit integer x.
She then calculates X = g^x mod p.
</li>
<li>Alice sends X to Bob <b>(Message 1)</b>.</li>
<li>Bob generates a secret 226-bit integer y.
He then calculates Y = g^y mod p.</li>
<li>Bob sends Y to Alice.<b>(Message 2)</b></li>
<li>Alice can now compute sessionKey = Y^x mod p.</li>
<li>Bob can now compute sessionKey = X^y mod p.</li>
<li>Both Alice and Bob now have a shared key sessionKey = g^(x*y) mod p.</li>
<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>.
</p>
{%- endtrans %}</p>
<h4>Message 1 (Session Request)</h4>
This is the DH request.
Alice already has Bob's
<a href="common_structures_spec.html#struct_RouterIdentity">Router Identity</a>,
<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="common_structures_spec.html#struct_RouterInfo">Router Info</a>,
<a href="{{ commonstructures }}#struct_RouterInfo">Router Info</a>,
which was published to the
<a href="{{ site_url('docs/how/networkdatabase') }}">network database</a>.
<a href="{{ netdb }}">network database</a>.
Alice sends Bob:
{%- endtrans %}</p>
<pre>
* X+(H(X) xor Bob.identHash)-----------------------------&gt;
Size: 288 bytes
{% trans %}Size:{% endtrans %} 288 bytes
</pre>
Contents:
<p>{% trans %}Contents:{% endtrans %}</p>
<pre>
+----+----+----+----+----+----+----+----+
| X, as calculated from DH |
@@ -158,28 +166,32 @@ Contents:
| |
+----+----+----+----+----+----+----+----+
X: 256 byte X from Diffie Hellman
X: {% trans %}256 byte X from Diffie Hellman{% endtrans %}
HXxorHI: SHA256 Hash(X) xored with SHA256 Hash(Bob's <a href="common_structures_spec.html#struct_RouterIdentity">Router Identity</a>)
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>Notes:</b>
<ul><li>
<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.
</li></ul>
{%- endtrans %}</li></ul>
<h4>Message 2 (Session Created)</h4>
<h4>{% trans %}Message 2 (Session Created){% endtrans %}</h4>
<p>{% trans -%}
This is the DH reply. Bob sends Alice:
{%- endtrans %}</p>
<pre>
* &lt;----------------------------------------Y+E(H(X+Y)+tsB+padding, sk, Y[239:255])
Size: 304 bytes
{% trans %}Size:{% endtrans %} 304 bytes
</pre>
Unencrypted Contents:
<p>{% trans %}Unencrypted Contents:{% endtrans %}</p>
<pre>
+----+----+----+----+----+----+----+----+
| Y as calculated from DH |
@@ -201,19 +213,19 @@ Unencrypted Contents:
| |
+----+----+----+----+----+----+----+----+
Y: 256 byte Y from Diffie Hellman
Y: {% trans %}256 byte Y from Diffie Hellman{% endtrans %}
HXY: SHA256 Hash(X concatenated with Y)
HXY: {% trans %}SHA256 Hash(X concatenated with Y){% endtrans %}
(32 bytes)
tsB: 4 byte timestamp (seconds since the epoch)
tsB: {% trans %}4 byte timestamp (seconds since the epoch){% endtrans %}
padding: 12 bytes random data
padding: {% trans %}12 bytes random data{% endtrans %}
</pre>
Encrypted Contents:
<p>{% trans %}Encrypted Contents:{% endtrans %}</p>
<pre>
+----+----+----+----+----+----+----+----+
| Y as calculated from DH |
@@ -235,29 +247,31 @@ Encrypted Contents:
| |
+----+----+----+----+----+----+----+----+
Y: 256 byte Y from Diffie Hellman
Y: {% trans %}256 byte Y from Diffie Hellman{% endtrans %}
encrypted data: 48 bytes <a href="{{ site_url('docs/how/cryptography') }}#AES">AES encrypted</a> using the DH session key and
the last 16 bytes of Y as the IV
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>Notes:</b>
<ul><li>
<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.
</li></ul>
</p>
{%- endtrans %}</li></ul>
<h4>Message 3 (Session Confirm A)</h4>
<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>
<pre>
* E(sz+Alice.identity+tsA+padding+S(X+Y+Bob.identHash+tsA+tsB), sk, hX_xor_Bob.identHash[16:31])---&gt;
Size: 448 bytes (typ. for 387 byte identity)
{% trans %}Size:{% endtrans %} 448 bytes (typ. for 387 byte identity)
</pre>
Unencrypted Contents:
<p>{% trans %}Unencrypted Contents:{% endtrans %}</p>
<pre>
+----+----+----+----+----+----+----+----+
| sz | Alice's Router Identity |
@@ -283,21 +297,25 @@ Unencrypted Contents:
| |
+----+----+----+----+----+----+----+----+
sz: 2 byte size of Alice's router identity to follow (should always be 387)
sz: {% trans %}2 byte size of Alice's router identity to follow (should always be 387){% endtrans %}
ident: Alice's 387 byte <a href="common_structures_spec.html#struct_RouterIdentity">Router Identity</a>
ident: {% trans commonstructures=site_url('docs/spec/common-structures') -%}
Alice's 387 byte <a href="{{ commonstructures }}#struct_RouterIdentity">Router Identity</a>
{%- endtrans %}
tsA: 4 byte timestamp (seconds since the epoch)
tsA: {% trans %}4 byte timestamp (seconds since the epoch){% endtrans %}
padding: 15 bytes random data
padding: {% trans %}15 bytes random data{% endtrans %}
signature: the 40 byte <a href="common_structures_spec.html#type_Signature">DSA signature</a> of the following concatenated data:
X, Y, Bob's <a href="common_structures_spec.html#struct_RouterIdentity">Router Identity</a>, tsA, tsB.
Alice signs it with the <a href="common_structures_spec.html#type_SigningPrivateKey">private signing key</a> associated with the <a href="common_structures_spec.html#type_SigningPublicKey">public signing key</a> in her <a href="common_structures_spec.html#struct_RouterIdentity">Router Identity</a>
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>
Encrypted Contents:
<p>{% trans %}Encrypted Contents:{% endtrans %}</p>
<pre>
+----+----+----+----+----+----+----+----+
| |
@@ -307,30 +325,36 @@ Encrypted Contents:
| |
+----+----+----+----+----+----+----+----+
encrypted data: 448 bytes <a href="{{ site_url('docs/how/cryptography') }}#AES">AES encrypted</a> using the DH session key and
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>Notes:</b>
<ul><li>
<p><b>{% trans %}Notes:{% endtrans %}</b></p>
<ul>
<li>{% trans -%}
Bob verifies the signature, and on failure, drops the connection.
</li><li>
{%- endtrans %}</li>
<li>{% trans -%}
Bob may drop the connection if the clock skew with Alice is too high as calculated using tsA.
</li></ul>
</p>
{%- endtrans %}</li>
</ul>
<h4>Message 4 (Session Confirm B)</h4>
<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>
<pre>
* &lt;----------------------E(S(X+Y+Alice.identHash+tsA+tsB)+padding, sk, prev)
Size: 48 bytes
{% trans %}Size:{% endtrans %} 48 bytes
</pre>
Unencrypted Contents:
<p>{% trans %}Unencrypted Contents:{% endtrans %}</p>
<pre>
+----+----+----+----+----+----+----+----+
| |
@@ -347,16 +371,18 @@ Unencrypted Contents:
+----+----+----+----+----+----+----+----+
signature: the 40 byte <a href="common_structures_spec.html#type_Signature">DSA signature</a> of the following concatenated data:
X, Y, Alice's <a href="common_structures_spec.html#struct_RouterIdentity">Router Identity</a>, tsA, tsB.
Bob signs it with the <a href="common_structures_spec.html#type_SigningPrivateKey">private signing key</a> associated with the <a href="common_structures_spec.html#type_SigningPublicKey">public signing key</a> in his <a href="common_structures_spec.html#struct_RouterIdentity">Router Identity</a>
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: 8 bytes random data
padding: {% trans %}8 bytes random data{% endtrans %}
</pre>
Encrypted Contents:
<p>{% trans %}Encrypted Contents:{% endtrans %}</p>
<pre>
+----+----+----+----+----+----+----+----+
| |
@@ -366,68 +392,82 @@ Encrypted Contents:
| |
+----+----+----+----+----+----+----+----+
encrypted data: 48 bytes <a href="{{ site_url('docs/how/cryptography') }}#AES">AES encrypted</a> using the DH session key and
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>
<ul><li>
<p><b>Notes:</b></p>
<ul><li>{% trans -%}
Alice verifies the signature, and on failure, drops the connection.
</li></ul>
</p>
{%- endtrans %}</li></ul>
<h4>After Establishment</h4>
<p>
<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.
</p>
{%- endtrans %}</p>
<h3>Check Connection Message</h3>
<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:
A check info connection will receive 256 bytes containing:
{%- endtrans %}</p>
<ul>
<li> 32 bytes of uninterpreted, ignored data
<li> 1 byte size
<li> that many bytes making up the local router's IP address (as reached by the remote side)
<li> 2 byte port number that the local router was reached on
<li> 4 byte i2p network time as known by the remote side (seconds since the epoch)
<li> uninterpreted padding data, up to byte 223
<li> xor of the local router's identity hash and the SHA256 of bytes 32 through bytes 223
<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>Discussion</h2>
Now on the <a href="{{ site_url('docs/discussions/ntcp') }}">NTCP Discussion Page</a>.
<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">Future Work</a></h2>
<ul><li>
<h2><a name="future">{% trans %}Future Work{% endtrans %}</a></h2>
<ul>
<li>{% trans -%}
The maximum message size should be increased to approximately 32 KB.
</li><li>
{%- 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.
</li><li>
{%- endtrans %}</li>
<li>{% trans -%}
Memory utilization (including that of the kernel) for NTCP should be compared to that for SSU.
</li><li>
{%- endtrans %}</li>
<li>{% trans -%}
Can the establishment messages be randomly padded somehow, to frustrate
identification of I2P traffic based on initial packet sizes?
</li><li>
{%- endtrans %}</li>
<li>{% trans -%}
Review and possibly disable 'check connection'
</li></ul>
</p>
{%- endtrans %}</li>
</ul>
{% endblock %}

View File

@@ -1,50 +1,60 @@
{% extends "global/layout.html" %}
{% block title %}SSU Transport{% endblock %}
{% block lastupdated %}October 2012{% endblock %}
{% block title %}{% trans %}SSU Transport{% endtrans %}{% endblock %}
{% block lastupdated %}{% trans %}October 2012{% endtrans %}{% endblock %}
{% block accuratefor %}0.9.2{% endblock %}
{% block content %}
<h1>Secure Semireliable UDP (SSU)</h1>
<p>
<h1>{% trans %}Secure Semireliable UDP{% endtrans %} (SSU)</h1>
<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="{{ site_url('docs/transport') }}">transports</a> currently implemented in I2P.
The other is <a href="{{ site_url('docs/transport/ntcp') }}">NTCP</a>.
</p><p>
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>SSU Services</h2>
<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>Cooperative NAT/Firewall traversal using <a href="#introduction">introducers</a>
<li>Local IP detection by inspection of incoming packets and <a href="#peerTesting">peer testing</a>
<li>Communication of firewall status and local IP, and changes to either to NTCP
<li>Communication of firewall status and local IP, and changes to either, to the router and the user interface
<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>Protocol Details</h1>
<h1>{% trans %}Protocol Details{% endtrans %}</h1>
<h2><a name="congestioncontrol">Congestion control</a></h2>
<h2><a name="congestioncontrol">{% trans %}Congestion control{% endtrans %}</a></h2>
<p>SSU's need for only semireliable delivery, TCP-friendly operation,
<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.</p>
meant to be both efficient in bandwidth as well as simple to implement.
{%- endtrans %}</p>
<p>Packets are scheduled according to the router's policy, taking care
<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.</p>
other messages.
{%- endtrans %}</p>
<p>The congestion detection techniques vary from TCP as well, since each
<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
@@ -52,48 +62,62 @@ 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.</p>
retransmitted with any new updates.
{%- endtrans %}</p>
<p>The current implementation does not pad the packets to
<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).
</p>
{%- endtrans %}</p>
<h3><a name="mtu">MTU</a></h3>
<p>
<p>{% trans -%}
As of router version 0.8.12,
two MTU values are used: 620 and 1484.
The MTU value is adjusted based on the percentage of packets that are retransmitted.
</p><p>
{%- endtrans %}</p>
<p>{% trans -%}
For both MTU values, it is desirable that (MTU % 16) == 12, so that
the payload portion after the 28-byte IP/UDP header is a multiple of
16 bytes, for encryption purposes.
This calculation is for IPv4 only. While the protocol as specified supports IPv6
addresses, IPv6 is not yet implemented.
</p><p>
{%- 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.
</p><p>
{%- 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).
</p><p>
{%- 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.
</p><p>
{%- 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.
</p><p>
{%- 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.
</p>
{%- endtrans %}</p>
<h3><a name="max">Message Size Limits</a></h3>
<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,
@@ -102,97 +126,115 @@ 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.
</p>
{%- endtrans %}</p>
<h2><a name="keys">Keys</a></h2>
<h2><a name="keys">{% trans %}Keys{% endtrans %}</a></h2>
<p>All encryption used is AES256/CBC with 32 byte keys and 16 byte IVs.
<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.</p>
the publicly knowable introKey is used for the MAC and encryption.
{%- endtrans %}</p>
<p>When using the introKey, both the initial message and any subsequent
<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.</p>
Bob.
{%- endtrans %}</p>
<p>Upon receiving a message, the receiver checks the "from" IP address and port
<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.</p>
it may be dropped anyway.
{%- endtrans %}</p>
<p>If Alice and Bob have an established session, but Alice loses the
<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.</p>
new one.
{%- endtrans %}</p>
<p>For the DH key agreement,
<a href="http://www.faqs.org/rfcs/rfc3526.html">RFC3526</a> 2048bit
MODP group (#14) is used:</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>
<p>{% trans cryptography=site_url('docs/how/cryptography') -%}
These are the same p and g used for I2P's
<a href="{{ site_url('docs/how/cryptography') }}#elgamal">ElGamal encryption</a>.
</p>
<a href="{{ cryptography }}#elgamal">ElGamal encryption</a>.
{%- endtrans %}</p>
<h2><a name="replay">Replay prevention</a></h2>
<h2><a name="replay">{% trans %}Replay prevention{% endtrans %}</a></h2>
<p>Replay prevention at the SSU layer occurs by rejecting packets
<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.</p>
"decay" periodically so that only recently added IVs are detected.
{%- endtrans %}</p>
<p>The messageIds used in DataMessages are defined at layers above
<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.</p>
replay prevention - higher layers should take that into account.
{%- endtrans %}</p>
<h2 id="addressing">Addressing</h2>
<h2 id="addressing">{% trans %}Addressing{% endtrans %}</h2>
<p>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.</p>
<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>
<pre>
Direct: host, port, introKey, options
Indirect: tag, relayhost, port, relayIntroKey, targetIntroKey, options
</pre>
<p>Each of the addresses may also expose a series of options - special
<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>.</p>
capabilities, see <a href="#capabilities">below</a>.
{%- endtrans %}</p>
<p>
The addresses, options, and capabilities are published in the <a href="{{ site_url('docs/how/networkdatabase') }}">network database</a>.
</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">Direct Session Establishment</a></h2>
<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:
</p>
{%- endtrans %}</p>
<h3><a name="establishDirect">Connection establishment (direct)</a></h3>
<p>
<h3><a name="establishDirect">{% trans %}Connection establishment (direct){% endtrans %}</a></h3>
<p>{% trans -%}
Alice connects directly to Bob.
</p>
{%- endtrans %}</p>
<pre>
Alice Bob
SessionRequest ---------------------&gt;
@@ -203,28 +245,35 @@ Alice connects directly to Bob.
DatabaseStoreMessage ---------------&gt;
Data &lt;---------------------------&gt; Data
</pre>
<p>
<p>{% trans i2npspec=site_url('docs/spec/i2np') -%}
After the SessionConfirmed message is received, Bob sends a small
<a href="i2np_spec.html#msg_DeliveryStatus">DeliveryStatus message</a>
<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).
</p><p>
{%- 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="i2np_spec.html#msg_DatabaseStore">DatabaseStore messages</a>
<a href="{{ i2npspec }}#msg_DatabaseStore">DatabaseStore messages</a>
containing their
<a href="common_structures_spec.html#struct_RouterInfo">RouterInfos</a>.
</p><p>
<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.
</p>
{%- endtrans %}</p>
<h2><a name="introduction">Introduction</a></h2>
<h2><a name="introduction">{% trans %}Introduction{% endtrans %}</a></h2>
<p>Introduction keys are delivered through an external channel
<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
@@ -234,9 +283,11 @@ 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).</p>
not necessary to any intermediary relay peer).
{%- endtrans %}</p>
<p>Indirect session establishment by means of a third party introduction
<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
@@ -251,7 +302,8 @@ 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.</p>
full direction session establishment with the specified IP and port.
{%- endtrans %}</p>
<!--
should Bob wait for Charlie to ack the RelayIntro packet to avoid
@@ -261,9 +313,11 @@ full direction session establishment with the specified IP and port.</p>
least one of them gets through
-->
<h3><a name="establishIndirect">Connection establishment (indirect using an introducer)</a></h3>
<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>
<pre>
Alice Bob Charlie
@@ -279,18 +333,20 @@ Alice first connects to introducer Bob, who relays the request to Charlie.
Data &lt;--------------------------------------------------&gt; Data
</pre>
<p>
<p>{% trans -%}
After the hole punch, the session is established between Alice and Charlie as in a direct establishment.
</p>
{%- endtrans %}</p>
<h2><a name="peerTesting">Peer testing</a></h2>
<h2><a name="peerTesting">{% trans %}Peer testing{% endtrans %}</a></h2>
<p>The automation of collaborative reachability testing for peers is
<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:</p>
quite simple:
{%- endtrans %}</p>
<pre>
Alice Bob Charlie
@@ -303,147 +359,193 @@ quite simple:</p>
&lt;------------------------------------------PeerTest
</pre>
<p>Each of the PeerTest messages carry a nonce identifying the
<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:</p>
that may be reached are as follows:
{%- endtrans %}</p>
<ul>
<li>If she doesn't receive a response from Bob, she will retransmit
<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.</li>
Charlie to reply.
{%- endtrans %}</li>
<li>If Alice doesn't receive a PeerTest message with the
<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).</li>
IP and port that Bob offered up should be forwarded).
{%- endtrans %}</li>
<li>If Alice receives Bob's PeerTest message and both of Charlie's
<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.</li>
remote connectivity, ignoring further port discovery.
{%- endtrans %}</li>
<li>If Alice receives Charlie's first message but not his second,
<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.</li>
that Charlie is either confused or no longer online.
{%- endtrans %}</li>
</ul>
<p>Alice should choose Bob arbitrarily from known peers who seem
<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.</p>
to designate a new peer as Bob and try again with a different nonce.
{%- endtrans %}</p>
<p>Alice's introduction key is included in all of the PeerTest
<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.</p>
with either Bob or Charlie, but it is not required.
{%- endtrans %}</p>
<h2><a name="acks">Transmission window, ACKs and Retransmissions</a></h2>
<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="{{ site_url('docs/transport/ssu/spec') }}">the protocol specification page</a>
<a href="{{ ssuspec }}">the protocol specification page</a>
for details.
</p><p>
{%- 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.html">streaming</a>.
or <a href="{{ streaming }}">streaming</a>.
See the code for initial, min and max parameters.
</p>
{%- endtrans %}</p>
<h2><a name="security">Security</a></h2>
<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.
</p><p>
{%- endtrans %}</p>
<p>{% trans -%}
The details of validation are not specified
here. Implementers should add defenses where appropriate.
</p>
{%- endtrans %}</p>
<h2><a name="capabilities">Peer capabilities</a></h2>
<h2><a name="capabilities">{% trans %}Peer capabilities{% endtrans %}</a></h2>
<dl>
<dt>B</dt>
<dd>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'.</dd>
<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>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.</dd>
<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">Future Work</a></h1>
<ul><li>
<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.
</li><li>
{%- endtrans %}</li>
<li>{% trans -%}
The current implementation repeatedly sends acknowledgments for the same packets,
which unnecessarily increases overhead.
</li><li>
{%- 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.
</li><li>
{%- endtrans %}</li>
<li>{% trans -%}
The protocol should be extended to exchange MTUs during the setup.
</li><li>
{%- endtrans %}</li>
<li>{% trans -%}
Rekeying is currently unimplemented and may never be.
</li><li>
{%- 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.
</li><li>
{%- 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.
</li><li>
{%- 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.
</li><li>
Why are introduction keys the same as the router hash, should it be changed, would there be any benefit?
</li><li>
Capacities appear to be unused.
</li><li>
Signed-on times in SessionCreated and SessionConfirmed appear to be unused or unverified.
</li></ul>
{%- endtrans %}</li>
<h1>Implementation Diagram</h1>
<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">Specification</a></h1>
<a href="{{ site_url('docs/spec/ssu') }}">Now on the SSU specification page</a>.
<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 %}