Этот перевод был создан с помощью машинного обучения и может быть не на 100% точным. Просмотреть английскую версию

Обзор I2CP

Обзор протокола клиентов I2P (I2CP) — управление сессиями, параметры, формат полезной нагрузки и мультиплексирование.

Обзор

Протокол клиент-серверного взаимодействия I2P (I2CP) обеспечивает чёткое разделение ответственности между маршрутизатором и любым клиентом, желающим взаимодействовать через сеть. Он позволяет осуществлять безопасную и асинхронную передачу сообщений посредством отправки и получения сообщений через один TCP-сокет. С помощью I2CP клиентское приложение сообщает маршрутизатору, кто оно («назначение»), какие компромиссы между анонимностью, надёжностью и задержкой следует применить, а также куда направлять сообщения. В свою очередь, маршрутизатор использует I2CP, чтобы уведомить клиент о прибытии сообщений и запросить разрешение на использование некоторых туннелей.

Сам протокол реализован на Java для предоставления клиентского SDK. Этот SDK представлен в пакете i2p.jar, который реализует клиентскую часть I2CP. Клиентам никогда не нужно обращаться к пакету router.jar, в котором содержится сам маршрутизатор и сторонняя часть I2CP. Клиент на другом языке, кроме Java, также должен реализовать библиотеку потоковой передачи для соединений по типу TCP.

Приложения могут использовать базовый I2CP вместе с библиотеками потоковой передачи и датаграмм , применяя протокол Простого Анонимного Обмена Сообщениями (SAM) , который не требует от клиентов работы с криптографией. Кроме того, клиенты могут получать доступ к сети через один из нескольких прокси-протоколов — HTTP, CONNECT и SOCKS 4/4a/5. Альтернативно, клиенты на Java могут обращаться к этим библиотекам через ministreaming.jar и streaming.jar. Таким образом, существует несколько вариантов для приложений как на Java, так и на других языках.

Шифрование с конца в конец на стороне клиента (шифрование данных через соединение I2CP) было отключено в релизе I2P 0.6, при этом осталось шифрование с конца в конец по схеме ElGamal/AES, реализованное в маршрутизаторе. Единственная криптография, которую клиентским библиотекам всё ещё необходимо реализовывать — это подпись по алгоритму DSA с открытым/закрытым ключом для LeaseSets и Session Configurations , а также управление этими ключами.

В стандартной установке I2P порт 7654 используется внешними Java-клиентами для связи с локальным маршрутизатором через I2CP. По умолчанию маршрутизатор привязывается к адресу 127.0.0.1. Чтобы привязаться к 0.0.0.0, установите расширенный параметр конфигурации маршрутизатора i2cp.tcp.bindAllInterfaces=true и перезапустите его. Клиенты, работающие в той же JVM, что и маршрутизатор, передают сообщения напрямую через внутренний интерфейс JVM.

Некоторые реализации маршрутизатора и клиента также могут поддерживать внешние подключения по SSL, как настроено параметром i2cp.SSL=true. Хотя SSL не является значением по умолчанию, его настоятельно рекомендуется использовать для любого трафика, который может быть доступен в открытом Интернете. Учётные данные авторизации (имя пользователя и пароль, если таковые имеются), Закрытый ключ и Закрытый ключ для подписи для Назначения передаются открыто, если SSL не включён. Некоторые реализации маршрутизатора и клиента также могут поддерживать внешние подключения через доменные сокеты.

Спецификация протокола I2CP

Полная спецификация протокола доступна на странице спецификации I2CP .

Инициализация I2CP

Когда клиент подключается к маршрутизатору, он сначала отправляет один байт версии протокола (0x2A). Затем он отправляет Сообщение GetDate и ожидает ответа Сообщения SetDate . Далее клиент отправляет Сообщение CreateSession , содержащее конфигурацию сессии. После этого он ожидает получения от маршрутизатора Сообщения RequestLeaseSet , которое указывает на то, что входящие туннели построены, и отвечает сообщением CreateLeaseSetMessage, содержащим подписанный LeaseSet. Теперь клиент может инициировать соединения или принимать подключения от других I2P-адресов.

Параметры I2CP

Опции на стороне роутера

Следующие параметры традиционно передаются маршрутизатору через SessionConfig , содержащийся в сообщении CreateSession Message или в сообщении ReconfigureSession Message .

