Построение собственной коммуникационной сети поверх I2P

    При современных тенденциях, направленных на тотальное прослушивание и сбор всевозможной информации, использование защищённых средств коммуникации как никогда актуально. Шифрование самих передаваемых данных решает проблему лишь частично, поскольку сам факт обмена информацией между участниками важнее его содержания.

    В большинстве современных систем будь то электронная почта, ICQ или твиттер, владелец серверов обладает всеми этими данными и может, при необходимости, поделиться ими при получении официального или неофициального запроса об этом. Ниже предлагается проект сети, построенной поверх I2P, в которой владелец использует свои узлы только для обеспечения более стабильной работы и в качестве шлюзов в обычный интернете, имея информации не больше, чем обычные узлы I2P.


    Рассмотрим механизмы обеспечения анонимности и конфиденциальности I2P, на которые будем опираться для построения нашей сети:
    1. Всякий участник I2P представляет собой известный остальной сети маршрутизатор и один или несколько адресов, образующих собственно «невидимую» сеть. Смысл I2P заключается в практической невозможности узнать на каком маршрутизаторе располагается тот или иной адрес
    2. Адрес I2P представляет собой пару открытых ключей для асимметричного шифрования и подписи. Закрытая пара ключей хранится у владельца и является подтверждением подлинности адреса. Иначе говоря, для авторизации вместо паролей используется этот файл с ключами — аналог электронно-цифровой подписи, может быть, при необходимости, реализовано в виде токена
    3. Соединения между маршрутизаторами шифруются с использованием AES, сеансовый ключ для которого согласовывается в несколько шагов, включающих в себя проверку подписи адреса узла с целью противостояния атакам типа «man-in-the-middle»


    Ранее было показано, что фактически I2P представляет собой двухуровневую конструкцию: маршрутизатор, обеспечивающий взаимодействие с другими маршрутизаторами и работу тоннелей, и протоколы, предназначенные для передачи данных между приложениями. Если протоколы для маршрутизатора представляются тщательно продуманными и эффективными, то прикладные протоколы оставляют желать лучшего и представляют собой нагромождение различных концепции и идей, обусловленных стремлением сделать их максимально универсальными и «прозрачными» для уже существующих приложений. В нашем случае задача существенно упрощается, поскольку мы предполагаем обмен между нашими клиентами, потому можем использовать собственный протокол.

    Другая проблема I2P заключается в том, что при попытке обратиться к адресу возникает ошибка «адрес не найден» хотя ресурс с указанным адресом в данный момент находится онлайн. Происходит это вследствие неполноты сетевой базы данных, например, сразу после старта, когда информация о многих маршрутизаторах становится устаревшей и требуется время для ее обновления. А поскольку адреса публикуют свои LeaseSet-ы на «ближайщих» к себе floodfill-ах, то нужных floodfill-ов у клиента в базе еще может просто не быть. Наши клиенты будут использовать вторую сетевую базу данных, содержащую набор узлов, соответствующие нашим серверам и публиковать свои LeaseSet-ы только на этих узлах, что позволит находить LeaseSet-ы друг друга немедленно.

    Каждый узел I2P идентифицируется I2P адресом, представляющим собой 2 пары открытых и закрытых ключей, генерируемых в момент создания узла случайным образом, без какой-либо корреляции с IP адресом или местоположением. Центрального источника адресов нет, предполагается, что вероятность совпадения двух случайно сгенерированных адресов пренебрежимо мала. Владельцем узла является тот, у кого имеется файл с полным набором ключей. Два открытых ключа и 3-х байтный сертификат (на настоящий момент всегда нулевой) образуют 387-байтный идентификатор узла, под которым узел становится известен в I2P. Поскольку полный 387-байтный идентификатор довольно неэффективен для сравнения, сортировки и передачи данных, то для обозначения узла используется 32-х байтный SHA-256 хэш от идентификатора, используемый нами для идентификации клиента. Поскольку адрес содержит ключ подписи, то выдавать себя за другого клиента злоумышленнику будет затруднительно, это эквивалентно подбору такой пары ключей, хэш от которой будет соответствовать данному идентификатору. При необходимости клиент может подтвердить, что за I2P адресом скрывается именно он, подписав некий документ своей ключом.

    Итак, наша сеть будет состоять из запускаемых на компьютерах клиентов нашей сети и принадлежащим нам серверов. И клиенты и сервера представляют собой полноценные I2P маршрутизаторы, при этом сервера объявлены высокоскоростными и рассчитаны в первую очередь на пропускание транзитного трафика, клиенты же в основном используют собственные тоннели, а транзитный трафик — для маскировки своей активности. Информация о серверах является публичной и известной клиентам, в то же время сервера ничего не знают о клиентах и не имеют возможности отличить клиентов от обычных узлов I2P. Клиенты будут выбирать узлы для тоннелей с тем расчетом, чтобы в тоннеле был ровно один сервер, а остальные узлы принадлежали другим участникам обычной I2P. Даже если все наши сервера окажутся под контролем злоумышленника, то одного узла будет недостаточно, чтобы определить другой конец стандартного для I2P 3-х шагового тоннеля. У пользователя всегда будет возможность увидеть маршруты тоннелей, а также исключать подозрительные узлы.

    С другой стороны, один наш сервер в тоннеле необходим для повышения надежности работы тоннелей за счет раннего выявления переставших работать тоннелей. Это одна из фундаментальных проблем I2P: если узел согласился участвовать в транзитном тоннеле, а потом перестал работать (например, пользователь его остановил), то создатель тоннеля ничего об этом не знает и продолжает использовать неработающий тоннель в течение продолжительного времени. В отличие от обычного I2P наши клиенты будут активно посылать в тоннель тестовые сообщения, и как только наш сервер обнаружит отсутствие трафика в тоннеле, то опубликует об этом уведомление для клиентов, позволяя тем самым клиенту прекратить использование такого тоннеля немедленно. 

    Для обмена данными между нашими клиентами может использоваться I2NP сообщение типа 20 — Data, содержащее произвольные данные, либо же сообщение типа 11 — Garlic. Первоначально в I2P предполагалась следующая схема обмена между адресами: следовало запросить LeaseSet адресата, затем следовало сформировать сообщение типа Garlic, указав адрес в качестве места назначения, зашифровать его публичным ключом шифрования из LeaseSet-а и отправить в соответствующий тоннель. Маршрутизатор, получив такое сообщение, расшифровывал его и далее определял, кому предназначено сообщение. Но в этом случае ключ шифрования должен был быть одинаковым для всех адресов, сидящих на данном маршрутизаторе, что порождало большую «дыру» в безопасности, поэтому в современной реализации I2P у каждого адреса свой набор входящих тоннелей и ключ шифрования, соответственно маршрутизатор может определить адрес и без «чесночного» сообщения. Отказавшись от использования «чесночного» шифрования мы избавляемся еще от одной громоздкой конструкции I2P — AES/ElGamal engine, и можем использование более эффективное для наших задач шифрование, в то же время отправляя сообщения типа 11, чтобы сделать наш трафик неотличимым от обычного I2P.


    Клиенты могут обмениваться почтой как между собой внутри сети, так и с внешними адресатами. В первом случае используются непосредственно I2P адреса, и сообщения пересылаются через тоннели из LeaseSet-а адресата. Если клиент не может обнаружить LeaseSet с таким адресом, то будет продолжать делать это в течение определенного времени, после чего сгенерирует сообщение о невозможности доставки.

    В втором случае клиенту следует воспользоваться одним из наших серверов в качестве исходящего SMTP сервера. У каждого из наших серверов будет свой адрес, а адресу клиента будет соответствовать назначенное сервером имя пользователя, вместе образующих действительный почтовый адрес. Если клиент желает отправить почтовое сообщение за пределы сети, он должен найти LeaseSet сервера (а он его найдет обязательно), после чего сервер распознает сообщение как почтовое и отправит его адресату как обычный SMTP сервер. Получатель будет знать лишь адреса нашего SMTP сервера, и даже если кто-то захочет узнать у нас, кто скрывается за тем или иным адресом, максимум, что мы сообщить, это I2P адрес, а чей это адрес нам по-прежнему неизвестно. Если сервер получает сообщение извне, то по имени пользователю находит его I2P адреса и далее посылает обычным образом внутри нашей сети.

    С целью борьбы со спамом мы введем ограничения на количество сообщений, отправляемых с каждого I2P адреса. Чтобы адрес мог отправлять сообщения наружу он будет должен зарегистрироваться на сервере и узнать свое имя, при этом мы потребуем от него сертификат, получающийся в результате некоторой ресурсоемкой вычислительной задачи, тем самым затруднив массовую генерацию адресов, в то же время не создавая проблем тем, кому нужен всего один или несколько адресов.

    Таким образом мы получаем сеть, с одной стороны обеспечивающую анонимность и конфиденциальность передаваемой информации, раскрытие которой невозможно без доступа к компьютеру клиента, а с другой стороны поддерживающую высокий уровень доверия между клиентами с помощью средств криптографической идентификации. Использование собственного протокола и только его между клиентами позволяет существенно упростить реализацию и повысить надежность работы сети, появление же новых высокоскоростных маршрутизаторов улучшит работу и пропускную способность самой I2P.

    Хотелось бы услышать мнение уважаемого хабрсообщества по поводу предложенного проекта в целом, и в первую очередь о потенциальных атаках с целью деанонимизации клиентов, а также иных слабых местах и уязвимостях.
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 12

      +2
      Проект интересный, но как то не хватает технической части.
        0
        Техническая часть представляет собой в первую очередь реализацию и модификацию I2P. Мне не хотелось в это углубляться, чтобы не перегружать статью лишними деталями — даже без них, на мой взгляд, получилась несколько громоздкой.
        +1
        По-моему заголовок не соответствует содержанию: читая «Построение собственной коммуникационной сети» я предполагаю увидеть внутри что-то именно про сеть, т.е. какую-то базовую вещь, которой потом сможет пользоваться остальное ПО, т.е. в большинстве случаев это IP или Ethernet сеть, возможно какая-то другая но тоже базовая — которой потом сможет пользоваться какая-то программа которая ничего не знает про I2P. Тут получается очень специализированная вещь только для программы которая будет специально под этот протокол написана.

        По сути:
        Как я понял — основная причина построения сети — повышение стабильности за счет раннего обнаружения отказов промежуточных узлов. А чем эта система лучше, чем отправка сообщение alive при tcp-соединениях через socks-прокси для I2P или каких-то пингов на уровне собственного приложения поверх обычной I2P сети, без использования специальных серверов?

        По опыту использования I2P у меня сложилось мнение о таких неудобствах:
        1. Высокая латентность
        2. Ограниченное использование существующего ПО — как я помню там или соединения точка-точка через socks-прокси или http через http-прокси, либо уже что-то специальное.

        Отчасти можно побудить пингами и перестроением тоннелей, хотя я с таким на практике не сталкивался — спокойно бродил по внутренним сайтам без каких-то явно больших задержек.

        Что хочется:
        Вот хорошо бы решить эту задачу — т.е. построение сети общего назначения: собственный VPN (IP/Ethernet) или какая-то более широкая IP-сеть. Чтобы участники этой сети могли просто подключить в компьютер дополнительный сетевой адаптер и например там между собой смогли бы общаться Jabber-сервера по обычному протоколу, Seafile-хранилища, можно было бы стандартными средствами попинговать узел чтобы понять жив ли он или например выходить в интернет через какой-то шлюз без заворачивания трафика на http-прокси а просто обычной настройкой маршрутизации или подключением к какому-то VPN-серверу опять же обычными средствами.

        При этом реализация на стороне клиента обеспечивала бы хождение трафика P2P без участия центральных серверов, а центральные сервера занимались бы распределением IP-адресов и указанием соответствия. Условно что сейчас IP 1.2.3.4 соответствует I2P адресу abcd и дальше обмен трафиком между ними идет уже напрямую.
          0
          >Условно что сейчас IP 1.2.3.4 соответствует I2P адресу abcd и дальше обмен трафиком между ними идет уже напрямую.

          И прощай вся анонимность.
            0
            Возможно я неясно сказал — IP-адреса приватные для этой сети.

            Т.е. по внутреннему IP-адресу можно узнать I2P адрес который ему соответствует, больше из него ничего узнать не получится.
              0
              Tun-интерфейс вместо использования отдельных портов как сейчас сделано в I2P.
              Эта задача успешно решается кстати, данный проект же ориентирован в первую очередь на прикладное применение I2P.
            0
            >Условно что сейчас IP 1.2.3.4 соответствует I2P адресу abcd и дальше обмен трафиком между ними идет уже напрямую
            Причем делается достаточно просто.
            1. При настройке роутера указываешь блок серых адресов, на которые будут мапиться i2p адреса. Один из этих адресов — адрес роутера.
            2. Роутер поднимает интерфейс с адресом из этого блока.
            3. Роуер поднимает DNS сервер, который резолвит *.i2p в адреса из серого блока. С каким нибудь мелким ttl.

            После этого начинает работать весь софт, и серверный и клиентский, который вообше ни сном ни духом о всяких прокси и соксах.

            Осталось сесть и написать. :)
            0
            >Как я понял — основная причина построения сети — повышение стабильности за счет раннего обнаружения отказов промежуточных узлов.

            Более важная причина это заведомая полнота базы, на которых наши клиенты объявляют свои LeaseSet-ы, тем самым гарантируя, что если LeaseSet опубликован, то он будет найден другим клиентом всегда.

            >А чем эта система лучше, чем отправка сообщение alive при tcp-соединениях через socks-прокси для I2P или каких-то пингов на уровне собственного приложения поверх обычной I2P сети, без использования специальных серверов?

            Тоннели работают только в одну сторону, потому вы должны пинговать пару тоннелей, а если пинг не вернулся, то непонятно какой из двух помер.
            Кроме того, введение одного заведомо надежного узла снижает вероятность отказа тоннеля на треть.
              0
              Более важная причина это заведомая полнота базы, на которых наши клиенты объявляют свои LeaseSet-ы, тем самым гарантируя, что если LeaseSet опубликован, то он будет найден другим клиентом всегда.

              Если я правильно понял LeaseSet это условно информация через какие маршрутизаторы можно подключиться к тому или иному I2P-адресу.
              Т.е. условно — вы предлагаете централизованная база маршрутов, чтобы быстрее находить путь подключения?

              Мне кажется это стоит отдельно проверять на снижение уязвимостей — не зря же сделан путь в несколько хопов с намеренным сокрытием маршрута следования и невозможностью определить конечного получателя (т.е. кто этот узел — адресат или тоже промежуточный узел).
              Если будет центральная база адресов может появиться соответствие — как найти конечный узел и возможно зная это можно понять на каком IP-адресе он работает.
              Это общие соображения — I2P пробовал относительно давно и недолго, т.к. нормальное ПО не работает, а специализированным общаться не с кем. Поясните где неправ.

              Тоннели работают только в одну сторону, потому вы должны пинговать пару тоннелей, а если пинг не вернулся, то непонятно какой из двух помер.

              Ну и нормально если любой из туннелей упал — перестроить оба. Это же не происходит ежеминутно чтобы требовало каких-то больших оптимизаций по снижению накладных расходов трафика. А по времени — они могут перестраиваться параллельно и времени уйдет столько же сколько на перестройку одного туннеля.

              Кроме того, введение одного заведомо надежного узла снижает вероятность отказа тоннеля на треть.

              Ну и степень анонимности снижается настолько же — этого эффекта (даже лучше) можно добиться если в настройках туннеля поставить на 1 хоп меньше.
                0
                Насчет LeaseSet-а в целом правильно — это текущий набор входящих тоннелей.
                Маршруты могут быть какие угодно, тут идея иная.
                Допустим вы хотите опубликовать LeaseSet вашего адреса, вы должен это делать на «ближайщем» к вам (в смысле DHT) floodfill-е. Сделали.
                Теперь ваш товарищ хочет к вам обратиться и он станет искать ваш LeaseSet тоже на ближайщем вам floodfill-е. Но может оказаться так что эти floodfill-ы у вас и у него разные потому что в этот момент у вас и у него него разное содержимое netDb.
                Мы же собираемся публиковать на своих серверах.

                >Ну и нормально если любой из туннелей упал — перестроить оба. Это же не происходит ежеминутно чтобы требовало каких-то больших оптимизаций по снижению накладных расходов трафика. А по времени — они могут перестраиваться параллельно и времени уйдет столько же сколько на перестройку одного туннеля.

                Именно так сейчас и делается. Но постройка тоннеля — удовольствие дорогое. Кроме того у многих маршрутизаторов стоит ограничение на число транзитных тоннелей. В итоге получается что висит масса неиспользумых тоннелей, потому что время жизни тоннеля строго 10 минут.

                >Ну и степень анонимности снижается настолько же — этого эффекта (даже лучше) можно добиться если в настройках туннеля поставить на 1 хоп меньше.

                Так наш сервер может располагаться в произвольном месте тоннеля, так что это не равносильно уменьшению на один хоп.
                Кстати в некоторых запущенных случаях (когда клиент сидит за нат-ом и закрыто почти все) придется удлинять тоннели на один хоп, делая наш сервер первым.
              +4
              Лучше бы вы написали, что ваш реализация I2P на C++ уже работает =) таким образом, может быть еще разработчики бы подтянулись
                0
                i2pd это можно сказать базис проект, реализующий саму функциональность I2P, а этот проект — содержательная надстройка

              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

              Самое читаемое