УСТАРЕЛ, БОЛЬШЕ НЕ ПОДДЕРЖИВАЕТСЯ. Отключен по умолчанию с версии 0.9.40 2019-05. Поддержка удалена с версии 0.9.50 2021-05. Заменен на NTCP2 . NTCP это транспорт на основе Java NIO, введенный в релизе I2P 0.6.1.22. Java NIO (новый I/O) не страдает от проблем “1 поток на соединение” старого TCP транспорта. NTCP-over-IPv6 поддерживается начиная с версии 0.9.8.
По умолчанию NTCP использует IP/порт, автоматически обнаруженный SSU. Когда включено в config.jsp, SSU будет уведомлять/перезапускать NTCP при изменении внешнего адреса или статуса брандмауэра. Теперь вы можете включить входящий TCP без статического IP или службы dyndns.
Код NTCP в I2P относительно легковесный (в 4 раза меньше кода SSU), поскольку использует базовый Java TCP транспорт для надежной доставки.
Спецификация адреса router
Следующие свойства хранятся в сетевой базе данных.
- Название транспорта: NTCP
- host: IP (IPv4 или IPv6). Сокращённый IPv6-адрес (с “::”) разрешён. Имена хостов ранее были разрешены, но считаются устаревшими начиная с версии 0.9.32. См. предложение 141.
- port: 1024 - 65535
Спецификация протокола NTCP
Стандартный формат сообщений
После установления соединения транспорт NTCP отправляет отдельные сообщения I2NP с простой контрольной суммой. Нешифрованное сообщение кодируется следующим образом:
+-------+-------+-------+-------+-------+-------+-------+-------+
| sizeof(data) | |
+-------+-------+ +
| data |
~ ~
| |
+ +-------+-------+-------+
| | padding
+-------+-------+-------+-------+-------+-------+-------+-------+
| Adler checksum of sz+data+pad |
+-------+-------+-------+-------+-------+-------+-------+-------+
Затем данные шифруются с использованием AES/256/CBC. Сеансовый ключ для шифрования согласовывается во время установления соединения (используя Diffie-Hellman 2048 бит). Установление соединения между двумя router реализовано в классе EstablishState и подробно описано ниже. IV для шифрования AES/256/CBC — это последние 16 байт предыдущего зашифрованного сообщения.
Требуется 0-15 байт заполнения, чтобы общая длина сообщения (включая шесть байт размера и контрольной суммы) была кратна 16. Максимальный размер сообщения в настоящее время составляет 16 КБ. Поэтому максимальный размер данных в настоящее время составляет 16 КБ - 6, или 16378 байт. Минимальный размер данных равен 1.
Формат сообщения синхронизации времени
Особый случай — это сообщение метаданных, где sizeof(data) равен 0. В этом случае незашифрованное сообщение кодируется как:
+-------+-------+-------+-------+-------+-------+-------+-------+
| 0 | timestamp in seconds | uninterpreted
+-------+-------+-------+-------+-------+-------+-------+-------+
uninterpreted | Adler checksum of bytes 0-11 |
+-------+-------+-------+-------+-------+-------+-------+-------+
Общая длина: 16 байт. Сообщение синхронизации времени отправляется примерно каждые 15 минут. Сообщение зашифровано так же, как и стандартные сообщения.
Контрольные суммы
Стандартные сообщения и сообщения синхронизации времени используют контрольную сумму Adler-32, как определено в спецификации ZLIB .
Тайм-аут бездействия
Время ожидания простоя и закрытие соединения остается на усмотрение каждой конечной точки и может варьироваться. Текущая реализация уменьшает время ожидания по мере приближения количества соединений к настроенному максимуму и увеличивает время ожидания при низком количестве соединений. Рекомендуемое минимальное время ожидания составляет две минуты или более, а рекомендуемое максимальное время ожидания — десять минут или более.
Обмен RouterInfo
После установления соединения, а затем каждые 30-60 минут, два router должны обмениваться RouterInfo с помощью DatabaseStoreMessage. Однако Алиса должна проверить, не является ли первое сообщение в очереди DatabaseStoreMessage, чтобы не отправлять дублирующее сообщение; это часто случается при подключении к floodfill router.
Последовательность установления соединения
В состоянии установки соединения происходит 4-фазная последовательность сообщений для обмена DH ключами и подписями. В первых двух сообщениях выполняется 2048-битный обмен по алгоритму Диффи-Хеллмана. Затем обмениваются подписи критических данных для подтверждения соединения.
Alice contacts Bob
=========================================================
X+(H(X) xor Bob.identHash)----------------------------->
<----------------------------------------Y+E(H(X+Y)+tsB+padding, sk, Y[239:255])
E(sz+Alice.identity+tsA+padding+S(X+Y+Bob.identHash+tsA+tsB), sk, hX_xor_Bob.identHash[16:31])--->
<----------------------E(S(X+Y+Alice.identHash+tsA+tsB)+padding, sk, prev)
Legend:
X, Y: 256 byte DH public keys
H(): 32 byte SHA256 Hash
E(data, session key, IV): AES256 Encrypt
S(): Signature
tsA, tsB: timestamps (4 bytes, seconds since epoch)
sk: 32 byte Session key
sz: 2 byte size of Alice identity to follow
Обмен ключами DH
Первоначальный обмен ключами DH с использованием 2048-битных ключей использует те же общие простое число (p) и генератор (g), что и для шифрования ElGamal в I2P.
Обмен ключами DH состоит из нескольких шагов, показанных ниже. Соответствие между этими шагами и сообщениями, отправляемыми между I2P router’ами, выделено жирным шрифтом.
- Алиса генерирует секретное целое число x. Затем она вычисляет
X = g^x mod p. - Алиса отправляет X Бобу (Сообщение 1).
- Боб генерирует секретное целое число y. Затем он вычисляет
Y = g^y mod p. - Боб отправляет Y Алисе. (Сообщение 2)
- Алиса теперь может вычислить
sessionKey = Y^x mod p. - Боб теперь может вычислить
sessionKey = X^y mod p. - Теперь и у Алисы, и у Боба есть общий ключ
sessionKey = g^(x*y) mod p.
sessionKey затем используется для обмена идентификаторами в Сообщении 3 и Сообщении 4. Длина экспоненты (x и y) для DH обмена документирована на странице криптографии .
Подробности о ключе сессии
32-байтовый ключ сессии создается следующим образом:
- Возьмите обмененный DH ключ, представленный как массив байтов положительного BigInteger минимальной длины (дополнительный код, big-endian)
- Если самый значимый бит равен 1 (то есть array[0] & 0x80 != 0), добавьте байт 0x00 в начало, как в представлении Java BigInteger.toByteArray()
- Если этот массив байтов больше или равен 32 байтам, используйте первые (наиболее значимые) 32 байта
- Если этот массив байтов меньше 32 байтов, добавьте байты 0x00 в конец для расширения до 32 байтов. (крайне маловероятно)
Сообщение 1 (Запрос сеанса)
Это DH запрос. Алиса уже имеет Router Identity , IP-адрес и порт Боба, которые содержатся в его Router Info , опубликованной в сетевой базе данных . Алиса отправляет Бобу:
X+(H(X) xor Bob.identHash)----------------------------->
Size: 288 bytes
Содержание:
+----+----+----+----+----+----+----+----+
| X, as calculated from DH |
+ +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
| |
+ +
| HXxorHI |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
X :: 256 byte X from Diffie Hellman
HXxorHI :: SHA256 Hash(X) xored with SHA256 Hash(Bob's RouterIdentity)
(32 bytes)
Примечания:
- Боб проверяет HXxorHI используя свой собственный router hash. Если проверка не проходит, Алиса связалась не с тем router, и Боб разрывает соединение.
Сообщение 2 (Сессия создана)
Это DH ответ. Боб отправляет Алисе:
<----------------------------------------Y+E(H(X+Y)+tsB+padding, sk, Y[239:255])
Size: 304 bytes
Незашифрованное содержимое:
+----+----+----+----+----+----+----+----+
| Y as calculated from DH |
+ +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
| |
+ +
| HXY |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| tsB | padding |
+----+----+----+----+ +
| |
+----+----+----+----+----+----+----+----+
Y :: 256 byte Y from Diffie Hellman
HXY :: SHA256 Hash(X concatenated with Y)
(32 bytes)
tsB :: 4 byte timestamp (seconds since the epoch)
padding :: 12 bytes random data
Зашифрованное содержимое:
+----+----+----+----+----+----+----+----+
| Y as calculated from DH |
+ +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
| |
+ +
| encrypted data |
+ +
| |
+ +
| |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
Y: 256 byte Y from Diffie Hellman
encrypted data: 48 bytes AES encrypted using the DH session key and
the last 16 bytes of Y as the IV
Примечания:
- Алиса может разорвать соединение, если расхождение часов с Бобом слишком велико, как рассчитано с использованием tsB.
Сообщение 3 (Подтверждение сессии A)
Это содержит идентификатор router Алисы и подпись критических данных. Алиса отправляет Бобу:
E(sz+Alice.identity+tsA+padding+S(X+Y+Bob.identHash+tsA+tsB), sk, hX_xor_Bob.identHash[16:31])--->
Size: 448 bytes (typ. for 387 byte identity and DSA signature), see notes below
Незашифрованное содержимое:
+----+----+----+----+----+----+----+----+
| sz | Alice's Router Identity |
+----+----+ +
| |
~ . . . ~
| |
+ +----+----+----+
| | tsA
+----+----+----+----+----+----+----+----+
| padding |
+----+ +
| |
+----+----+----+----+----+----+----+----+
| |
+ +
| signature |
+ +
| |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
sz :: 2 byte size of Alice's router identity to follow (387+)
ident :: Alice's 387+ byte RouterIdentity
tsA :: 4 byte timestamp (seconds since the epoch)
padding :: 0-15 bytes random data
signature :: the Signature of the following concatenated data:
X, Y, Bob's RouterIdentity, tsA, tsB.
Alice signs it with the SigningPrivateKey associated with
the SigningPublicKey in her RouterIdentity
Зашифрованное содержимое:
+----+----+----+----+----+----+----+----+
| |
+ +
| encrypted data |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
encrypted data: 448 bytes AES encrypted using the DH session key and
the last 16 bytes of HXxorHI (i.e., the last 16 bytes
of message #1) as the IV
448 is the typical length, but it could be longer, see below.
Примечания:
- Боб проверяет подпись и при неудаче разрывает соединение.
- Боб может разорвать соединение, если расхождение часов с Алисой слишком велико, как рассчитано с использованием tsA.
- Алиса будет использовать последние 16 байт зашифрованного содержимого этого сообщения в качестве IV для следующего сообщения.
- До выпуска 0.9.15 router identity всегда был 387 байт, подпись всегда была 40-байтовой DSA подписью, а padding всегда был 15 байт. Начиная с выпуска 0.9.16, router identity может быть длиннее 387 байт, а тип и длина подписи подразумеваются типом Signing Public Key в Router Identity Алисы. Padding выполняется по мере необходимости до кратного 16 байт для всего незашифрованного содержимого.
- Общая длина сообщения не может быть определена без частичной расшифровки для чтения Router Identity. Поскольку минимальная длина Router Identity составляет 387 байт, а минимальная длина подписи составляет 40 (для DSA), минимальный общий размер сообщения составляет 2 + 387 + 4 + (длина подписи) + (padding до 16 байт), или 2 + 387 + 4 + 40 + 15 = 448 для DSA. Получатель мог бы прочитать это минимальное количество перед расшифровкой, чтобы определить фактическую длину Router Identity. Для небольших сертификатов в Router Identity это, вероятно, будет все сообщение, и больше не будет байт в сообщении, требующих дополнительной операции расшифровки.
Сообщение 4 (Подтверждение сессии B)
Это подпись критически важных данных. Боб отправляет Алисе:
<----------------------E(S(X+Y+Alice.identHash+tsA+tsB)+padding, sk, prev)
Size: 48 bytes (typ. for DSA signature), see notes below
Незашифрованное содержимое:
+----+----+----+----+----+----+----+----+
| |
+ +
| signature |
+ +
| |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| padding |
+----+----+----+----+----+----+----+----+
signature :: the Signature of the following concatenated data:
X, Y, Alice's RouterIdentity, tsA, tsB.
Bob signs it with the SigningPrivateKey associated with
the SigningPublicKey in his RouterIdentity
padding :: 0-15 bytes random data
Зашифрованное содержимое:
+----+----+----+----+----+----+----+----+
| |
+ +
| encrypted data |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
encrypted data: Data AES encrypted using the DH session key and
the last 16 bytes of the encrypted contents of message #2 as the IV
48 bytes for a DSA signature, may vary for other signature types
Примечания:
- Alice проверяет подпись, и при неудаче разрывает соединение.
- Bob будет использовать последние 16 байт зашифрованного содержимого этого сообщения в качестве IV для следующего сообщения.
- До релиза 0.9.15 подпись всегда была 40-байтной DSA подписью, а дополнение всегда составляло 8 байт. Начиная с релиза 0.9.16, тип и длина подписи определяются типом Signing Public Key в Router Identity Bob’а. Дополнение выполняется по мере необходимости до кратности 16 байтам для всего незашифрованного содержимого.
После установления
Соединение установлено, и могут обмениваться стандартные сообщения или сообщения синхронизации времени. Все последующие сообщения шифруются AES с использованием согласованного DH session key. Алиса будет использовать последние 16 байт зашифрованного содержимого сообщения #3 в качестве следующего IV. Боб будет использовать последние 16 байт зашифрованного содержимого сообщения #4 в качестве следующего IV.
Сообщение проверки соединения
Альтернативно, когда Боб получает соединение, это может быть проверочное соединение (возможно, инициированное тем, что Боб попросил кого-то проверить его слушателя). Check Connection в настоящее время не используется. Однако, для справки, проверочные соединения форматируются следующим образом. Информационное соединение проверки получит 256 байт, содержащих:
- 32 байта неинтерпретируемых, игнорируемых данных
- 1 байт размера
- столько байтов, составляющих IP-адрес локального router (как он достигается удаленной стороной)
- 2-байтовый номер порта, на котором был достигнут локальный router
- 4-байтовое сетевое время i2p, известное удаленной стороне (секунды с начала эпохи)
- неинтерпретируемые данные заполнения, до байта 223
- xor хеша идентификатора локального router и SHA256 байтов с 32 по 223
Проверка соединения полностью отключена начиная с релиза 0.9.12.
Обсуждение
Теперь на странице обсуждения NTCP .
Дальнейшие работы
Максимальный размер сообщения должен быть увеличен примерно до 32 КБ.
Набор фиксированных размеров пакетов может быть уместен для дальнейшего сокрытия фрагментации данных от внешних противников, но дополнения на уровне tunnel, garlic и end-to-end должно быть достаточно для большинства потребностей до тех пор. Однако, в настоящее время нет provision для дополнения за пределами следующей 16-байтовой границы, чтобы создать ограниченное количество размеров сообщений.
Использование памяти (включая память ядра) для NTCP должно сравниваться с использованием памяти для SSU.
Могут ли сообщения установления соединения быть случайным образом дополнены данными, чтобы затруднить идентификацию I2P трафика на основе размеров начальных пакетов?