Router-side Options
OptionAs Of ReleaseRecommended ArgumentsAllowable RangeDefaultDescription
clientMessageTimeout8*1000 - 120*100060*1000The timeout (ms) for all sent messages. Unused. See the protocol specification for per-message settings.
crypto.lowTagThreshold0.9.21-12830Minimum number of ElGamal/AES Session Tags before we send more. Recommended: approximately tagsToSend * 2/3
crypto.ratchet.inboundTags0.9.471-?160Inbound tag window for ECIES-X25519-AEAD-Ratchet. Local inbound tagset size. See proposal 144.
crypto.ratchet.outboundTags0.9.471-?160Outbound tag window for ECIES-X25519-AEAD-Ratchet. Advisory to send to the far-end in the options block. See proposal 144.
crypto.tagsToSend0.9.21-12840Number of ElGamal/AES Session Tags to send at a time. For clients with relatively low bandwidth per-client-pair (IRC, some UDP apps), this may be set lower.
explicitPeersnullComma-separated list of Base 64 Hashes of peers to build tunnels through; for debugging only
i2cp.dontPublishLeaseSettrue, falsefalseShould generally be set to true for clients and false for servers
i2cp.fastReceive0.9.4true, falsefalseIf true, the router just sends the MessagePayload instead of sending a MessageStatus and awaiting a ReceiveMessageBegin.
i2cp.leaseSetAuthType0.9.4100-20The type of authentication for encrypted LS2. 0 for no per-client authentication (the default); 1 for DH per-client authentication; 2 for PSK per-client authentication. See proposal 123.
i2cp.leaseSetEncType0.9.384,00-65535,...0The encryption type to be used, as of 0.9.38. Interpreted client-side, but also passed to the router in the SessionConfig, to declare intent and check support. As of 0.9.39, may be comma-separated values for multiple types. See PublicKey in common structures spec for values. See proposals 123, 144, and 145.
i2cp.leaseSetOfflineExpiration0.9.38The expiration of the offline signature, 4 bytes, seconds since the epoch. See proposal 123.
i2cp.leaseSetOfflineSignature0.9.38The base 64 of the offline signature. See proposal 123.
i2cp.leaseSetPrivKey0.9.41A base 64 X25519 private key for the router to use to decrypt the encrypted LS2 locally, only if per-client authentication is enabled. Optionally preceded by the key type and ':'. Only "ECIES_X25519:" is supported, which is the default. See proposal 123. Do not confuse with i2cp.leaseSetPrivateKey which is for the leaseset encryption keys.
i2cp.leaseSetSecret0.9.39""Base 64 encoded UTF-8 secret used to blind the leaseset address. See proposal 123.
i2cp.leaseSetTransientPublicKey0.9.38[type:]b64 The base 64 of the transient private key, prefixed by an optional sig type number or name, default DSA_SHA1. See proposal 123.
i2cp.leaseSetType0.9.381,3,5,71-2551The type of leaseset to be sent in the CreateLeaseSet2 Message. Interpreted client-side, but also passed to the router in the SessionConfig, to declare intent and check support. See proposal 123.
i2cp.messageReliabilityBestEffort, 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.password0.8.2stringFor authorization, if required by the router. If the client is running in the same JVM as a router, this option is not required. Warning - username and password are sent in the clear to the router, unless using SSL (i2cp.SSL=true). Authorization is only recommended when using SSL.
i2cp.username0.8.2string
inbound.allowZeroHoptrue, falsetrueIf incoming zero hop tunnel is allowed
outbound.allowZeroHoptrue, falsetrueIf outgoing zero hop tunnel is allowed
inbound.backupQuantitynumber from 0 to 3No limit0Number of redundant fail-over for tunnels in
outbound.backupQuantitynumber from 0 to 3No limit0Number of redundant fail-over for tunnels out
inbound.IPRestrictionnumber from 0 to 40 to 42Number of IP bytes to match to determine if two routers should not be in the same tunnel. 0 to disable.
outbound.IPRestrictionnumber from 0 to 40 to 42Number of IP bytes to match to determine if two routers should not be in the same tunnel. 0 to disable.
inbound.lengthnumber from 0 to 30 to 73Length of tunnels in
outbound.lengthnumber from 0 to 30 to 73Length of tunnels out
inbound.lengthVariancenumber 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.lengthVariancenumber 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.nicknamestringName of tunnel - generally used in routerconsole, which will use the first few characters of the Base64 hash of the destination by default.
outbound.nicknamestringName of tunnel - generally ignored unless inbound.nickname is unset.
outbound.priority0.9.4number from -25 to 25-25 to 250Priority adjustment for outbound messages. Higher is higher priority.
inbound.quantitynumber from 1 to 31 to 162Number of tunnels in. Limit was increased from 6 to 16 in release 0.9; however, numbers higher than 6 are incompatible with older releases.
outbound.quantitynumber from 1 to 3No limit2Number of tunnels out
inbound.randomKey0.9.17Base 64 encoding of 32 random bytesUsed for consistent peer ordering across restarts.
outbound.randomKey0.9.17Base 64 encoding of 32 random bytes
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.
shouldBundleReplyInfo0.9.2true, falsetrueSet to false to disable ever bundling a reply LeaseSet. 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.
Примечание: высокие значения количества, длины или дисперсии могут вызвать серьёзные проблемы с производительностью или надёжностью.

