389 lines
17 KiB
HTML
389 lines
17 KiB
HTML
{% extends "_layout.html" %}
|
|
{% block title %}SSU Transport{% endblock %}
|
|
{% block content %}
|
|
|
|
Updated December 2011 for release 0.8.12
|
|
|
|
<h1>Secure Semireliable UDP (SSU)</h1>
|
|
<p>
|
|
SSU (also called "UDP" in much of the I2P documentation and user interfaces)
|
|
is one of two <a href="transport.html">transports</a> currently implemented in I2P.
|
|
The other is <a href="ntcp.html">NTCP</a>.
|
|
</p><p>
|
|
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.
|
|
|
|
<h2>SSU Services</h2>
|
|
|
|
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:
|
|
|
|
<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>
|
|
|
|
|
|
<h1>Protocol Details</h1>
|
|
|
|
<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 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>
|
|
|
|
<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 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>
|
|
|
|
<h3><a name="mtu">MTU</a></h3>
|
|
<p>
|
|
As of router version 0.8.12,
|
|
two MTU values are used: 620 and 1488.
|
|
The MTU value is adjusted based on the percentage of packets that are retransmitted.
|
|
</p><p>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
|
|
<h3><a name="max">Message Size Limits</a></h3>
|
|
<p>
|
|
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.
|
|
</p>
|
|
|
|
<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 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>
|
|
|
|
<p>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>
|
|
|
|
<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>
|
|
These are the same p and g used for I2P's
|
|
<a href="how_cryptography.html#elgamal">ElGamal encryption</a>.
|
|
</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 id="addressing">Addressing</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>
|
|
|
|
<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
|
|
capabilities of that particular peer. For a list of available
|
|
capabilities, see <a href="#capabilities">below</a>.</p>
|
|
|
|
<p>
|
|
The addresses, options, and capabilities are published in the <a href="how_networkdatabase.html">network database</a>.
|
|
</p>
|
|
|
|
|
|
<h2><a name="direct">Direct Session Establishment</a></h2>
|
|
<p>
|
|
Direct session establishment is used when no third party is required for NAT traversal.
|
|
The message sequence is as follows:
|
|
</p>
|
|
|
|
<h3><a name="establishDirect">Connection establishment (direct)</a></h3>
|
|
|
|
Alice connects directly to Bob.
|
|
|
|
<pre>
|
|
Alice Bob
|
|
SessionRequest--------------------->
|
|
<---------------------SessionCreated
|
|
SessionConfirmed------------------->
|
|
<---------------------->Data
|
|
</pre>
|
|
|
|
|
|
|
|
<h2><a name="introduction">Introduction</a></h2>
|
|
|
|
<p>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).</p>
|
|
|
|
<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 receives 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
|
|
-->
|
|
|
|
<h3><a name="establishIndirect">Connection establishment (indirect using an introducer)</a></h3>
|
|
|
|
Alice first connects to introducer Bob, who relays the request to Charlie.
|
|
|
|
<pre>
|
|
Alice Bob Charlie
|
|
RelayRequest ---------------------->
|
|
<--------------RelayResponse RelayIntro----------->
|
|
<--------------------------------------------HolePunch (data ignored)
|
|
SessionRequest-------------------------------------------->
|
|
<--------------------------------------------SessionCreated
|
|
SessionConfirmed------------------------------------------>
|
|
<----------------------------------------------->Data
|
|
</pre>
|
|
|
|
<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 ------------------->
|
|
PeerTest-------------------->
|
|
<-------------------PeerTest
|
|
<-------------------PeerTest
|
|
<------------------------------------------PeerTest
|
|
PeerTest------------------------------------------>
|
|
<------------------------------------------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="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>
|
|
|
|
<h1><a name="future">Future Work</a></h1>
|
|
<ul><li>
|
|
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>
|
|
The current implementation repeatedly sends acknowledgments for the same packets,
|
|
which unnecessarily increases overhead.
|
|
</li><li>
|
|
The Session Destroyed message was implemented (reception only) in release 0.8.1,
|
|
and is never sent. Transmission implementation scheduled for release 0.8.9.
|
|
</li><li>
|
|
The default small MTU value of 608 should be analyzed and possibly increased.
|
|
The current MTU adjustment strategy should be evaluated.
|
|
Does a streaming lib 1730-byte packet fit in 3 SSU packets? Probably not.
|
|
</li><li>
|
|
Rekeying is currently unimplemented and may never be.
|
|
</li><li>
|
|
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>
|
|
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>
|
|
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>
|
|
|
|
<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>.
|
|
|
|
|
|
{% endblock %}
|