{% extends "_layout.html" %} {% block title %}SSU Transport{% endblock %} {% block content %} Updated July 2010 for release 0.8

Secure Semireliable UDP (SSU)

SSU (also called "UDP" in much of the I2P documentation and user interfaces) is one of two transports currently implemented in I2P. The other is NTCP.

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.

SSU Services

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:

Protocol Details

Congestion control

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.

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 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.

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.

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).

MTU

The current implementation uses two MTU values: 608 and 1350. The MTU value is adjusted based on the percentage of packets that are retransmitted.

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.

Based on measurements, 1350 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).

Message Size Limits

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.

Keys

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.

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.

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.

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.

For the DH key agreement, RFC3526 2048bit MODP group (#14) is used:

  p = 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 }
  g = 2

These are the same p and g used for I2P's ElGamal encryption.

Replay prevention

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.

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.

Addressing

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.

    Direct: host, port, introKey, options
  Indirect: tag, relayhost, port, relayIntroKey, targetIntroKey, options

Each of the addresses may also expose a series of options - special capabilities of that particular peer. For a list of available capabilities, see below.

The addresses, options, and capabilities are published in the network database.

Direct Session Establishment

Direct session establishment is used when no third party is required for NAT traversal. The message sequence is as follows:

Connection establishment (direct)

Alice connects directly to Bob.
        Alice                         Bob
    SessionRequest--------------------->
          <---------------------SessionCreated
    SessionConfirmed------------------->
          <---------------------->Data

Introduction

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).

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.

Connection establishment (indirect using an introducer)

Alice first connects to introducer Bob, who relays the request to Charlie.
        Alice                         Bob                  Charlie
    RelayRequest ---------------------->
         <--------------RelayResponse    RelayIntro----------->
         <--------------------------------------------HolePunch (data ignored)
    SessionRequest-------------------------------------------->
         <--------------------------------------------SessionCreated
    SessionConfirmed------------------------------------------>
         <----------------------------------------------->Data

Peer testing

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:

        Alice                  Bob                  Charlie
    PeerTest ------------------->
                             PeerTest-------------------->
                                <-------------------PeerTest
         <-------------------PeerTest
         <------------------------------------------PeerTest
    PeerTest------------------------------------------>
         <------------------------------------------PeerTest

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:

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.

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.

Peer capabilities

B
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'.
C
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.

Future Work

Implementation Diagram

This diagram should accurately reflect the current implementation, however there may be small differences.

Specification

Now on the SSU specification page. {% endblock %}