Примечание: Начиная с версии 0.7.7, имена и значения параметров должны использовать кодировку UTF-8. Это в первую очередь полезно для псевдонимов. В более ранних версиях параметры с многобайтовыми символами повреждались. Поскольку параметры кодируются в Mapping , длина имён и значений параметров ограничена максимум 255 байтами (не символами).

Опции на стороне клиента

Следующие параметры интерпретируются на стороне клиента и будут обработаны, если переданы в I2PSession через вызов I2PClient.createSession(). Библиотека потоковой передачи также должна передавать эти параметры через I2CP. Другие реализации могут иметь другие значения по умолчанию.

Client-side Options
OptionAs Of ReleaseRecommended ArgumentsAllowable RangeDefaultDescription
i2cp.closeIdleTime0.7.11800000300000 minimum(ms) Idle time required (default 30 minutes)
i2cp.closeOnIdle0.7.1true, falsefalseClose I2P session when idle
i2cp.encryptLeaseSet0.7.1true, falsefalseEncrypt the lease
i2cp.fastReceive0.9.4true, falsetrueIf true, the router just sends the MessagePayload instead of sending a MessageStatus and awaiting a ReceiveMessageBegin.
i2cp.gzip0.6.5true, falsetrueGzip outbound data
i2cp.leaseSetAuthType0.9.4100-20The type of authentication for encrypted LS2. 0 for no per-client authentication (the default); 1 for DH per-client authentication; 2 for PSK per-client authentication. See proposal 123.
i2cp.leaseSetBlindedType0.9.390-65535See prop. 123The sig type of the blinded key for encrypted LS2. Default depends on the destination sig type. See proposal 123.
i2cp.leaseSetClient.dh.nnn0.9.41b64name:b64pubkeyThe base 64 of the client name (ignored, UI use only), followed by a ':', followed by the base 64 of the public key to use for DH per-client auth. nnn starts with 0. See proposal 123.
i2cp.leaseSetClient.psk.nnn0.9.41b64name:b64privkeyThe base 64 of the client name (ignored, UI use only), followed by a ':', followed by the base 64 of the private key to use for PSK per-client auth. nnn starts with 0. See proposal 123.
i2cp.leaseSetEncType0.9.3800-65535,...0The encryption type to be used, as of 0.9.38. Interpreted client-side, but also passed to the router in the SessionConfig, to declare intent and check support. As of 0.9.39, may be comma-separated values for multiple types. See also i2cp.leaseSetPrivateKey. See PublicKey in common structures spec for values. See proposals 123, 144, and 145.
i2cp.leaseSetKey0.7.1For encrypted leasesets. Base 64 SessionKey (44 characters)
i2cp.leaseSetOption.nnn0.9.66srvKey=srvValueA service record to be placed in the LeaseSet2 options. Example: "_smtp._tcp=1 86400 0 0 25 ...b32.i2p". nnn starts with 0. See proposal 167.
i2cp.leaseSetPrivateKey0.9.18Base 64 private keys for encryption. Optionally preceded by the encryption type name or number and ':'. For LS1, only one key is supported, and only "0:" or "ELGAMAL_2048:" is supported, which is the default. As of 0.9.39, for LS2, multiple keys may be comma-separated, and each key must be a different encryption type. I2CP will generate the public key from the private key. Use for persistent leaseset keys across restarts. See proposals 123, 144, and 145. See also i2cp.leaseSetEncType. Do not confuse with i2cp.leaseSetPrivKey which is for encrypted LS2.
i2cp.leaseSetSecret0.9.39""Base 64 encoded UTF-8 secret used to blind the leaseset address. See proposal 123.
i2cp.leaseSetSigningPrivateKey0.9.18Base 64 private key for signatures. Optionally preceded by the key type and ':'. DSA_SHA1 is the default. Key type must match the signature type in the destination. I2CP will generate the public key from the private key. Use for persistent leaseset keys across restarts.
i2cp.leaseSetType0.9.381,3,5,71-2551The type of leaseset to be sent in the CreateLeaseSet2 Message. Interpreted client-side, but also passed to the router in the SessionConfig, to declare intent and check support. See proposal 123.
i2cp.messageReliabilityBestEffort, NoneNoneGuaranteed is disabled; None implemented in 0.8.1; None is the default as of 0.9.4
i2cp.reduceIdleTime0.7.11200000300000 minimum(ms) Idle time required (default 20 minutes, minimum 5 minutes)
i2cp.reduceOnIdle0.7.1true, falsefalseReduce tunnel quantity when idle
i2cp.reduceQuantity0.7.111 to 51Tunnel quantity when reduced (applies to both inbound and outbound)
i2cp.SSL0.8.3true, falsefalseConnect 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.tcp.host127.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.port1-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.
Примечание: Все аргументы, включая числа, являются строками. Значения true/false — строки без учёта регистра. Любое значение, отличное от "true" (без учёта регистра), интерпретируется как false. Названия всех параметров чувствительны к регистру.

