{% extends "global/layout.html" %} {% block title %}I2CP{% endblock %} {% block lastupdated %}November 2012{% endblock %} {% block accuratefor %}0.9.3{% endblock %} {% block content %}

The I2P Client Protocol (I2CP) exposes a strong separation of concerns between the router and any client that wishes to communicate over the network. It enables secure and asynchronous messaging by sending and receiving messages over a single TCP socket, yet never exposing any private keys and authenticating itself to the router only through signatures. With I2CP, a client application tells the router who they are (their "destination"), what anonymity, reliability, and latency tradeoffs to make, and where to send messages. In turn the router uses I2CP to tell the client when any messages have arrived, and to request authorization for some tunnels to be used.

The protocol itself has only been implemented in Java, to provide the Client SDK. This SDK is exposed in the i2p.jar package, which implements the client-side of I2CP. Clients should never need to access the router.jar package, which contains the router itself and the router-side of I2CP.

While implementing the client side of I2CP in a non-Java language is certainly feasible, a non-Java client would also have to implement the streaming library for TCP-style connections. Together, implementing I2CP and the streaming library would be a sizable task.

Applications can take advantage of the base I2CP plus the streaming and datagram libraries by using the Simple Anonymous Messaging or BOB protocols, which do not require clients to deal with any sort of cryptography. Also, clients may access the network by one of several proxies - HTTP, CONNECT, and SOCKS 4/4a/5. Alternatively, Java clients may access those libraries in ministreaming.jar and streaming.jar. So there are several options for both Java and non-Java applications.

Client-side end-to-end encryption (encrypting the data over the I2CP connection) was disabled in I2P release 0.6, leaving in place the ElGamal/AES end-to-end encryption which is implemented in the router. The only cryptography that client libraries must still implement is DSA public/private key signing for LeaseSets and Session Configurations, and management of those keys.

In a standard I2P installation, port 7654 is used by external java clients to communicate with the local router via I2CP. By default, the router binds to address 127.0.0.1. To bind to 0.0.0.0, set the router advanced configuration option i2cp.tcp.bindAllInterfaces=true and restart. Clients in the same JVM as the router pass messages directly to the router through an internal JVM interface.

I2CP Protocol Specification

Now on the I2CP Specification page.

I2CP Initialization

When a client connects to the router, it first sends a single protocol version byte (0x2A). Then it sends a GetDate Message and waits for the SetDate Message response. Next, it sends a CreateSession Message containing the session configuration. It next awaits a RequestLeaseSet Message from the router, indicating that inbound tunnels have been built, and responds with a CreateLeaseSetMessage containing the signed LeaseSet. The client may now initiate or receive connections from other I2P destinations.

I2CP Options

The following options are traditionally passed to the router via a SessionConfig contained in a CreateSession Message or a ReconfigureSession Message.

Router-side Options
Option Recommended Arguments Allowable RangeDefaultDescription
inbound.quantity number from 1 to 3 1 to 162Number of tunnels in. Limit was increased from 6 to 16 in release 0.9; however, numbers higher than 6 are not currently recommended, as this is untested and is incompatible with older releases.
outbound.quantity number from 1 to 3 No limit2Number of tunnels out
inbound.length number from 0 to 3 0 to 72Length of tunnels in
outbound.length number from 0 to 3 0 to 72Length of tunnels out
inbound.lengthVariance number from -1 to 2 -7 to 70Random amount to add or subtract to the length of tunnels in. A positive number x means add a random amount from 0 to x inclusive. A negative number -x means add a random amount from -x to x inclusive. The router will limit the total length of the tunnel to 0 to 7 inclusive. The default variance was 1 prior to release 0.7.6.
outbound.lengthVariance number from -1 to 2 -7 to 70Random amount to add or subtract to the length of tunnels out. A positive number x means add a random amount from 0 to x inclusive. A negative number -x means add a random amount from -x to x inclusive. The router will limit the total length of the tunnel to 0 to 7 inclusive. The default variance was 1 prior to release 0.7.6.
inbound.backupQuantity number from 0 to 3 No limit0Number of redundant fail-over for tunnels in
outbound.backupQuantity number from 0 to 3 No limit0Number of redundant fail-over for tunnels out
inbound.nickname string  Name of tunnel - generally used in routerconsole, which will use the first few characters of the Base64 hash of the destination by default.
outbound.nickname string  Name of tunnel - generally ignored unless inbound.nickname is unset.
inbound.allowZeroHop true, false trueIf incoming zero hop tunnel is allowed
outbound.allowZeroHop true, false trueIf outgoing zero hop tunnel is allowed
inbound.IPRestriction number from 0 to 4 0 to 42Number of IP bytes to match to determine if two routers should not be in the same tunnel. 0 to disable.
outbound.IPRestriction number from 0 to 4 0 to 42Number of IP bytes to match to determine if two routers should not be in the same tunnel. 0 to disable.
outbound.prioritynumber from -25 to 25 -25 to 250Priority adjustment for outbound messages. Higher is higher priority. As of 0.9.4.
i2cp.dontPublishLeaseSet true, false falseShould generally be set to true for clients and false for servers
i2cp.messageReliability  BestEffort, NoneBestEffortGuaranteed is disabled; None implemented in 0.8.1; the streaming lib default is None as of 0.8.1, the client side default is None as of 0.9.4
i2cp.fastReceive true, falsefalseIf true, the router just sends the MessagePayload instead of sending a MessageStatus and awaiting a ReceiveMessageBegin. As of 0.9.4
explicitPeers  nullComma-separated list of Base 64 Hashes of peers to build tunnels through; for debugging only
i2cp.usernamestring  For authorization, if required by the router (since 0.8.2). If the client is running in the same JVM as a router, this option is not required.
i2cp.passwordstring  For authorization, if required by the router (since 0.8.2). If the client is running in the same JVM as a router, this option is not required.
crypto.tagsToSend 1-12840Number of ElGamal/AES Session Tags to send at a time (since 0.9.2). For clients with relatively low bandwidth per-client-pair (IRC, some UDP apps), this may be set lower.
crypto.lowTagThreshold 1-12830Minimum number of ElGamal/AES Session Tags before we send more (since 0.9.2). Recommended: approximately tagsToSend * 2/3
shouldBundleReplyInfotrue, false trueSet to false to disable ever bundling a reply LeaseSet (since 0.9.2). For clients that do not publish their LeaseSet, this option must be true for any reply to be possible. "true" is also recommended for multihomed servers with long connection times.

