Files
i2p.www/www.i2p2/pages/udp.html

363 lines
16 KiB
HTML
Raw Normal View History

2008-02-01 19:13:27 +00:00
{% extends "_layout.html" %}
2010-07-28 01:13:15 +00:00
{% block title %}SSU Transport{% endblock %}
2008-02-01 19:13:27 +00:00
{% block content %}
2010-07-28 01:13:15 +00:00
Updated July 2010 for release 0.8
2008-02-01 19:13:27 +00:00
<h1>Secure Semireliable UDP (SSU)</h1>
<p>
2009-05-12 19:20:08 +00:00
SSU (also called "UDP" in much of the I2P documentation and user interfaces)
2010-07-28 01:13:15 +00:00
is one of two <a href="transport.html">transports</a> currently implemented in I2P.
2009-05-12 19:20:08 +00:00
The other is <a href="ntcp.html">NTCP</a>.
</p><p>
2010-07-28 01:13:15 +00:00
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.
A router
The selection of a transport for a connection.
2008-02-01 19:13:27 +00:00
2010-07-28 01:13:15 +00:00
<h2>SSU Services</h2>
2008-02-01 19:13:27 +00:00
2010-07-28 01:13:15 +00:00
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:
2008-02-01 19:13:27 +00:00
2010-07-28 01:13:15 +00:00
<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
</ul>
2008-02-01 19:13:27 +00:00
2010-07-28 01:13:15 +00:00
<h1>Protocol Details</h1>
2008-02-01 19:13:27 +00:00
<h2><a name="congestioncontrol">Congestion control</a></h2>
<p>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>
<p>Packets are scheduled according to the 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 should operate 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.
Veering away from TCP, however, routers may give up on some messages after
a given period or number of retransmissions while continuing to transmit
other messages.</p>
<p>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.</p>
<p>The simplest possible implementation does not need to 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). A more efficient
strategy would be to bundle multiple message fragments into the same packet,
so long as it doesn't exceed the MTU, but this is not necessary. Eventually,
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.</p>
2009-05-12 19:20:08 +00:00
<h3><a name="mtu">MTU</a></h3>
<p>
The current implementation uses two MTU values: 608 and 1350.
</p><p>
596 gives us 588 IP byes, 568 UDP bytes, and with an SSU data message,
522 fragment bytes, which is enough to send a tunnel data message in 2
packets. A tunnel data message sent over the wire is 1044 bytes, meaning
we need 522 fragment bytes to fit it in 2 packets - add 46 for SSU, 20
for UDP, and 8 for IP, giving us 596. Round up to mod 16, giving a total
of 608.
</p><p>
Based on measurements, 1350 fits nearly all reasonably small I2NP messages
2010-07-28 01:13:15 +00:00
(larger I2NP messages may be up to 1900 to 4500 bytes, which isn't going to fit
2009-05-12 19:20:08 +00:00
into a live network MTU anyway).
</p>
<h3><ajname="max">Message Size Limits</a></h3>
<p>
While a statement above claims that the maximum message size is 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.
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.
2008-02-01 19:13:27 +00:00
<h2><a name="keys">Keys</a></h2>
<p>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>
<p>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 requestor (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>
2009-05-24 22:58:30 +00:00
<p>Upon receiving a message, the receiver checks the "from" IP address and port
2010-01-02 02:47:28 +00:00
with all established sessions - if there are matches,
2009-05-24 22:58:30 +00:00
that session's MAC keys are tested in the HMAC. If none
2008-02-01 19:13:27 +00:00
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>
<p>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>
<p>For the DH key agreement,
<a href="http://www.faqs.org/rfcs/rfc3526.html">RFC3526</a> 2048bit
MODP group (#14) is used:</p>
<pre>
p = 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 }
g = 2
</pre>
<p>The DSA p, q, and g are shared according to the scope of the
identity which created them.</p>
<h2><a name="replay">Replay prevention</a></h2>
<p>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>
<p>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>
<h2><a name="introduction">Introduction</a></h2>
<p>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 receive's Bob's RelayResponse packet, she begins a new
full direction session establishment with the specified IP and port.</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
-->
<h2><a name="peerTesting">Peer testing</a></h2>
<p>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>
<pre>
Alice Bob Charlie
PeerTest -------------------&gt;
PeerTest--------------------&gt;
&lt;-------------------PeerTest
&lt;-------------------PeerTest
&lt;------------------------------------------PeerTest
PeerTest------------------------------------------&gt;
&lt;------------------------------------------PeerTest
</pre>
<p>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>
<ul>
<li>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>
<li>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>
<li>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>
<li>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>
</ul>
<p>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>
<p>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>
<h2><a name="messageSequences">Message sequences</a></h2>
<h3><a name="establishDirect">Connection establishment (direct)</a></h3>
2010-07-28 01:13:15 +00:00
Alice connects directly to Bob.
2008-02-01 19:13:27 +00:00
<pre>
Alice Bob
SessionRequest---------------------&gt;
&lt;---------------------SessionCreated
SessionConfirmed-------------------&gt;
SessionConfirmed-------------------&gt;
SessionConfirmed-------------------&gt;
SessionConfirmed-------------------&gt;
&lt;--------------------------Data
</pre>
2010-07-28 01:13:15 +00:00
<h3><a name="establishIndirect">Connection establishment (indirect using an introducer)</a></h3>
Alice first connects to introducer Bob, who relays the request to Charlie.
2008-02-01 19:13:27 +00:00
<pre>
Alice Bob Charlie
RelayRequest ----------------------&gt;
&lt;--------------RelayResponse RelayIntro-----------&gt;
&lt;--------------------------------------------Data (ignored)
SessionRequest--------------------------------------------&gt;
&lt;--------------------------------------------SessionCreated
SessionConfirmed------------------------------------------&gt;
SessionConfirmed------------------------------------------&gt;
SessionConfirmed------------------------------------------&gt;
SessionConfirmed------------------------------------------&gt;
&lt;---------------------------------------------------Data
</pre>
<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>
<pre>
+----+----+----+----+----+----+----+----+
| MAC |
| |
+----+----+----+----+----+----+----+----+
| IV |
| |
+----+----+----+----+----+----+----+----+
|flag| time |flag|#frg| |
+----+----+----+----+----+----+----+ |
| padding to fit a full AES256 block |
+----+----+----+----+----+----+----+----+
</pre>
<b>Minimal data message with payload</b><br />
<i>(Size: 46+fragmentSize bytes)</i>
<pre>
+----+----+----+----+----+----+----+----+
| MAC |
| |
+----+----+----+----+----+----+----+----+
| IV |
| |
+----+----+----+----+----+----+----+----+
|flag| time |flag|#frg|
+----+----+----+----+----+----+----+----+
messageId | frag info | |
+----+----+----+----+----+----+ |
| that many bytes of fragment data |
. . .
| |
+----+----+----+----+----+----+----+----+
</pre>
<h2><a name="capabilities">Peer capabilities</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>
<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>
</dl>
2010-07-28 01:13:15 +00:00
<h1><a name="future">Future Work</a></h1>
<p>
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.
<p>
The current implementation repeatedly sends acknowledgements for the same packets,
which unnecessarily increases overhead.
<p>
The Session Destroyed message is not currently implemented and is scheduled for release 0.8.1.
<p>
Rekeying is currently unimplemented and may never be.
<h1>Implementation Diagram</h1>
This diagram
should accurately reflect the current implementation, however there may be small differences.
<p>
<img src="/_static/images/udp.png">
<h1><a name="spec">Specification</a></h1>
<a href="udp_spec.html">Now on the SSU specification page</a>.
2008-02-01 19:13:27 +00:00
{% endblock %}