Формат данных полезной нагрузки I2CP и мультиплексирование

Сообщения с сквозным шифрованием, обрабатываемые I2CP (то есть данные, отправленные клиентом в SendMessageMessage и полученные клиентом в MessagePayloadMessage ), сжимаются с использованием стандартного 10-байтового заголовка gzip, начинающегося с 0x1F 0x8B 0x08, как указано в RFC 1952 . Начиная с версии 0.7.1, I2P использует игнорируемые части заголовка gzip для включения информации о протоколе, порте отправителя и порте получателя, что обеспечивает поддержку потоковой передачи и датаграмм на одном и том же адресате, а также надёжную работу запросов/ответов с использованием датаграмм при наличии нескольких каналов.

Функцию gzip нельзя полностью отключить, однако установка параметра i2cp.gzip=false приводит к тому, что уровень сжатия gzip устанавливается в 0, что может немного сэкономить процессорное время. Реализации могут выбирать различные уровни сжатия gzip для каждого сокета или сообщения в зависимости от оценки степени сжимаемости содержимого. Из-за сжимаемости дополнительных данных назначения, реализованной в API 0.9.57 (предложение 161), рекомендуется использовать сжатие для SYN-пакетов потоковой передачи в обоих направлениях, а также для ответных датаграмм, даже если полезная нагрузка не поддаётся сжатию. Реализациям может быть полезно написать упрощённую функцию gzip/gunzip для уровня сжатия 0, что обеспечит значительный выигрыш в эффективности по сравнению с использованием полноценной библиотеки gzip в данном случае.

BytesContent
0-2Gzip header 0x1F 0x8B 0x08
3Gzip flags
4-5I2P Source port (Gzip mtime)
6-7I2P Destination port (Gzip mtime)
8Gzip xflags (set to 2 to be indistinguishable from the Java implementation)
9I2P Protocol (6 = Streaming, 17 = Datagram, 18 = Raw Datagrams) (Gzip OS)
Примечание: номера протоколов I2P 224–254 зарезервированы для экспериментальных протоколов. Номер протокола I2P 255 зарезервирован для будущего расширения.

Целостность данных проверяется с помощью стандартной CRC-32 gzip, как указано в RFC 1952 .

Важные различия от стандартного IP

Порты I2CP предназначены для сокетов и датаграмм I2P. Они не связаны с вашими локальными сокетами или портами. Поскольку I2P не поддерживал порты и номера протоколов до выпуска 0.7.1, порты и номера протоколов в нём несколько отличаются от стандартных IP-решений, во имя обратной совместимости:

  • Порт 0 является допустимым и имеет особое значение.
  • Порты 1–1023 не являются специальными или привилегированными.
  • Серверы по умолчанию прослушивают порт 0, что означает «все порты».
  • Клиенты по умолчанию отправляют данные на порт 0, что означает «любой порт».
  • Клиенты по умолчанию отправляют данные с порта 0, что означает «неуказанный».
  • На серверах может быть сервис, прослушивающий порт 0, и другие сервисы, прослушивающие более высокие порты. В таком случае сервис на порту 0 будет использоваться по умолчанию и к нему будет установлено соединение, если входящий порт сокета или датаграммы не соответствует другому сервису.
  • На большинстве I2P-адресов работает только одна служба, поэтому вы можете использовать значения по умолчанию и игнорировать настройку портов I2CP.
  • Протокол 0 является допустимым и означает «любой протокол». Однако это не рекомендуется и, вероятно, работать не будет. Для потоковой передачи необходимо, чтобы номер протокола был установлен в 6.
  • Потоковые сокеты отслеживаются по внутреннему идентификатору соединения. Следовательно, нет необходимости в уникальности 5-кортежа dest:port:dest:port:protocol. Например, может существовать несколько сокетов с одинаковыми портами между двумя адресами. Клиентам не нужно выбирать «свободный порт» для исходящего соединения.

Будущая работа

  • Текущий механизм авторизации можно изменить для использования хешированных паролей.
  • Закрытый ключ подписи включается в сообщение Create Lease Set, хотя это не требуется. Отзыв не реализован. Следует заменить его случайными данными или удалить.
  • Некоторые улучшения могут использовать сообщения, ранее определённые, но не реализованные.

Was this page helpful?