Setting to "false" may save significant outbound bandwidth, especially if the client is configured with a large number of inbound tunnels (Leases). If replies are still required, this may shift the bandwidth burden to the far-end client and the floodfill. There are several cases where "false" may be appropriate:

  • Unidirectional communication, no reply required
  • LeaseSet is published and higher reply latency is acceptable
  • LeaseSet is published, client is a "server", all connections are inbound so the connecting far-end destination obviously has the leaseset already. Connections are either short, or it is acceptable for latency on a long-lived connection to temporarily increase while the other end re-fetches the LeaseSet after expiration. HTTP servers may fit these requirements.
inbound.*   Any other options prefixed with "inbound." are stored in the "unknown options" properties of the inbound tunnel pool's settings.
outbound.*   Any other options prefixed with "outbound." are stored in the "unknown options" properties of the outbound tunnel pool's settings.

Note: Large quantity, length, or variance settings may cause significant performance or reliability problems.

Note: As of release 0.7.7, option names and values must use UTF-8 encoding. This is primarily useful for nicknames. Prior to that release, options with multi-byte characters were corrupted.

The following options are interpreted on the client side, and will be interpreted if passed to the I2PSession via the I2PClient.createSession() call. The streaming lib should also pass these options through to I2CP. Other implementations may have different defaults.

Client-side Options
Option As Of ReleaseRecommended Arguments Allowable RangeDefaultDescription
i2cp.tcp.host    127.0.0.1Router hostname. If the client is running in the same JVM as a router, this option is ignored, and the client connects to that router internally.
i2cp.tcp.port   1-655357654Router I2CP port. If the client is running in the same JVM as a router, this option is ignored, and the client connects to that router internally.
i2cp.SSL0.8.3true, false falseConnect to the router using SSL. If the client is running in the same JVM as a router, this option is ignored, and the client connects to that router internally.
i2cp.gzip0.6.5true, false  trueGzip outbound data
i2cp.reduceOnIdle0.7.1true, false  falseReduce tunnel quantity when idle
i2cp.closeOnIdle0.7.1true, false  falseClose I2P session when idle
i2cp.reduceIdleTime0.7.11200000300000 minimum (ms) Idle time required (default 20 minutes, minimum 5 minutes)
i2cp.closeIdleTime0.7.11800000300000 minimum (ms) Idle time required (default 30 minutes)
i2cp.reduceQuantity0.7.111 to 51Tunnel quantity when reduced (applies to both inbound and outbound)
i2cp.encryptLeaseSet0.7.1true, false  falseEncrypt the lease
i2cp.leaseSetKey0.7.1   Base64 SessionKey (44 characters)
i2cp.messageReliability  BestEffort, NoneNoneGuaranteed is disabled; None implemented in 0.8.1; None is the default as of 0.9.4
i2cp.fastReceive0.9.4 true, falsetrueIf true, the router just sends the MessagePayload instead of sending a MessageStatus and awaiting a ReceiveMessageBegin.

Note: All arguments, including numbers, are strings. True/false values are case-insensitive strings. Anything other than case-insensitive "true" is interpreted as false. All option names are case-sensitive.

I2CP Payload Data Format and Multiplexing

The end-to-end messages handled by I2CP (i.e. the data sent by the client in a SendMessageMessage and received by the client in a MessagePayloadMessage) are gzipped with a standard 10-byte gzip header beginning with 0x1F 0x8B 0x08 as specified by RFC 1952. As of release 0.7.1, I2P uses ignored portions of the gzip header to include protocol, from-port, and to-port information, thus supporting streaming and datagrams on the same destination, and allowing query/response using datagrams to work reliably in the presence of multiple channels.

The gzip function cannot be completely turned off, however setting i2cp.gzip=false turns the gzip effort setting to 0, which may save a little CPU.

BytesContent
0-2Gzip header 0x1F 0x8B 0x08
3Gzip flags
4-5I2P Source port (Gzip mtime)
6-7I2P Destination port (Gzip mtime)
8Gzip xflags
9I2P Protocol (6 = Streaming, 17 = Datagram, 18 = Raw Datagrams) (Gzip OS)

Data integrity is verified with the standard gzip CRC-32 as specified by RFC 1952.

Future Work

{% endblock %}