6.16 Стек протоколов I2P и немного о TOR
Семенов Ю.А. (ГНЦ ИТЭФ)
В последнее время в связи с тем, что многие тоталитарные государства вводят активную фильтрация запросов, появились программные средства, препятствующие такой фильтрации (TOR и I2P). Впрочем, вполне возможно, что дело идет к тому, что весь Интернет со временем перейдет на работу через прокси с шифрованием всего трафика.
I2P (Invisible Internet Project) представляет собой масштабируемый, самоорганизующийся анонимный сетевой уровень, поверх которого могут работать различные приложения, предназначенные для обеспечения анонимности и секретности. Доступные на сегодня приложения могут обеспечить весь диапазон операций Интернет: анонимный просмотр WEB-страниц, WEB-хостинг, чаты, совместное использование файлов, блоггинг, и т.д. См. http://www.i2p2.de/protocols.html.
В отличие от WEB-сайтов, размещенных в сетях с распределенным содержимым (Freenet или GNUnet), сервисы I2P являются полностью интерактивными – там имеется традиционные системы WEB-поиска, доски объявлений, блоги, где вы можете оставлять свои комментарии, сайты, управляемые базами данных, и ретрансляторы для запросов в системы типа Freenet без необходимости локальной инсталляции. По существу I2P представляет собой маршрутизатор сообщений. На рис. 1 представлена схема стека протоколов I2P..
I2CP | (I2P Client Protocol) Протокол управления I2P |
NTCP | (NIO-базирующийся TCP). NTCP является одним из двух видов транспорта, используемым в I2P. NTCP представляет собой транспорт, базирующийся на NIO (new I/O). |
SSU | Secure Semireliable UDP (один из транспортных протоколов I2P) |
I2NP | I2P Network Protocol |
Рис. 1. Слои стека сети I2P
Клиентский протокол I2P (I2CP) демонстрирует глубокое различие между маршрутизатором и любым клиентом, который хочет работать через сеть . Протокол обеспечивает безопасный и асинхронный обмен сообщениями посредством одного ТСР-сокета. При этом не раскрываются никакие секретные ключи, а аутентификация производится с помощью подписей . Посредством I2CP приложение клиента сообщает маршрутизатору, что оно из себя представляет, какая анонимность, надежность и задержки допустимы, и куда нужно посылать сообщения. В свою очередь маршрутизатор использует I2CP, чтобы сообщить клиенту, когда сообщение пришло и запрашивает авторизации для некоторых туннелей. В стандартной реализации I2P для работы с внешнего клиента с локальным маршрутизатором в рамках протокола I2CP используется порт 7654 .
За счет всех средств анонимности, I2P выполняет посредническую функцию, ориентированную на передачу сообщений – приложения сообщают, что они хотят послать некоторые данные криптографическому идентификатору (назначению) и I2P берет на себя функцию доставки этих данных скрытно и анонимно. I2P содержит в себе обширную библиотеку для работы с потоками данных, что позволяет передать I2P-сообщения в виде прозрачного, упорядоченного потока. При этом реализуется ТСР-механизм подавления перегрузки. В работе I2P для объединения приложений в сеть используется несколько SOCKS-прокси..
Потоковая библиотека I2P может рассматриваться как потоковый интерфейс (зеркалируя TCP-сокеты), который осуществляет поддержку протокола скользящего окна с несколькими оптимизациями, учитывающими большие задержки I2P.
Малые HTTP-транзакции, проксированные с помощью потоковой библиотеки, могут быть завершены за один RTT-период – первое сообщение объединяет в себе SYN, FIN и небольшое поле данных (что обычно достаточно для HTTP-запроса), а отклик объединяет в себе SYN, FIN, ACK и небольшое поле данных (что пригодно для многих HTTP-откликов). В случае когда необходим дополнительный отклик, чтобы уведомить HTTP-сервер о получении SYN/FIN/ACK, локальный HTTP-прокси может прислать браузеру сразу полный отклик.
Вообще потоковая библиотека имеет большое сходство с традиционной моделью TCP, с алгоритмами скользящего окна и управления перегрузкой (режимы медленного старта и исключения перегрузки), и стандартным набором флагов (ACK, SYN, FIN, RST и т.д.).
Протокол I2P не является исследовательским проектом - академическим, коммерческим или правительственным, это просто инженерная разработка, имеющая целью обеспечения достаточного уровня анонимности для тех, кто нуждается в этом. Эта технология начала разрабатываться с начала 2003.
Работа над I2P выполнялась в рамках проекта по программам с открытым кодом. Существует несколько приложений I2P с лицензией GPL (I2PТуннель, susimail, I2PSnark, I2P-Bote, I2Phex и др.).
Чтобы понять работу I2P, важно учесть несколько ключевых моментов. Во-первых, I2P делает четкое различие между программами, вовлеченными в работу сети (маршрутизаторами) и анонимными конечными системами ("местами назначения"), ассоциируемыми с индивидуальными приложениями. Факт работы с I2P не является секретом. Скрытой является информация, которую пользователь запрашивает в сети, и откуда эта информация берется. Конечные пользователи обычно имеют несколько локальных адресов в своем маршрутизаторе – например, один для прокси IRC-серверов, другой поддерживает анонимный WEB-сервер пользователя ("eepsite"; порт=4444), один - для I2Phex, еще один - для торрентов и т.д..
Еще одним важным аспектом технологии является "туннель". Туннель представляет собой ориентированный проход через явно заданный список маршрутизаторов. При этом используется послойная криптография, так что маршрутизатор может дешифровать только один слой. Дешифрованная информация включает в себя IP-адрес следующего маршрутизатора, и зашифрованную информацию, которую нужно переадресовать. Каждый туннель имеет начало (первый маршрутизатор, называемый "шлюзом" (gateway)) и конечную точку. Сообщения могут посылаться только в одном направлении. Чтобы послать сообщение в обратном направлении, нужен другой туннель.
Рис. 2. Два типа туннелей: входящие (inbound) и исходящие (outbound).
Существует два типа туннелей: "входящие" туннели посылают сообщения от создателя туннеля, в то время как "исходящие" туннели доставляют сообщения создателю туннеля. Комбинируя два таких туннеля, пользователи могут посылать сообщения друг другу. Отправитель ("Алиса" на рисунке выше) формирует исходящий туннель, в то время как получатель ("Боб" на рисунке выше) формирует входящий туннель. Шлюз входящего туннеля может получать сообщения от любого пользователя и посылать сообщения Бобу. Оконечная точка исходящего туннеля будет нужна для посылки сообщения шлюзу входящего туннеля. Чтобы осуществить это, отправитель ("Алиса") добавляет инструкции к своему зашифрованному сообщению. Когда в конечной точке исходящего туннеля сообщение дешифруется, получаются инструкции переадресации сообщения нужному шлюзу входящего туннеля (шлюзу "Боба").
Третьим принципиальным моментом I2P является "сетевая база данных" (или "netDb") –служащая для хранения и совместного использования сетевых метаданных. Имеется два типа метаданных "routerInfo" и "leaseSets", которые подписываются одним из партнеров и верифицируется другим. - RouterInfo предоставляет маршрутизаторам информацию, необходимую для взаимодействия с определенным маршрутизатором (их общедоступные ключи, транспортные адреса и т.д.), а leaseSet предоставляет маршрутизаторам данные, необходимые для контакта с определенными объектами места назначения. leaseSet содержит некоторое число "leases". Каждый из этих lease специфицирует шлюз туннеля, который позволяет достичь специфицированного места назначения. В lease содержится следующая информация:
Сами маршрутизаторы посылают свою routerInfo в netDb непосредственно, в то время как leaseSets посылаются через исходящий туннель (leaseSets должны посылаться анонимно, чтобы избежать корреляции маршрутизатора с его leaseSets).
Чтобы сформировать свой собственный внутренний и внешний туннели, Алиса заглядывает в netDb, чтобы получить routerInfo. Таким образом, она формирует список партнеров, которые она может использовать в качестве шагов туннелей. Она может затем послать сформированное сообщение по первому этапу, запрашивая формирование туннеля и, прося этот маршрутизатор прислать после этого сообщение формирования, пока туннель не будет создан.
Рис. 3. Для построения туннелей используются данные маршрутизатора
Когда Алиса хочет послать сообщение Бобу, она сначала должна заглянуть в netDb, чтобы найти leaseSet Боба, выдавая ей его шлюз текущего входящего туннеля. Затем она берет один из ее исходящих туннелей и посылает сообщение с инструкциями для исходящего туннеля, чтобы переадресовать сообщение на шлюз входного туннеля Боба. Когда получатель принимает эти инструкции, он переадресует сообщение в соответствии с запросом, и когда шлюз входящего туннеля Боба получает сообщение, он переадресует его маршрутизатору Боба. Если Алиса хочет, чтобы Боб мог ответить на сообщение, она должна переслать свой адрес в рамках этого сообщения. Это может быть сделано путем введения более высокого уровня, реализуемого в потоковой библиотеке. Алиса может уменьшить время отклика путем введения своего последнего leaseSet в сообщение, так что Бобу будет ненужно обращаться в netDb перед отправкой отклика, но эта операция является опционной.
Рис. 4. Наборы Leaseset используются для соединения входящих и исходящих туннелей
В то время как сами туннели должны использовать криптографию, чтобы исключить неавторизованное раскрытие имени партнера в сети, необходимо добавить еще один уровень между конечными точками для криптозащиты сообщения в шлюзе конечной точки исходящего и входящего туннелей. Этот метод называется "garlic encryption" (чесночное шифрование). Пусть маршрутизатор Алисы помещает несколько сообщений в одно "чесночное сообщение", зашифрованное определенным общедоступным ключом, так что партнеры не могут сразу определить, сколько там сообщений, что в этих сообщениях или где находятся партнеры. Для стандартных коммуникаций точка-точка между Алисой и Бобом, garlic будет зашифрован с помощью общедоступного ключа, опубликованного в leaseSet Боба, что позволяет зашифровать сообщение, не раскрывая общедоступного ключа маршрутизатору Боба.
Еще один важный факт, который следует иметь в виду, заключается в том, что I2P полностью базируется на сообщениях и что некоторые сообщения могут быть потеряны. Приложения, использующие I2P, могут применять интерфейс, базирующийся на сообщениях и сами заботиться об управлении перегрузкой.
Как входящие, так и исходящие туннели работают на аналогичных принципах. Шлюз туннеля аккумулирует некоторое количество сообщений, опционно предварительно их преобразует для последующей передачи через туннель. Далее, шлюз шифрует переработанные данные и переадресует сообщение на следующий этап. Этот партнер и последующие участники туннеля добавляются на уровне шифрования, после чего осуществляется переадресация сообщения на следующий этап. В конце концов, сообщение приходит адресату, где сообщения снова разделяются и переадресуются, куда следует. Различие возникает в том, что делает создатель туннеля – для входящих туннелей создателем является конечная точка, и они дешифруют все добавленные уровни, в то время как для исходящих туннелей, создателем является шлюз и они шифруют все слои, так что в конце концов добавляются слои с индивидуальным шифрованием для каждого из этапов, сообщение прибывает в место назначения туннеля незашифрованным.
В то время как сетевая база данных имеет свои собственные критерии для выбора партнеров, создатели туннелей могут использовать любых партнеров в сети в любом порядке (и даже любое их число) в одном туннеле.
С точки зрения перспективы анонимности, простейшая методика - произвольный выбор партнеров в сети, расположение их произвольно и использование их на постоянной основе. С точки зрения рабочих характеристик простейшая методика - выбор наиболее быстрого партнера с необходимой резервной емкостью, распределение нагрузки между несколькими партнерами, что обеспечивает переход на резервный маршрут при отказе основного. Туннель перестраивается, если изменяется информация о ресурсах каналов. I2P предоставляет набор стратегий выбора партнеров в сочетании с анонимностью.
I2P постоянно отслеживает профайлы партнеров, с которыми взаимодействуют - например, когда партнер реагирует на запрос netDb за 1.3 секунды, эта задержка записывается в профайлы всех маршрутизаторов, вовлеченных во входящий и исходящий туннели, через которые проходят запрос и отклик. Прямое измерение, такое как на транспортном уровне или при перегрузке, не используется, так как здесь возможны манипуляции, а также выявление измеряющего маршрутизатора, с последующими тривиальными атаками. В процессе сбора данных этих профайлов производится ряд вычислений, чтобы охарактеризовать рабочие параметры объекта – его задержку, пропускную способность, уровень перегрузки и т.д.. Эти вычисления затем сравниваются для активных партнеров, чтобы рассортировать маршрутизаторы на четыре группы – быстрые с большой полосой пропускания, с высокой пропускной способностью, устойчивые и нестабильные. Пороги для групп определяются динамически.
Используя данные профайла, реализуется простейшая стратегия выбора партнеров, начиная с верха списка (быстрые с большой полосой пропускания). Исследовательские туннели (используемые для netDb и управления туннелем) выбирают партнеров случайным образом из группы устойчивых (куда входят маршрутизаторы), что позволяет более широкий выбор партнеров. Такие стратегии сами по себе допускают утечку информации, сопряженной с маршрутизаторами высшей группы через предшественников и netDb, что может привести к атакам.
Путем выбора произвольного ключа и упорядочения партнеров по XOR-расстоянию от него, количество утекающей информации через предшественников уменьшается. Другой простой стратегией понижения возможности атак через netDb является дальнейшая рэндомизация партнеров в туннеле. Более жесткой стратегией является явная фиксация партнеров и упорядочение в туннеле, используя только индивидуальных партеров, если они все согласны выполнять свои функции всегда и в любое время. Это отличается от упорядочения на основе XOR, где предшественник и последователь каждого партнера всегда один и тот же. XOR-техника гарантирует неизменность порядка партнеров.
Как было упомянуто выше, I2P сейчас (версия 0.8) включает в себя послойную стратегию случайного выбора, с упорядочением на основе процедур XOR.
I2P netDb служит для обеспечения доступа к сетевым метаданным. База данных netDb распределена с помощью техники, называемой "floodfill", где субнабор всех маршрутизаторов, названный "floodfill марштутизаторы", содержит распределенную базу данных.
Некоторая доля I2P-пользователей объявляются 'floodfill-партнерами'. В настоящее время I2P-инсталляции, которые имеют большую полосу и высокое быстродействие, объявляют себя floodfill, если число имеющихся floodfill-маршрутизаторов становится малым.
Большинство I2P-маршрутизаторов записывают свои данные и извлекают их путем посылки запросов 'store' и 'lookup' узлам floodfill. Если floodfill-маршрутизатор получает запрос 'store', он передает информацию другим floodfill-маршрутизаторам с использованием алгоритма Kademlia (распределенная хэш таблица для децентрализованных P2P сетей). Запросы 'lookup' реализуются иначе, для этой цели посылается в netdb I2NP DatabaseLookupMessage, чтобы получить нужные данные из floodfill маршрутизатора. При рлступлении запроса floodfill-маршрутизатор не переадресует его другим партнерам, а всегда выполняет сам (если имеет запрашиваемые данные).
В сетевой базе данных хранятся два типа данных.
Вся эта информация подписана субъектом, который ее выдал и верифицируется любым I2P-маршрутизатором использующим или записывающим эти данные. Кроме того, данные несут временную информацию, чтобы исключить запись старых записей и возможные атаки.
Кто-то может захотеть разрешить определенным людям доступ к определенному месту назначения. Это возможно, если не публиковать место назначения в netDb. Вы будете, однако должны передать место назначения другими средствами. Альтернативой является 'зашифрованный leaseSet'. Эти наборы могут быть дешифрованы субъектами, имеющими доступ к соответствующему ключу.
Начальная загрузка netDb достаточно проста. Раз маршрутизатор может получать routerInfo доступного партнера, он может запросить, ссылки для других маршрутизаторов в сети. В настоящее время определенное число пользователей, выставляет свои routerInfo-файлы на вебсайте, чтобы сделать эту информацию доступной. I2P автоматически подключается к одному из этих вебсайтов, чтобы собрать вместе файлы routerInfo и осуществить стартовую загрузку.
Запросы Lookup I2P-сети не переадресуются другим netDb-маршрутизаторам. Сейчас это несущественно, так как сеть невелика. Однако, по мере роста сети, не все файлы routerInfo и leaseSet будут присутствовать на каждом netDb-маршрутизаторе. Это вызовет ухудшение процента успешных запросов lookup. По этой причине, совершенствование netDb будет осуществлено в последующих версиях.
Коммуникации между маршрутизаторами нуждаются в обеспечении конфиденциальности и целостности по отношению внешних врагов при аутентификации. Детали того, как общаются маршрутизаторы между собой, не являются критическими – три разных протокола используются в разных точках, чтобы решить эти проблемы.
I2P эволюционировал от транспорта, базирующегося на TCP, к UDP-based - "Secure Semireliable UDP", или "SSU".
Целью данного протокола является обеспечение безопасной, аутентифицированной, неупорядоченной доставки с минимальным доступом к данным третей стороны. Он должен поддерживать высокий уровень коммуникаций, а также управление перегрузкой TCP-типа, и может включать в себя PMTU-детектирование (Path MTU). Он должен быть способен передавать большие объемы данных при скоростях, достаточных для домашних пользователей. Кроме того, он должен поддерживать системы оперирования типа NAT или firewall.
Внедряется новая техника ТСР-транспорта на основе NIO (New I/O), называемая NTCP. Она предполагается по умолчанию для исходящих соединений. Те, кто конфигурирует свой NAT/firewall с возможностью входных соединений и специфицирует внешний компьютер и порт в /config.jsp может осуществить и входящие соединения.
NTCP является одним из двух видов транспорта, используемым в I2P. Другим из этих двух является SSU. NTCP представляет собой транспорт, базирующийся на NIO и введенный в I2P в версии 0.6.1.22. Java NIO (new I/O) не имеет ограничения на число тредов на одно соединение, присущего TCP-транспорту.
По умолчанию, NTCP использует пару IP/порт, автоматически детектируемых SSU. Когда это разрешено config.jsp, SSU запрашивает/перезапускает NTCP при изменении адреса или статуса firewall. Теперь вы можете разрешить входное TCP без статического IP или динамического DNS-сервиса.
Программа NTCP в I2P относительно проста, так как использует для надежной доставки Java TCP транспорт.
После установления, NTCP-транспорт посылает индивидуальные I2NP сообщения, с простой контрольной суммой. Незашифрованное сообщение имеет следующий формат:
Рис. 5. Формат стандартного сообщения
Данные шифруются с использованием алгоритмов AES/256/CBC. Ключ сессии для шифрования согласуется в процессе установления соединения (с использованием алгоритма Диффи-Хелмана с 2048 битами). Установление соединения между двумя маршрутизаторами реализуется в классе EstablishState. Вектор IV для шифрования AES/256/CBC записывается в последних 16 байтах предшествующего зашифрованного сообщения.
Необходимы 0-15 байтов заполнителя, чтобы довести полную длину сообщения (включая байты размера и контрольной суммы) до значения, кратного 16. Максимальный размер сообщения в настоящее время равен 16 Kбайт. Следовательно, максимальный размер поля данных равен 16 Kбайт - 6, или 16378 байт. Минимальный размер = 1.
Специальным случаем является сообщение метаданных, где в поле размера данных записывается 0. В этом случае незашифрованное сообщение выглядит следующим образом:
Рис. 6.
Полная длина: 16 байт. Сообщение time sync посылается примерно каждые 15 минут. Сообщение шифруется как стандартное сообщение.
Стандартное сообщение и сообщения time sync используют контрольную сумму Adler-32, как это определено в http://tools.ietf.org/html/rfc1950.
Для установления соединения производится 4-фазный обмен DH ключами и подписями. В первых двух сообщениях реализуется обмен согласно 2048-битному алгоритму Диффи-Хелмана. Затем производится обмен, DSA-подписями критических данных, чтобы подтвердить соединение.
Алиса контакты Боб ========================================================= X+(H(X) xor Bob.identHash)-----------------------------> <----------------------------------------Y+E(H(X+Y)+tsB+заполнитель, sk, Y[239:255]) E(sz+Alice.identity+tsA+ заполнитель +S(X+Y+Bob.identHash+tsA+tsB), sk, hX_xor_Bob.identHash[16:31])---> <----------------------E(S(X+Y+Alice.identHash+tsA+tsB)+заполнитель, sk, prev)
Обозначения:
X, Y: 256 байта DH общедоступные ключи
H(): 32 байта хэша SHA256
E(данные, ключ сессии, IV): зашифровано AES256
S(): 40 байт DSA-подпись
tsA, tsB: временные метки (4 байта, секунд с начала эпохи)
sk: 32 байтный ключ сессии
sz: 2 байта размера идентификатора Алисы (который следует далее)
Исходный 2048-битовый ключевой DH-обмен использует тот же исходный код р (prime) и генератор g, что и в случае I2P кодирования с привлечением алгоритма Эль-Гамаля.
Ключевой DH обмен реализуется в несколько этапов, представленных ниже. Сообщения, пересылаемые между I2P-маршрутизаторами, выделены жирным шрифтом.
SessionKey затем используется для обмена идентификаторами в Сообщении 3 и Сообщении 4.
Это DH-запрос. Алиса уже имеет идентификатор маршрутизатора Боба, IP адрес и порт, содержащиеся в Router Info, которая была опубликована в сетевой базе данных. Алиса посылает Бобу:
X+(H(X) xor Bob.identHash)----------------------------->
Размер: 288 байт
Содержимое: Х за которым сразу следует HX xor HI.
X: 256 байт X от Диффи Хелмана
HXxorHI: SHA256 хэш(X) xor с SHA256 Хэш(идентификатор маршрутизатора Боба)
(32 байта)
Это DH-отклик. Боб посылает Алисе
<----------------------------------------Y+E(H(X+Y)+tsB+заполнитель, sk, Y[239:255])
Размер: 304 байта
Незашифрованное содержимое имеет формат:
Рис. 7. Формат сообщения DH-отклик
Y: 256 байт Y из алгоритма Диффи Хелмана
HXY: SHA256 Хэш(X объединен с Y) (32 байта)
tsB: 4 байтная временная метка (секунды с начала эпохи)
Заполнитель: 12 байт произвольных данных
Зашифрованное содержимое: Сначала следует Y, вычисленное на основе DH, за ним непосредственно располагаются зашифрованные данные.
Y: 256 байт Y от Диффи Хелмана
Зашифрованные данные: 48 байт зашифрованные AES с использованием ключа сессии DH и последние 16 байт Y в качестве IV (Initialization Vector).
Это сообщение содержит идентификатор маршрутизатора Алисы и DSA подпись критических данных. Алиса посылает Бобу:
E(sz+Alice.identity+tsA+padding+S(X+Y+Bob.identHash+tsA+tsB), sk, hX_xor_Bob.identHash[16:31])--->
Размер: 448 байт (для 387 байтного идентификатора)
Незашифрованное содержимое:
Рис. 8. Формат сообщения подтверждения
sz: 2 байта размера идентификатора маршрутизатора Алисы, который следует далее (должно быть всегда 387)
ident: 387-байтный идентификатор маршрутизатора Алисы
tsA: 4 байта временной метки (число секунд с начала эпохи)
Заполнитель: 15 байт произвольных данных
Подпись: 40-байтная DSA-подпись следующих ниже объединенных данных:
X, Y, идентификатор маршрутизатора Боба, tsA, tsB.
Алиса подписывает это секретным ключом, сопряженным с общедоступным ключом в ее идентификаторе маршрутизатора.
Зашифрованные данные: 448 байтов зашифрованных AES с использованием ключа сессии DH и последними 16 байт HXxorHI в качестве IV (т.e., последние 16 байт сообщения #1)
Это DSA-подпись критических данных. Боб посылает Алисе:
<----------------------E(S(X+Y+Alice.identHash+tsA+tsB)+заполнитель, sk, prev)
Размер: 48 байтов
Незашифрованное содержимое: Сначала следует подпись, за которой может располагаться заполнитель.
Подпись: 40-байтоваяDSA-подпись следующих ниже объединенных данных:
X, Y, Alice's Router Identity, tsA, tsB.
Боб подписывает это с помощью секретного ключа, соответствующего общедоступному ключу в его идентификаторе маршрутизатора.
Заполнитель: 8 байт произвольных данных
Зашифрованные данные: 48 байт зашифрованных AES с использованием ключа сессии DH, а последние 16 байт зашифрованных данных сообщения #2 служат в качестве IV.
Соединение установлено, и обмен стандартными или синхронизирующими сообщениями можно начинать. Все последующие сообщения зашифрованы AES с использованием согласованного ключа сессии DH. Алиса будет использовать последние 16 байт зашифрованного сообщения #3 в качестве следующего IV. Боб будет использовать последние 16 байт зашифрованного сообщения #4 в качестве следующего IV.
Когда Боб установил соединение, оно может быть протестировано (возможно Боба может кто-то попросить, проверить одного из своих контактеров). Тестирование может быть выполнено следующим способом. Тестовые данные включают в себя 256 байтов, содержащих:
I2P поддерживает несколько обменов одновременно. Определенный транспорт для исходящего соединения выбирается посредством заявок (“bids”). Каждая транспортная заявка на соединение и относительные значения этих заявок определяют приоритет заявки.
Текущая реализация позиционирует NTCP в большинстве ситуаций как высокоприоритетный транспорт для исходящих соединений. SSU допустимо, как для исходящих, так и для входящих соединений. Ваш firewall и ваш I2P-маршрутизатор должен быть сконфигурирован так, чтобы позволять входящие NTCP-соединения.
Для обеспечения многослойной безопасности I2P минимальный набор криптографических примитивов объединяются с тем, чтобы противостоять различным угрозам. На самом нижнем уровне, внутри маршрутизаторные коммуникации защищены средствами транспортного уровня - SSU шифрует каждый пакет с помощью AES256/CBC с использованием как IV (Initialization Vector) так и MAC (HMAC-MD5-128) после согласования ключа сессии с помощью 2048-битового обмена в рамках алгоритма Диффи-Хелмана. Аутентификация станция-станция выполняется с привлечением ключа DSA, плюс каждое сетевое сообщение имеет свой собственный хэш для проверки локальной целостности. Туннельные сообщения имеют свой собственный уровень криптозащиты (AES256/CBC). Различные прочие сообщения передаются в "garlic-сообщениях", которые шифруются с привлечением алгоритмов Эль-Гамаля/AES+метки сессии (SessionTags).
Сообщения Garlic являются расширением "onion"-слоя шифрования (см. протокол TOR), позволяя отдельным сообщениям содержать в себе несколько секций ("cloves") –сообщений со своими инструкциями по доставке. Сообщения объединяются в garlic-сообщение всякий раз, когда сообщение может быть передано через партнера открытым текстом, а его доступ к данным нежелателен. - например, когда маршрутизатор хочет запросить другой маршрутизатор участвовать в туннеле. Другим примером может быть случай, когда клиент хочет послать сообщение адресату – маршрутизатор отправителя вкладывает это информационное сообщение в garlic, шифрует этот garlic с привлечением 2048-битового общедоступного ключа Эль-Гамаля, опубликованного в leaseSet получателя, и переадресует его через соответствующий туннель.
"Инструкции", присоединенные к каждой секции внутри крипто-слоя, включают возможность запросить локальную переадресацию секций удаленному маршрутизатору, или удаленному туннелю. Существуют поля в этих инструкциях, позволяющие партнеру запрашивать задержку доставки до определенного времени или выполнение определенных условий. Имеется возможность явно маршрутизовать garlic-сообщения через любое число этапов без построения туннелей, или даже перемаршрутизовать туннельные сообщения, вставляя их в garlic-сообщения и переадресуя их через некоторое число этапов, прежде чем направлять следующему узлу туннеля, но эти методики в настоящее время в существующих реализациях не используются.
Для обеспечения конфиденциальности и целостности garlic-сообщений I2P использует простую комбинацию асимметричных и симметричных крипто алгоритмов. В целом комбинация включает в себя ElGamal/AES+метки сессий, но это многословный способ описать простое использование 2048-битового алгоритма ElGamal, AES256, SHA256 и 32 байтового защитного кода (nonce).
Когда маршрутизатор хочет зашифровать garlic-сообщение, адресованное другому маршрутизатору в первый раз, он шифруют ключевой материал для ключа сессии AES256 с привлечением алгоритма ElGamal и присоединяет данные, зашифрованные посредством AES256/CBC, сразу вслед за блоком кодов ElGamal. Кроме зашифрованного поля данных, зашифрованная AES секция содержит длину поля данных, SHA256-хэш незашифрованных данных, а также несколько меток сессии - случайных 32-битовых кодов защиты (nonce). В следующий раз, когда отправитель захочет зашифровать garlic-сообщение, другому маршрутизатору, вместо того чтобы ElGamal-шифровать новый ключ сессии, они просто берут одну из доставленных раннее меток сессии и шифруют с помощью AES поле данных, используя ключ сессии с меткой сессии. Когда маршрутизатор получает зашифрованное garlic-сообщение, он проверяет первые 32 байта, чтобы посмотреть, соответствует ли это доступной метке сессии – если это так, он просто дешифрует сообщение с помощью AES, но если это не так, он дешифрует с помощью ElGamal первый блок данных.
Каждая метка сессии может быть использована только один раз. Отправитель сообщения, шифрованного ElGamal/AES+SessionTag выбирает, когда и как доставлять метки, предоставляя получателю достаточно меток, чтобы покрыть поток сообщений. Garlic-сообщения могут детектировать успешную доставки метки путем добавления небольшого сообщения в качестве секции ("сообщение состояния доставки") - когда garlic-сообщение прибывает адресату и успешно дешифруется, это небольшое статусное сообщение является одной из секций (cloves). Оно содержит инструкции для получателя, послать секцию назад исходному отправителю (через входящий туннель). Когда исходный отправитель получает это статусное сообщение, он знает, что метки сессии, включенные в garlic-сообщение, успешно доставлены.
Сами метки сессий имеют очень короткое время жизни, после которого они уничтожаются, если не используются. Кроме того, число меток, запомненное для каждого ключа ограничено, как и число самих ключей – если их приходит слишком много, либо новые, либо старые сообщения могут быть отброшены. Отправитель отслеживает, прошли ли благополучно сообщения, использующие метки сессии, и, если нет, он может отбросить сообщение, которое предполагалось ранее доставленным корректно.
Альтернативой может быть передача лишь одной метки сессии, и далее, запустить детерминистский PRNG (Pseudo-Random Number Generator) для определения того, какую метку использовать или ожидать. Поддерживая синхронность PRNG для отправителя и получателя (получатель предварительно вычисляет окно для, например, следующих 50 меток), избыточность периодического добавления большого числа меток при этом удаляется, допуская больше опций в плоскости пространство/время, и, возможно уменьшая число необходимых шифрований с привлечением алгоритма ElGamal. Однако это будет зависеть от возможности PRNG обеспечить необходимое прикрытие от внутренних атакеров, хотя при этом ограничивается число раз использования PRNG.
I2P является сетью для работы поверх сети с коммутацией пакетов, использующий схему точка-точка, обеспечивающий анонимность и безопасность. В то время как Интернет не реализует более принцип точка-точка (благодаря использованию NAT), I2P в действительности требует, чтобы существенная доля сети была достижимой – могут быть много партнеров на краях, работающие с использованием ограниченных маршрутов, но I2P не включает в себя соответствующий алгоритм маршрутизации для вырожденного варианта, где большинство партнеров недостижимы. Это будет, однако работать поверх сети, использующей такой алгоритм.
Операции с ограниченными маршрутами, где имеются ограничения того, какие партнеры доступны непосредственно, имеет несколько различных функционалов и возможностей анонимности, в зависимости от того, как обрабатываются ограниченные маршруты. На базовом уровне ограниченные маршруты реализуются, когда партнер находится за NAT или firewall, при запрете входящих соединений. Это относится, прежде всего, к версии I2P 0.6.0.6, позволяя людям, находящимся за NAT и firewall, осуществлять соединения по собственной инициативе без какой-либо конфигурации. Однако это не ограничивает раскрытие IP-адресов партнеров маршрутизаторам внутри сети.
За пределами функциональной обработки ограниченных маршрутов имеется два уровня ограниченных операций, которые могут быть использованы для ограничения доступа к IP-адресам – использование специальных туннелей для коммуникаций маршрутизаторов, и предложение ‘клиентских маршрутизаторов'. Для первых, маршрутизаторы могут либо строить новый пул туннелей или повторно использовать свой диагностический пул, раскрывая данные о шлюзах входящих каналов для некоторых из них, в своих routerInfo вместо своих транспортных адресов. Когда партнер хочет вступить в контакт с ними, они видят эти шлюзы туннелей в netDb и просто посылают соответствующие сообщения к ним через один из опубликованных туннелей. Если партнер на другом конце ограниченного маршрута хочет ответить, он может сделать это либо непосредственно (если он согласен раскрыть партнеру свой IP) либо через свой исходящий туннель. Когда маршрутизаторы, с которыми партнер имеет непосредственное соединение, захотят с ним взаимодействовать (например, переслать туннельное сообщение), он просто отдает предпочтение соединению через опубликованный шлюз туннеля. Концепция 'клиентских маршрутизаторов' просто расширяет ограниченный маршрут, не публикуя каких-либо адресов маршрутизаторов. Такому маршрутизатору даже не нужно публиковать свою routerInfo в netDb, просто предоставляя самоподписанную routerInfo партнерам, с которыми он контактирует (необходимо передать общедоступный ключ маршрутизатора). Оба уровня работы с ограниченными маршрутами планируется реализовать в версии I2P 2.0.
Существуют методы оптимизации для случая ограниченных маршрутов, так как они, вероятно участвуют в других туннелях менее часто, и маршрутизаторы, с которыми они связаны, могут быть способны извлекать определенные данные из трафика, которые в противном случае не будут раскрыты. С другой стороны, если цена раскрытия меньше стоимости публикации IP, это может иметь смысл. Это, конечно, предполагает, что партнеры, с которыми контактируют маршрутизаторы ограниченного маршрута, не являются враждебными – либо сеть достаточно велика, так что вероятность использования враждебного партнера достаточно мала, либо используются исключительно надежные (проверенные) партнеры.
Хотя большая часть начальных усилий в I2P была потрачена на коммуникации с малыми задержками, эта сеть спроектирована из расчета на сервисы с переменной задержкой. На базовом уровне приложения, работающие поверх I2P, могут предложить анонимность для коммуникаций со средней и высокой задержкой. Внутренне I2P может предложить свои собственные коммуникации со средней и высокой задержкой за счет garlic-шифрования – специфицируя условие, что сообщение должно быть послано после некоторой задержки, в определенное время, после определенного числа сообщений. На уровне шифрования только маршрутизатор, которому передан секцией запрос задержки, будет знать, что сообщение требует высокой задержки, допуская смешение трафика с потоками низкой задержки. Раз выполнены условия передачи, маршрутизатор, задействованный для clove-секции (которая сама может быть garlic-сообщением), просто переадресует его маршрутизатору в туннель, или, более вероятно, удаленному клиенту места назначения.
Архитектура I2P строится на основе программ, осуществляющих обмен сообщениями, топологии DHT (Distributed Hash Table), анонимности и криптографии смешанной сети свободных маршрутов, и адаптивности сетей с коммутацией пакетов. Решение приходит не из новых концепций алгоритмов, а из тщательной инженерной проработки, комбинирования результатов исследования существующих систем и статей.
Смотри также Network Comparisons Page.
В то время как Tor (см. ниже) и I2P сходны во многих отношениях, присутствуют заметные отличия в терминологии.
TOR | I2P |
Cell (Ячейка) | Сообщение |
Клиент | Маршрутизатор или клиент |
Circuit (канал) | Туннель |
Directory (каталог) | NetDb (база данных) |
Directory Server (сервер каталога) | Floodfill-маршрутизатор |
Entry Guards | Fast Peers (быстрые партнеры) |
Entry Node (входной узел) | Inproxy (входной прокси) |
Exit Node (выходной узел) | Outproxy (выходной прокси) |
Hidden Service (скрытый сервис) | Eepsite или место назначения (Eepsite – сайт размещенный анонимно) |
Hidden Service Descriptor (описатель скрытого сервиса) | LeaseSet |
Introduction point (вводная точка) | Шлюз входного туннеля (Inbound Gateway) |
Узел | Маршрутизатор |
Onion прокси | I2PTunnel Client (более или менее) |
Relay (ретранслятор) | Маршрутизатор |
Rendezvous Point (точка встречи) | Что-то вроде шлюза входного канала + оконечная точка выходного канала |
Описатель маршрутизатора | RouterInfo |
Сервер | Маршрутизатор |
На первый взгляд, Tor и I2P имеют много сходств. В то время как разработка I2P началась раньше Tor, многие уроки onion-маршрутизации были интегрированы в протокол I2P. Вместо того, чтобы строить доверительную, централизованную систему с серверами каталогов, I2P имеет самоорганизующуюся сетевую базу данных для каждого партнера Другим ключевым отличием является то, что, как I2P, так и Tor используют послойную систему и упорядоченные проходы (туннели и трассы/потоки), I2P является принципиально сетью с коммутацией пакетов, в то время как Tor является системой с коммутацией каналов, позволяя I2P прозрачно маршрутизировать в условиях перегрузки и других отказов. В то время как Tor предлагает полезный выходной прокси, I2P оставляет такие решения прикладного уровня приложениям, работающим поверх I2P. I2P имеет на прикладном уровне TCP-подобную поточную библиотеку.
С точки зрения анонимности, существует много общего, когда ядра сетей сопоставимы. Когда имеется внутренний противник или много внешних атакеров, симплексные туннели I2P дают вдвое лучший результат, чем Tor.
В общем, Tor и I2P взаимно дополняют друг друга - Tor обеспечивает анонимность в высокоскоростных сетях прокси, в то время как I2P предлагает децентрализованную, адаптивную сеть. В теории, оба решения могут использоваться, хотя каждый из протоколов имеет свои сильные и слабые стороны.
В последнее время сети TOR стали называться Darknet и использоваться не только диссидентами, но и преступниками для торговли наркотиками и оружием. Число пользователей TOR в России (середина 2017г) составляет около 250000, а в мире ~1,6млн.
Проект Freenet играл главную роль на начальном этапе разработки I2P - продемонстрировав, что опасности, присущие внешним прокси, могут быть обойдены. Первый вариант I2P появился как замена коммуникационного слоя для Freenet. Однако со временем, некоторые элементы анонимности и масштабируемости, присущие алгоритмам Freenet, сделали понятным, что I2P следует концентрироваться на реализации слоя анонимности, а не служить одним из компонентов Freenet. С годами стало ясно, что Freenet должна работать поверх смешанной сети, такой как I2P или Tor, с "узлами клиентов" запрашивающими и публикующие данные через сеть "узлам сервера".
Функциональность Freenet является дополняющей по отношению к I2P, так как Freenet предоставляет много средств для работы в системах со средними и высокими значениями задержки, в то время как I2P ориентирован на анонимность.
Сам I2P делает не так много – он просто посылает сообщения удаленному адресату и получает сообщения, адресованные локальному объекту – наиболее интересная работа выполняется на уровнях, расположенных выше. Сам по себе, I2P может рассматриваться как анонимный и безопасный IP-уровень, и потоковую библиотеку в качестве реализации анонимного и безопасного TCP-уровня поверх него.
Протокол I2P использует библиотеку для работы с именами и базовая реализация сконструирована так, чтобы избавиться от локальных имен для удаленных объектов. Уникальность имен является лишь локальной. Так как все сообщения в I2P криптографически адресуемы в местах назначения, разные люди могут иметь в своей адресной локальной книге запись для "Alice", которая имеет отношение к разным местам назначения. Люди могут выявлять новые имена путем импортирования опубликованных адресных книг партнера. В какой-то мере эти адресные книги могут рассматриваться как традиционная система DNS.
I2P не допускает сервисов типа DNS, так как это открывает дополнительные возможности вторжения, а небезопасный сайт интереса не представляет. DNSsec не может предоставить адекватный уровень безопасности, в то время как с помощью I2P, запросы, посланные адресату не могут быть перехвачены или отклики фальсифицированы, так как они зашифрованы. Системы с DNS с другой стороны позволяют легко бороться с атаками типа DoS.
Именование с использованием мажоритарной выборки также представляет определенную опасность из-за атак на анонимные системы типа Sybil – атакер может создать сколь угодно большое число партнеров и голосование пройдет, так как ему надо в отношении нужного ему имени. Чтобы сделать идентичность фиксированной можно использовать методы Proof-of-work, но при росте размера сети такие методики становятся неэффективными.
В случае Интернет I2P переносит проблему имен на коммуникационный уровень. Библиотека работы с именами включает в себя простой провайдерский интерфейс, который позволяет конечному пользователю выбрать систему, предпочтительную для него.
I2PTunnel является, вероятно, наиболее популярным и универсальным клиентским приложением, позволяющим прокси обмены, как внутрь, так и вне I2P-сети. I2P-туннель может рассматриваться как четыре раздельных прокси-приложения - "клиент", который принимает входящие TCP -соединения и переадресует их заданному I2P месту назначения, "httpclient" (известный под названием "eepproxy"), который действует подобно HTTP-прокси и переадресует запросы соответствующему I2P месту назначения (после запроса в систему имен, если требуется), "сервер", который получает входное потоковое I2P-соединение с местом назначения и переадресует его на данную комбинацию TCP машина+порт, и "httpserver", который расширяет "сервер" путем анализа HTTP-запросов и откликов, обеспечивая более безопасную работу.
Сам I2P не является выходной прокси сетью – соображения анонимности и безопасности, присущие сети, которая переадресует данные в и из сети, поддерживают I2P принципы, ориентированные на реализацию анонимной сети, которая способна удовлетворить потребность пользователя, не требуя внешних ресурсов. Однако, Приложение I2PTunnel "httpclient" предлагает вариант для внешних прокси. Если имя запрошенной машины не соответствует концу туннеля ".i2p", берется произвольное место назначения из списка внешних прокси, предоставленного пользователем, и переадресует запрос туда.
I2P-туннель допускает использование большинства приложений. "httpserver", позволяет любому работать со своим анонимным web-сайтом (или "eepsite") – для этой цели web-сервер объединяется с I2P, но может использоваться любой web-сервер. Любой может запустить "клиент", указывающий на один из анонимно расположенных IRC-серверов, каждый из которых работает как "сервер", указывающий на свой локальный IRCd и работающий с IRCd через свой "клиентский" туннель. Конечные пользователи также имеют "клиентские" туннели, указывающие на I2Pmail's POP3 и места назначения SMTP, аналогично "клиентские" туннели указывают на I2P CVS-серверы, реализуя анонимные операции.
I2Pmail является скорее сервисом, чем приложением - почтальон предлагает как внутреннюю так и внешнюю почту через POP3 и SMTP-сервис, работающий с привлечением I2Ptunnel, позволяя клиентам использовать свой, предпочтительный для них почтовый клиент для псевдонимной посылки и приема почты. Однако большинство почтовых клиентов раскрывают значительный объем идентифицирующей информации, I2P объединяет почтовый клиент susi, базирующийся на web, с возможностями анонимности I2P. Сервис I2Pmail/mail.i2p предлагает прозрачную фильтрацию вирусов и предотвращение DoS. Кроме того, каждый пользователь может контролировать стратегию подбора, прежде чем осуществит пересылку почты через систему выходных прокси i2p, которые отделены от mail.i2p SMTP и POP3-серверов – выходные и входные прокси взаимодействуют с mail.i2p SMTP и POP3-серверами через I2P.
I2P-Bote представляет собой распределенное приложение электронной почты. Оно не использует традиционную концепцию e-mail с посылкой сообщения серверу и извлечением его из сервера. Вместо этого, оно использует распределенную хэш таблицу (DHT) Kademlia для запоминания электронной почты. Один пользователь может уложить почтовое сообщение в DHT, в то время как другой пользователь может запросить это сообщение из DHT. Все сообщения в пределах сети I2P-Bote автоматически шифруются.
Более того, I2P-Bote предлагает функцию анонимной переадресации сообщений поверх I2P.
I2P-Messenger представляет собой систему пересылки шифрованных сообщений по схеме точка-точка без использования централизованных серверов. Для коммуникации между двумя пользователями они должны предоставить друг другу свои ключи места назначения.
Каждый из слоев в стеке предоставляет дополнительные возможности. Эти возможности перечислены ниже, начиная со дна стека.
IP: протокол, позволяющий адресовать компьютеры в регулярной сети Интернет и маршрутизовать эти пакеты с использованием принципа ”наилучшего возможного”.
TCP: обеспечивает надежную упорядоченную доставку пакетов через Интернет.
UDP: позволяет организовать передачу пакетов без гарантии доставки или их упорядоченности.
Tunnel messages: туннельные сообщения являются большими сообщениями, содержащими зашифрованные I2NP-сообщения и зашифрованные инструкции по их доставке. Шифрование многослойно. На первом этапе дешифруется туннельное сообщение и читается часть. Другая часть может быть зашифрованной другим ключом, в таком виде она будет переадресована.
I2NP messages: сетевые протокольные сообщения I2P вкладываются друг в друга и используются, чтобы реализовать шифрование между двумя туннелями, сохраняя анонимность отправителя и получателя.
Следующие уровни, строго говоря, не являются частью стека протоколов I2P, они функционально не являются частью ядра 'маршрутизатора I2P'. Однако, каждый из этих слоев добавляет свою функциональность, чтобы облегчить использование приложений I2P.
I2CP: Протокол клиента I2P, обеспечивает безопасность и асинхронный обмен сообщениями поверх I2P, передавая сообщения через I2CP TCP-сокета.
Наконец, следует рассмотреть 'уровень приложений I2P', где имеется большое число программ, работающих поверх I2P.
Сетевой протокол I2P (I2NP), который размещается между I2CP и различными транспортными протоколами I2P, управляет маршрутизацией и микшированием сообщений между маршрутизаторами, а также выбором того, какой транспорт использовать, при коммуникациях с партнерами, для которых существуем многопротокольная транспортная поддержка.
I2NP-сообщения (сетевой протокол I2P) могут использоваться для одношаговой пересылки сообщений маршрутизатор-маршрутизатор, точка-точка. За счет шифрования и вложения одних сообщений в другие он могут пересылаться безопасным образом оконечному месту назначения.
Как NTCP, так и UDP-транспорт осуществляют приоритетную передачу, но в несколько разных манерах. UDP имеет сложный код с отдельными очередями для каждого приоритета, однако обрабатывает сообщения с приоритетами 400-499 одинаково, Это общие очереди для всех партнеров. NTCP имеет тривиальный линейный поиск для высшего приоритета в пределах буфера для конкретного партнера. Это много менее эффективно.
Поле | Длина в байтах |
Уникальный ID | 4 |
Время пригодности | 8 |
Длина поля данных | 2 |
Контрольная сумма | 1 |
Поле данных | 0 - 61.2Kбайт |
В то время как максимальный размер поля данных равен в норме 64Kб, размер может ограничиваться в случае фрагментации I2NP-сообщений при работе с несколькими 1Kб туннельными сообщениями, как это описано в туннель-alt.html. Максимальное число фрагментов равно 63.
Максимальный размер фрагмента составляет 956 байтов (в случае туннельного режима доставки); максимальный размер последующего фрагмента равен 996 байт. Следовательно максимальный размер сообщения равен 956 + (62 * 996) = 62708 байтов, или 61.2 Kбайт.
Кроме того, транспорты могут иметь дополнительные ограничения. NTCP в настоящее время устанавливает ограничения на уровне 16Kбайт - 6 = 16378 байт, но в будущем это значение может быть увеличено. Ограничение SSU составляет 32 Kбайта.
Заметим, что это не предел для дейтограмм, которые попадают клиенту, так как маршрутизатор может объединить leaseset отклика и/или метки сессии с сообщением клиента в garlic-сообщении. Leaseset и метки вместе могут добавить около 5.5Kбайт. Следовательно, на данный момент предельный размер дейтограмм лежит в области 10Kбайт.
Большие значения кодов соответствуют большему приоритету. Большую часть трафика составляет TunnelDataMessages (приоритет 400), таким образом все, что выше 400 – это высокий приоритет, а все что ниже - низкий. Заметим также, что многие сообщения маршрутизируются через тестовые, а не клиентские туннели, и следовательно не могут быть в той же очереди, если только ближайший шаг не соответствует тому же самому партнеру.
Кроме того, не все типы сообщений посылаются незашифрованными. Например, при тестировании туннеля, маршрутизатор упаковывает DeliveryStatusMessage, который вложен в GarlicMessage, который в свою очередь вложен в DataMessage.
Сообщение | Тип | Длина поля данных | Прио-ритет | Комментарий |
DatabaseLookupMessage | 2 | - | 100/400 | В норме 400; 100, если от HarvesterJob и посланы непосредственно; 400 для запросов маршрутизатора lookup |
DatabaseSearchReplyMessage | 3 | обычно. 161 | 300 | Размер равен 65 + 32*(число хэшей), где обычно, присылаются хэши для трех floodfill-маршрутизаторов. |
DatabaseStoreMessage | 1 | Варьи-руется | 100/400 | Обычно 100. Размер равен 898 байт для типового 2-lease leaseSet. Структуры RouterInfo компрессированы, а размер варьируется; однако продолжаются усилия уменьшить объем данных, помещаемых в RouterInfo. |
DataMessage | 20 | 4 - 62080 | 400 | - |
DeliveryStatusMessage | 19 | 12 | - | Используется для сообщений откликов, и для тестирования туннелей – обычно помещаются в GarlicMessage |
GarlicMessage | 11 | - | - | Обычно помещается в DataMessage – но, когда передается без вложения, переадресующий маршрутизатор использует приоритет 100 |
TunnelBuildMessage | 21 | 4224 | 300/500 | Обычно 500 |
TunnelBuildReplyMessage | 22 | 4224 | 300 | - |
TunnelDataMessage | 18 | 1028 | 400 | Наиболее общее сообщение. Приоритет для шлюза туннеля участников, исходящего и входящего был понижен до 200, как в 0.6.1.33. Сообщения шлюза исходящего туннеля (т.e. сформированные локально) остаются с 400. |
unnelGatewayMessage | 19 | - | 300/400 | - |
VariableTunnelBuildMessage | 23 | 1057 - 4225 | 300/500 | Более короткое TunnelBuildMessage, как в 0.7.12 |
VariableTunnelBuildReplyMessage | 24 | 1057 - 4225 | 300 | Более короткое TunnelBuildReplyMessage, как в 0.7.12 |
Другие, перечисленные в спецификации 2003 г | 0,4-9,12 | - | - | устарели, не используются |
Следующие структуры являются элементами многих I2NP-сообщений. Они не являются завершенными сообщениями.
Общий заголовок всех сообщений I2NP содержит контрольную сумму, время истечения пригодности и т.д..
1 байт специфицирует тип этого сообщения, следующие 4 байта представляют собой идентификатор сообщения. После этого следует код, характеризующий время пригодности, далее идут 2 байта длины поля данных сообщения, после этого кода идет хэш, который укорачивается вплоть до первого байта. После заголовка идут данные сообщения. Время пригодности равно числу миллисекунд с полночи 1-го января 1970 года во временной зоне GMT. Если это число равно нулю, то время не определено или равно 0. Стандартный заголовок (16 байт):
Рис. 9. Стандартный заголовок I2NP
Ниже рассматриваются форматы данных для протокола SSU. Ниже на рис. 10 представлен формат короткого заголовка (SSU, 5 байт):
Рис. 10. Короткий заголовок
Тип :: целое
длина -> 1 байт
назначение -> определение типа сообщения (см. таблицу ниже)
Msg-ID :: целое
длина -> 4 байта
назначение -> однозначно идентифицировать это сообщение.
Время пригодности :: Дата
8 байт
Дата, когда пригодность сообщения истечет.
Короткое время пригодности :: целое
4 байта
Дата, когда пригодность сообщения истечет (число секунд с начала эпохи)
Размер :: целое
длина -> 2 байта
назначение -> длина поля данных
Сtl-S :: целое
длина -> 1 байт
назначение -> контрольная сумма поля данных
хэш SHA256, сокращенный до одного байта
Данные :: Data
длина -> $размер байт
назначение -> содержимое сообщения.
Один рекорд в наборе из нескольких рекордов для запроса создания одного шага туннеля.
За TunnelId принимаемого сообщения следует Hash нашего RouterIdentity, после которого следует TunnelId и Hash RouterIdentity следующего маршрутизатора.
Рис. 11. Формат BuildRequestRecord
Зашифровано c привлечением алгоритма ElGamal:
незашифровано:
Для поля зашифрованные данные используются алгоритмы Эль-Гамаля и AES:
Не зашифровано
Туннель получателя :: TunnelId
длина -> 4 байта
Наш идентификатор :: хэш
длина -> 32 байта
Следующий_туннель :: TunelId
длина -> 4 байта
Следующий идентификатор :: хэш
длина -> 32 байта
ключ слоя :: SessionKey
длина -> 32 байта
Ключ iv :: SessionKey (ключ вектора инициализации)
длина -> 32 байта
ключ ответа :: SessionKey
длина -> 32 байта
iv ответа :: данные
длина -> 16 байта
Флаг :: целое
длина -> 1 байт
Время запроса :: целое
длина -> 4 байта
Часы с начала эпохи, т.e. текущее время / 3600
ID посланного сообщения :: целое
длина -> 4 байта
Заполнитель :: Data
длина -> 29 байт
source -> random
Полная длина: 222
Зашифровано ElGamal:
toPeer :: первые 16 байт SHA-256 хэша ID маршрутизатора партнера
длина -> 16 байт
Зашифрованные данные :: данные, зашифрованные ElGamal-2048
длина -> 512
Полная длина: 528
Зашифровано ElGamal и AES:
Зашифрованные данные :: данные, зашифрованные с помощью ElGamal и AES
длина -> 528
Полная длина: 528
незашифровано:
Рис. 12.
0-526 байтов: произвольные данные
527 байт : отклик (reply)
Зашифровано:
0-527 байтов: запись, зашифрованная AES (замечание: тот же размер, что и BuildRequestRecord)
Полная длина: 528
незашифровано:
Рис. 13. Формат GarlicClove
Не зашифровано:
Инструкции доставки :: http://www.i2p2.de/tunnel_message_spec.html#delivery
Длина варьируется, но обычно равно 39, 43 или 47 байт
I2NP-сообщение :: Любое I2NP-сообщение
ID секции :: 4 байта целое
Время истечения пригодности :: дата (8 байт)
Сертификат :: В настоящей реализации всегда NULL (3 байта, все нули)
Определены в http://www.i2p2.de/tunnel_message_spec.html#delivery.
Таблица 2. Типы сообщений
Сообщение | Тип |
DatabaseStore | 1 |
DatabaseLookup | 2 |
DatabaseSearchReply | 3 |
DeliveryStatus | 10 |
Garlic | 11 |
TunnelData | 18 |
ТunnelGateway | 19 |
Data | 20 |
TunnelBuild | 21 |
ТunnelBuildReply | 22 |
VariableTunnelBuild | 23 |
VariableTunnelBuildReply | 24 |
Запись в базу данных по собственной инициативе, или отклик на успешный запрос-сообщение базы данных (Lookup).
Некомпрессированный LeaseSet или компрессированный RouterInfo с кодами отклика:
Рис. 14. Формат DatabaseStore
с кодом отклика == 0:
Рис. 14A.
ключ: 32 байт
SHA256 хэш
Тип: 1 байт
Идентификатор типа
соответствие:br>
0 RouterInfo
1 LeaseSet
Коды отклика: 4 байта
Если больше нуля, запрошен Delivery Status Message c ID-сообщения равным значению Reply Token.
Если код больше нуля, ожидается, что Floodfill-маршрутизатор направляет поток данных ближайшему floodfill-партнеру.
TunnelId отклика: 4 байта ID туннеля
Включается только, если код отклика > 0
Это ID шлюза входящего туннеля, отклик которому должен быть послан.
Шлюз отклика: 32 байта
Хэш записи routerInfo включается только, если код отклика > 0
Это хэш маршрутизатора шлюза входящего туннеля, куда должен быть послан отклик.
Данные:
Если тип == 0, данные содержат 2-байтовое целое, специфицирующее число байт, которые далее следуют, далее располагается gzip-компрессированная RouterInfo.
Если тип == 1, данные являются некомпрессированным набором LeaseSet.
Рис. 15. Формат DatabaseLookup
Ключ: 32 байта
SHA256 хэш объекта запроса lookup
От (from): 32 байт
Если флаг == 0, SHA256 хэш записи routerInfo, указывает, откуда пришел этот запрос (и куда должен быть послан отклик).
Если флаг == 1, SHA256 хэш отклика шлюза туннеля (которому должен быть послан отклик).
Флаг: 1 байт
Возможные значения:
0 FALSE => послать отклик непосредственно
1 TRUE => послать отклик в некоторый туннель
TunnelId отклика: 4 байта Туннель ID
Включается, если только flag==TRUE
TunnelId туннеля, чтобы послать отклик
Размер: 2 байта целое
Возможный диапазон: 0-512
Число партнеров, которых следует исключить из Database Search Reply Message.
excludedPeers:
Остальная часть сообщения имеет размер $size SHA256 хэшей по 32 байта каждый (всего $size*32 байт).
Если запрос lookup неудачен, партнеры запрашиваются на предмет исключения их из списка сообщения отклика Database Search.
Если excludedPeers включает в себя хэш со всеми нулями, запрос является исследовательским, и сообщение Database Search Reply запрошено для получения списка non-floodfill маршрутизаторов.
Отклик на сообщение о неудаче запроса базе данных.
Список хэшей маршрутизаторов, наиболее близких к запрошенному ключу.
Рис. 16. Формат DatabaseSearchReply
Ключ: 32 байта
SHA256 объекта, который ищется
num: 1 байт целое
Число хэшей партнеров, которые далее следуют
хэш партнера: 32 байта
SHA256 RouterInfo, которую другие маршрутизаторы считают наиболее близкой к ключу $num записей
от: 32 байта
SHA256 RouterInfo маршрутизатора, от которого должен быть послан отклик.
Хэш 'от' не аутентифицирован и ему нельзя доверять.
Простое сообщение подтверждения. Обычно формируется отправителем сообщения, и помещается в Garlic-сообщение, для отправки по адресу места назначения.
ID доставленного сообщения и время создания или прибытия.
Рис. 17. Формат DeliveryStatus
msg-id: 4 байта
уникальный ID сообщения, в котором мы посылаем DeliveryStatus (см. Общий заголовок I2NP)
Временная метка: дата
8 байт
Время, когда сообщение было сформировано или доставлено
Временная метка всегда устанавливается отправителем равной текущему времени.
Используется, чтобы сворачивать вместе несколько зашифрованных I2NP-сообщений. После расшифровки, представляет последовательность Garlic Cloves (секций).
зашифровано:
Рис. 18. Формат DeliveryStatus
Незашифрованные данные:
Рис. 18A.
Зашифровано:
Длина: 4 байта целое
Число, которое следуют далее, 0 - 64 Kбайта
Данные: $length байт
ElGamal зашифрованные данные
Незашифрованные данные:
num: 1 байт целое число Garlic-секций, следующих далее.
секция: Garlic Clove
Сертификат :: всегда нуль в текущей реализации (всего 3 байта нулей)
ID сообщения :: 4 байта целое
Время пригодности :: дата (8 байт)
Рис. 19. Формат TunnelData
ID-туннеля: 4 байта ID туннеля
идентифицирует туннель, куда следует послать сообщение
Данные: 1024 байт
Поле данных до 1024 байт
Рис. 20. Формат TunnelGateway
TunnelId: 4 байта ID туннеля
идентифицирует туннель, куда должно быть направлено сообщение.
Длина: 2 байта целое
Длина поля данных
Данные : $length байт
Поле данных сообщения.
Используется в качестве упаковки для зашифрованных Garlic-сообщений и Garlic Cloves (секций).
Длина - целое, далее следуют непрозрачные данные.
Рис. 21. Формат поля данные
Длина: 4 байта
Длина поля данных
Данные: $length байт
Поле данных сообщения
Содержит в себе 8 рекордов Build Request, пронумерованных от 0 до 7, объединенных вместе.
Размер записи: 528 байт
Полная длина: 8*528 = 4224 байта
Тот же формат, что и у сообщения ТуннельBuild, c Build Response Records
Рис. 22. Формат VariableTunnelBuild
Тот же формат, что и ТуннельBuildMessage, за исключением добавления в начале поля "num" и числа $num записей, образующих запрос вместо 8.
num: 1 байт целое
Возможные значения: 1-8
Размер записи: 528 байт
Полный размер: 1 + $num*528
Рис. 23. Формат VariableTunnelBuildReply
Тот же формат, что и в сообщении VariableTunnelBuild, с записями Build Response.
"Транспорт" в I2P представляет собой метод для непосредственной коммуникации двух маршрутизаторов. Транспорты должны обеспечивать конфиденциальность и целостность против внешних противников, при аутентификации, которую маршрутизатор осуществляет для партнера, который должен получить данное сообщение.
I2P поддерживает много видов транспорта одновременно. В настоящее время реализованы две разновидности транспорта:
Каждый реализует парадигму соединения с аутентификацией управлением потока, подтверждениями и повторными передачами.
Транспортная подсистема I2P предоставляет следующие сервисы:
Транспортная подсистема поддерживает набор адресов маршрутизатора, каждый из которых содержит транспортный метод, IP и порт. Эти адреса представляют собой анонсированные контактные точки, которые публикуются маршрутизатором в сетевой базе данных.
Типичными сценариями являются:
Транспортная система доставляет сообщения I2NP. Выбор транспорта для каждого сообщения является независимым от протокола прикладного уровня (TCP или UDP).
Для каждого исходящего сообщения транспортная система запрашивает "цену” (bids) для каждого вида транспорта. При транспортной оценке нижняя цена выигрывает и получает сообщение для доставки. Транспорт может отказаться конкурировать.
Будет ли транспорт конкурировать (bids), и с каким значением, зависит от многих факторов:
Вообще, значения цены выбираются так, чтобы два маршрутизатора имели только одно соединение одновременно. Однако это не является обязательным требованием.
SSU нужен только для полунадежной доставки, TCP-подобных операций, и емкости для высокой пропускной способности, чтобы обеспечить приемлемую широту управления перегрузкой. Алгоритм управления перегрузкой, описанный ниже, достаточно прост для реализации.
Пакеты посылаются в порядке, определяемом политикой маршрутизатора, заботясь о том, чтобы не превысить выходной емкости маршрутизатора или возможностей удаленного партнера. Измеренная полоса учитывается во всех каналах при медленном старте TCP и при избегании перегрузки (используется алгоритм AIMD (additive increases and multiplicative decreases)). В отличие от TCP, маршрутизаторы могут прерывать попытки передать определенное сообщение после определенного числа неудач, продолжая передавать другие сообщения.
Методики детектирования перегрузки также отличаются от TCP, так как каждое сообщение имеет свой собственный уникальный идентификатор, и каждое сообщение имеет ограниченный размер – не более 32Kбайт. Чтобы эффективно обеспечить обратную связь с отправителем, получатель периодически включает список идентификаторов полностью подтвержденных сообщений и может также включать битовые поля для частично доставленных сообщений, где каждый бит представляет получение определенного фрагмента. Если приходит задублированный фрагмент, сообщение должно быть подтверждено снова, или если сообщение не было полностью доставлено, битовое поле должно быть переслано повторно.
В текущей реализации не используются заполнители, чтобы довести размер пакета до какого-то определенного размера, вместо этого одиночный фрагмент сообщения помещается в пакет и посылается.
Так как для версии маршрутизатора 0.8.12, используются два значения MTU: 620 и 1484. Значение MTU определяется процентом повторно пересылаемых пакетов.
Для обоих значений MTU, желательно, чтобы (MTU % 16) == 12, так что для целей шифрования доля поля данных после 28-байтного IP/UDP заголовка была кратной 16 байтам. Это справедливо только для IPv4.
Для малого значения MTU, желательно упаковать 2646-байтное сообщение в несколько пакетов.
На основе измерений MTU=1492 подходит практически для всех разумно малых I2NP-сообщений (большие I2NP-сообщения могут достигать 1900 - 4500 байт, которые не согласуются с сетевым значением MTU).
Значения MTU равнялись 608 и 1492 для версий 0.8.9 - 0.8.11.
Максимальный размер получаемых пакетов равен 1571 байтам (для версии 0.8.12). Для версий 0.8.9 - 0.8.11 это число равно 1535 байтам.
В то время как номинально максимальный размер сообщения равен 32Kбайт, на практике этот предел может варьироваться. Протокол ограничивает число фрагментов 7 битами, или 128. Текущая реализация, однако, ограничивает каждое сообщение максимум 64 фрагментами, каждый из которых достаточен для 64 * 534 = 33.3 Kбайт, при использовании 608 MTU. Из-за избыточности в случае добавления LeaseSets и ключей сессии, практическое ограничение на прикладном уровне несколько ниже 6Kбайт, или около 26Kбайт. Необходима дальнейшая работа, чтобы поднять транспортный предел UDP выше 32Kбайт. Для соединений, использующих большие значения MTU, допустимы сообщения большей длины.
Все шифрования используют AES256/CBC с 32-байтными ключами и 16 байтами IV. MAC и ключи сессии согласуются в процессе DH-обмена, используемого для HMAC (Hashed Message Authentication Code) и шифрования, соответственно. Перед DH-обменом, для MAC и шифрования используется общедоступный introKey.
При использовании introKey, как исходное сообщение, так и любой последующий отклик используют introKey Боба – субъект отклика не обязан знать introKey субъекта запроса (Алисы). DSA-ключ подписи, используемый Бобом, должен быть известен Алисе, когда она с ним контактирует, хотя ключ DSA Алисы может быть не известен Бобу.
По получении сообщения получатель проверяет IP-адрес "От" и порт для всех установленных сессий – если соответствие имеется, MAC ключи сессий проверяются в HMAC. Если ни один из них не верифицирован или, если нет соответствия для IP-адресов, получатель пытается применить свои introKey в MAC. Если верификация не прошла, пакет отбрасывается. Если верификация успешна, результат интерпретируется в соответствии с типом сообщения, хотя если получатель перегружен, он может отбросить пакет все равно.
Если Алиса и Боб имеют установленную сессию, но Алиса по каким-то причинам теряет ключи и она хочет контактировать с Бобом, она может в любое время установить новую сессию с помощью SessionRequest. Если Боб потерял ключ, а Алиса его не знает, она сначала попытается вызвать его отклик, послав DataMessage с установленным флагом wantReply, и, если Боб не отвечает, она предполагает ключ потерянным и формирует новый.
Для ключевого соглашения DH, RFC3526 2048бит MODP используется:
p=22048 - 21984 - 1 + 264 ×{ [21918 pi] + 124476}
g=2;
Аналогичные значения p и g используются для шифрования I2P's ElGamal.
Предотвращение отклика на SSU-уровне происходит при отбрасывании пакета с чрезмерно старой временной меткой или пакетов, который повторно используют IV. Чтобы детектировать дубликаты IV, применена последовательность фильтров Блума (Bloom).
MessageIds используемые в DataMessages определены на уровне выше SSU-транспорта и передаются прозрачным образом. Эти ID никак не упорядочены – и в действительности являются случайными кодами. Уровень SSU не делает попыток предотвращения отклика с messageId – эту задачу должны брать на себя более высокие уровни.
Чтобы установить соединение с SSU-партнером, необходим один из двух наборов: прямой адрес, когда партнер доступен напрямую или непрямой адрес, когда для достижения партнера нужен посредник. Не существует ограничения на число адресов, которые может иметь партнер.
Непосредственно: машина, порт, introKey, опции
Апосредовано: метка, relayhost, порт, relayIntroKey, targetIntroKey, опции
Каждый из адресов может также предоставлять некоторый набор опций – специальные возможности конкретного партнера.
Непосредственное установление сессии используется, когда не нужен какой-либо посредник для NAT преобразования. Последовательность обмена выглядит следующим образом:
Алиса устанавливает непосредственное соединение с Бобом.
Алиса Боб SessionRequest---------------------> <---------------------SessionCreated SessionConfirmed------------------> <---------------------->Данные
Вводные ключи доставляются через внешний канал (сетевая база данных, где они на данный момент идентичны хэшу маршрутизатора) и должны использоваться при формировании ключа сессии. Для непрямых адресов партнер должен сначала контактировать с узлом-ретранслятором и просить его представления партнеру, известному этому ретранслятору под заданным именем (tag). Если возможно, ретранслятор посылает сообщение адресуемому партнеру, уведомляя его о необходимости контактировать с партнером, пославшим запрос, а также дает запрашивающему партнеру IP и порт, по которым он находится. Кроме того, партнеру, устанавливающему соединение, должен быть известны общедоступные ключи партнера, с которым они устанавливают соединение.
Установление непрямых сессий через посредника необходимо для эффективного отслеживания NAT. Чарли, маршрутизатор за NAT или firewall’ом, который не допускает незапрошенных входящих UDP-пакетов, сначала контактирует с несколькими партнерами, выбирая те, которые могут быть ретрансляторами. Каждый из этих партнеров (Боб, Бил, Бетти и т.д.) предоставляет Чарли вводную метку - 4 байтовое случайное число, которое он делает доступным для контактирования с ним. Алиса, маршрутизатор, который знает опубликованные методы контакта с Чарли, сначала посылает пакет RelayRequest одному или более посредникам, прося представить ее Чарли (предлагая метку, идентифицирующую Чарли). Боб переадресует пакет RelayIntro Чарли, включая публичный IP и номер порта Алисы, затем возвращает Алисе пакет RelayResponse, содержащий IP-адрес Чарли и его номер порта. Когда Чарли получает пакет RelayIntro, он посылает небольшой пакет по IP-адресу Алисы, и, когда Алиса получает от Боба пакет RelayResponse, она начинает формирование новой сессии для специфицированного IP и номера порта.
Алиса сначала устанавливает соединение с Бобом, который передает запрос Чарли.
Алиса Боб Чарли RelayRequest ----------------------> <--------------RelayResponse RelayIntro-----------> <--------------------------------------------HolePunch (данные игнорируются) SessionRequest--------------------------------------------> <--------------------------------------------SessionCreated SessionConfirmed------------------------------------------> <----------------------------------------------->Данные
Автоматизация тестирования коллаборативной доступности для партнеров обеспечивается с помощью последовательности PeerTest-сообщений. При их корректном исполнении партер будет способен определить свою доступность и скорректировать свои рабочие параметры. Процесс тестирования достаточно прост:
Алиса Боб Чарли PeerTest -------------------> PeerTest--------------------> <-------------------PeerTest <-------------------PeerTest <------------------------------------------PeerTest PeerTest------------------------------------------> <------------------------------------------PeerTest
Каждый из PeerTest сообщений несет в себе код, идентифицирующий саму тестовую последовательность, как инициализированную Алисой. Если Алиса не получила определенное сообщение, которое ожидала, она повторяет передачу и на основе полученных данных или потерянных сообщений, получает данные о своей доступности. При этом могут быть получены следующие конечные состояния:
Алиса должна выбрать Боба произвольно из числа известных партеров, которые кажутся способными участвовать в тестировании партнеров. Боб в свою очередь должен аналогично выбрать Чарли из числа известных ему партнеров, кто кажется способным участвовать в тестировании и кто использует IP отличающиеся от адресов Боба и Алисы. Если реализовано условие ошибки (Алиса не получила сообщения PeerTest от Боба), Алиса может решить назначить новым партнером Боба и попытаться снова с другим кодом безопасности (nonce).
Вводный ключ Алисы включен во все сообщения PeerTest, так что ей не нужно устанавливать сессию с Бобом и что Чарли может контактировать с ней, не имея какой-либо дополнительной информации. Алиса может продолжить, установив сессию с Бобом или Чарли, но это не является необходимым.