Обзор
Данная спецификация документирует протокол для UDP объявлений bittorrent в I2P. Для общей спецификации bittorrent в I2P см. BitTorrent over I2P . Для справочной информации и дополнительных сведений о разработке данной спецификации см. Proposal 160 .
Дизайн
Это предложение использует repliable datagram2, repliable datagram3 и raw datagrams, как определено в Datagrams . Datagram2 и Datagram3 — это новые варианты repliable datagrams, определённые в Предложении 163 . Datagram2 добавляет защиту от повторного воспроизведения и поддержку автономных подписей. Datagram3 меньше старого формата datagram, но без аутентификации.
BEP 15
Для справки, поток сообщений, определенный в BEP 15 , выглядит следующим образом:
Client Tracker
Connect Req. ------------->
<-------------- Connect Resp.
Announce Req. ------------->
<-------------- Announce Resp.
Announce Req. ------------->
<-------------- Announce Resp.
Фаза подключения необходима для предотвращения подмены IP-адресов. Трекер возвращает идентификатор соединения, который клиент использует в последующих анонсах. Этот идентификатор соединения истекает по умолчанию через одну минуту на клиенте и через две минуты на трекере.
I2P будет использовать тот же поток сообщений, что и BEP 15, для упрощения внедрения в существующие кодовые базы клиентов с поддержкой UDP: для эффективности и по соображениям безопасности, обсуждаемым ниже:
Client Tracker
Connect Req. -------------> (Repliable Datagram2)
<-------------- Connect Resp. (Raw)
Announce Req. -------------> (Repliable Datagram3)
<-------------- Announce Resp. (Raw)
Announce Req. -------------> (Repliable Datagram3)
<-------------- Announce Resp. (Raw)
...
Это потенциально обеспечивает значительную экономию пропускной способности по сравнению с потоковыми (TCP) объявлениями. Хотя Datagram2 примерно того же размера, что и потоковый SYN, необработанный ответ намного меньше потокового SYN ACK. Последующие запросы используют Datagram3, а последующие ответы являются необработанными.
Запросы announce представляют собой Datagram3, поэтому tracker не нужно поддерживать большую таблицу соответствия ID соединений с назначениями announce или хешами. Вместо этого tracker может генерировать ID соединений криптографически на основе хеша отправителя, текущей временной метки (основанной на некотором интервале) и секретного значения. Когда получается запрос announce, tracker проверяет ID соединения, а затем использует хеш отправителя Datagram3 в качестве целевого адресата для отправки.
Время жизни соединения
BEP 15 указывает, что ID соединения истекает через одну минуту на клиенте и через две минуты на трекере. Это не настраивается. Это ограничивает потенциальные выгоды в эффективности, если только клиенты не группируют анонсы, чтобы выполнить их все в течение одноминутного окна. i2psnark в настоящее время не группирует анонсы; он распределяет их во времени, чтобы избежать всплесков трафика. Сообщается, что опытные пользователи запускают тысячи торрентов одновременно, и сжатие такого количества анонсов в одну минуту нереалистично.
Здесь мы предлагаем расширить ответ на подключение, добавив необязательное поле времени жизни соединения. По умолчанию, если не указано, это одна минута. В противном случае время жизни, указанное в секундах, должно использоваться клиентом, и трекер будет поддерживать ID соединения еще одну минуту.
Совместимость с BEP 15
Данная архитектура максимально сохраняет совместимость с BEP 15 , чтобы минимизировать изменения, необходимые в существующих клиентах и трекерах.
Единственное обязательное изменение — это формат информации о пирах в ответе announce. Добавление поля lifetime в ответе connect не является обязательным, но настоятельно рекомендуется для эффективности, как объяснено выше.
Анализ безопасности
Важной целью протокола UDP announce является предотвращение подмены адресов. Клиент должен реально существовать и содержать настоящий leaseset. У него должны быть входящие туннели для получения Connect Response. Эти туннели могут быть нулевой длины и созданы мгновенно, но это скомпрометирует создателя. Данный протокол достигает этой цели.
Проблемы
- Этот протокол не поддерживает скрытые назначения, но может быть расширен для этого. См. ниже.
Спецификация
Протоколы и порты
Repliable Datagram2 использует I2CP протокол 19; repliable Datagram3 использует I2CP протокол 20; необработанные датаграммы используют I2CP протокол 18. Запросы могут быть Datagram2 или Datagram3. Ответы всегда необработанные. Старый формат repliable datagram (“Datagram1”), использующий I2CP протокол 17, НЕ ДОЛЖЕН использоваться для запросов или ответов; они должны быть отброшены при получении на портах запроса/ответа. Обратите внимание, что протокол Datagram1 17 по-прежнему используется для DHT протокола.
Запросы используют I2CP “to port” из announce URL; см. ниже. “From port” запроса выбирается клиентом, но должен быть ненулевым и отличаться от портов, используемых DHT, чтобы ответы могли быть легко классифицированы. Трекеры должны отклонять запросы, полученные на неправильном порту.
Ответы используют “to port” из I2CP из запроса. “From port” запроса является “to port” из запроса.
URL для объявления
Формат URL для announce не указан в BEP 15
, но как и в обычной сети, UDP announce URL имеют вид udp://host:port/path. Путь игнорируется и может быть пустым, но обычно это /announce в обычной сети. Часть :port должна всегда присутствовать, однако, если часть :port опущена, используйте порт I2CP по умолчанию 6969, так как это общепринятый порт в обычной сети. Также могут быть добавлены cgi параметры &a=b&c=d, которые могут быть обработаны и предоставлены в запросе announce, см. BEP 41
. Если нет параметров или пути, завершающий / также может быть опущен, как подразумевается в BEP 41
.
Форматы датаграмм
Все значения передаются в сетевом порядке байтов (big endian). Не ожидайте, что пакеты будут точно определенного размера. Будущие расширения могут увеличить размер пакетов.
Запрос на подключение
Клиент к трекеру. 16 байт. Должен быть repliable Datagram2. То же самое, что и в BEP 15 . Без изменений.
| Offset | Size | Name | Value |
|---|---|---|---|
| 0 | 64-bit integer | protocol_id | 0x41727101980 // magic constant |
| 8 | 32-bit integer | action | 0 // connect |
| 12 | 32-bit integer | transaction_id |
Tracker к клиенту. 16 или 18 байт. Должен быть в сыром виде. То же самое, что в BEP 15 , за исключением отмеченного ниже.
| Offset | Size | Name | Value |
|---|---|---|---|
| 0 | 32-bit integer | action | 0 // connect |
| 4 | 32-bit integer | transaction_id | |
| 8 | 64-bit integer | connection_id | |
| 16 | 16-bit integer | lifetime | optional // Change from BEP 15 |
Поле lifetime является необязательным и указывает время жизни connection_id клиента в секундах. По умолчанию 60, минимальное значение при указании также 60. Максимальное значение составляет 65535 или около 18 часов. Трекер должен поддерживать connection_id на 60 секунд дольше времени жизни клиента.
Запрос объявления
Клиент к трекеру. Минимум 98 байт. Должна быть отвечаемая Datagram3. То же, что и в BEP 15 , за исключением отмеченного ниже.
connection_id — это значение, полученное в ответе на подключение.
| Offset | Size | Name | Value |
|---|---|---|---|
| 0 | 64-bit integer | connection_id | |
| 8 | 32-bit integer | action | 1 // announce |
| 12 | 32-bit integer | transaction_id | |
| 16 | 20-byte string | info_hash | |
| 36 | 20-byte string | peer_id | |
| 56 | 64-bit integer | downloaded | |
| 64 | 64-bit integer | left | |
| 72 | 64-bit integer | uploaded | |
| 80 | 32-bit integer | event | 0 // 0: none; 1: completed; 2: started; 3: stopped |
| 84 | 32-bit integer | IP address | 0 // default, unused in I2P |
| 88 | 32-bit integer | key | |
| 92 | 32-bit integer | num_want | -1 // default |
| 96 | 16-bit integer | port | // must be same as I2CP from port |
| 98 | varies | options | optional // As specified in BEP 41 |
- ключ игнорируется
- IP-адрес не используется
- порт вероятно игнорируется, но должен совпадать с портом I2CP from
- Секция опций, если присутствует, определяется как в BEP 41
Ответ ДОЛЖЕН быть отправлен на I2CP “to port”, который был получен как “from port” запроса. Не используйте порт из запроса announce.
Ответ на объявление
Tracker к клиенту. Минимум 20 байт. Должно быть в raw формате. То же самое, что в BEP 15 , за исключением отмеченного ниже.
| Offset | Size | Name | Value |
|---|---|---|---|
| 0 | 32-bit integer | action | 1 // announce |
| 4 | 32-bit integer | transaction_id | |
| 8 | 32-bit integer | interval | |
| 12 | 32-bit integer | leechers | |
| 16 | 32-bit integer | seeders | |
| 20 | 32 * n 32-byte hash | binary hashes | // Change from BEP 15 |
- Вместо 6-байтового IPv4+порт или 18-байтового IPv6+порт, мы возвращаем кратное 32-байтовым “компактным ответам” с двоичными SHA-256 хешами узлов. Как и в случае с TCP компактными ответами, мы не включаем порт.
Ответ ДОЛЖЕН быть отправлен на I2CP “to port”, который был получен как “from port” запроса. Не используйте порт из запроса объявления.
I2P датаграммы имеют очень большой максимальный размер около 64 КБ; однако для надежной доставки следует избегать датаграмм размером больше 4 КБ. Для эффективности пропускной способности трекеры должны вероятно ограничивать максимальное количество peers примерно до 50, что соответствует пакету размером около 1600 байт до накладных расходов на различных уровнях, и должно укладываться в лимит полезной нагрузки двух tunnel сообщений после фрагментации.
Как и в BEP 15, здесь не включается счетчик количества адресов пиров (IP/порт для BEP 15, хеши здесь), которые следуют далее. Хотя это не предусмотрено в BEP 15, можно определить маркер конца пиров из всех нулей, чтобы указать, что информация о пирах завершена и далее следуют некоторые данные расширения.
Чтобы расширение было возможно в будущем, клиенты должны игнорировать 32-байтовый хеш из всех нулей и любые данные, следующие за ним. Трекеры должны отклонять анонсы с хешем из всех нулей, хотя такой хеш уже заблокирован Java router’ами.
Парсинг
Запрос/ответ scrape из BEP 15 не требуется данной спецификацией, но может быть реализован при желании, изменения не требуются. Клиент должен сначала получить идентификатор соединения. Запрос scrape всегда является repliable Datagram3. Ответ scrape всегда в raw формате.
Ответ с ошибкой
Tracker к клиенту. Минимум 8 байт (если сообщение пустое). Должен быть необработанным. То же самое, что и в BEP 15 . Без изменений.
| Offset | Size | Name | Value |
|---|---|---|---|
| 0 | 32-bit integer | action | 3 // error |
| 4 | 32-bit integer | transaction_id | |
| 8 | string | message |
Биты расширения или поле версии не включены. Клиенты и трекеры не должны предполагать, что пакеты имеют определенный размер. Таким образом, дополнительные поля могут быть добавлены без нарушения совместимости. Если требуется, рекомендуется формат расширений, определенный в BEP 41 .
Ответ подключения изменен для добавления необязательного времени жизни идентификатора соединения.
Если требуется поддержка blinded destination (скрытых назначений), мы можем либо добавить blinded 35-байтовый адрес в конец запроса announce, либо запросить blinded хеши в ответах, используя формат BEP 41 (параметры будут определены позже). Набор blinded 35-байтовых адресов узлов может быть добавлен в конец ответа announce после 32-байтового хеша из нулей.
Руководство по реализации
Смотрите раздел о дизайне выше для обсуждения проблем неинтегрированных клиентов и трекеров, не использующих I2CP.
Клиенты
Для данного имени хоста трекера клиент должен предпочитать UDP вместо HTTP URLs и не должен объявлять себя на обоих.
Клиенты с существующей поддержкой BEP 15 должны требовать только незначительных модификаций.
Если клиент поддерживает DHT или другие протоколы датаграмм, он должен вероятно выбрать другой порт в качестве “порта отправителя” запроса, чтобы ответы приходили на этот порт и не смешивались с сообщениями DHT. Клиент получает только необработанные датаграммы в качестве ответов. Трекеры никогда не отправят repliable datagram2 клиенту.
Клиенты со списком opentrackers по умолчанию должны обновить список, добавив UDP URL после того, как станет известно, что известные opentrackers поддерживают UDP.
Клиенты могут реализовывать или не реализовывать повторную передачу запросов. Повторные передачи, если они реализованы, должны использовать начальный таймаут не менее 15 секунд и удваивать таймаут для каждой повторной передачи (экспоненциальная задержка).
Клиенты должны делать откат после получения ответа с ошибкой.
Трекеры
Tracker’ы с существующей поддержкой BEP 15 должны требовать лишь небольших модификаций. Данная спецификация отличается от предложения 2014 года тем, что tracker должен поддерживать прием repliable datagram2 и datagram3 на том же порту.
Чтобы минимизировать требования к ресурсам tracker’а, этот протокол разработан для исключения любых требований к tracker’у хранить сопоставления хешей клиентов с идентификаторами соединений для последующей проверки. Это возможно, поскольку пакет запроса announce является отвечаемым пакетом Datagram3, поэтому он содержит хеш отправителя.
Рекомендуемая реализация:
- Определить текущую эпоху как текущее время с разрешением времени жизни соединения,
epoch = now / lifetime. - Определить криптографическую хеш-функцию
H(secret, clienthash, epoch), которая генерирует 8-байтовый выход. - Сгенерировать случайную константу secret, используемую для всех соединений.
- Для ответов на подключение генерировать
connection_id = H(secret, clienthash, epoch) - Для запросов announce валидировать полученный connection ID в текущей эпохе путем проверки
connection_id == H(secret, clienthash, epoch) || connection_id == H(secret, clienthash, epoch - 1)
Справочные материалы
- [BEP15] BEP 15 - Протокол UDP Tracker
- [BEP41] BEP 41 - Расширения протокола UDP Tracker
- [DATAGRAMS] Спецификация датаграмм
- [Prop160] Предложение 160 - UDP Tracker’ы
- [Prop163] Предложение 163 - Datagram2/Datagram3
- [SAMv3] SAM v3 API
- [SPEC] BitTorrent поверх I2P