- PVSM.RU - https://www.pvsm.ru -

Распределенная природа мессенджера Tox

Пока правообладатели собираются заблокировать централизованный Telegram [1], сообщество пользователей распределенного мессенджера Tox растет. Сегодня, согласно статистике сайта www.toxstats.com [2], Россия занимает второе место после США по количеству пользователей отставая всего на какие-то 30-50 узлов.

В данной публикации я бы хотел рассказать про распределенную природу данного мессенджера, общие принципы работы DHT-сети Tox, а так же как "догнать и перегнать Америку" по количеству нод.

tox logo

Введение

Каждая нода Tox определяется IP адресом, номером порта и публичным 256-и битным ключом. Существует два условных вида нод:

  • Bootstrap-нода — нода, которая обслуживает работу сети, но не взаимодействует напрямую с пользователем.
  • Клиент Tox — нода, которая помимо обслуживания работы сети, выполняет какую-либо дополнительную работу (бот, мессенджер). При этом клиент и нода используют разные пары ключей.

Публичный ключ ноды используется для шифрования пакетов передаваемых этой ноде. Пакеты расшифровываются на стороне ноды при помощи 256-и битного приватного ключа. Для передачи DHT-пакетов используется протокол UDP.

Для «входа» в сеть Tox достаточно иметь связность с любой нодой Tox, которая уже находится в сети. Обычно для этого используется список из известных bootstrap-нод [3] в сети интернет. Дополнительно библиотека libtoxcore [4] использует отправку пакетов на широковещательные адреса, что позволяет подключиться к сети Tox не имея выхода в интернет (при условии, что в вашем сегменте сети есть необходимая нода). И даже без выхода в интернет две и более ноды Tox образуют изолированную сеть Tox, позволяющую взаимодействовать локальным клиентам.

Самоорганизация DHT-сети

Поскольку каждая нода Tox имеет уникальный идентификатор в виде публичного ключа, то отношения между двумя любыми нодами можно выразить искусственной метрикой на базе этих ключей. Этой метрикой является расстояние между ключами. Расстояние вычисляется как сложение по модулю 2 (побитовый XOR) между двумя ключами и интерпретируется как беззнаковое целое.

xor

Из свойств операции XOR вытекает, что нулевое расстояние может быть только между одним и тем же ключом (ключом ноды), а половина всего пространства ключей по отношению к ключу ноды будет иметь максимально возможное расстояние — с некоторой условностью ноды с такими ключами можно считать «недостижимыми» и взаимодействие с подобными нодами будет достаточно редким событием.

Процесс входа в сеть Tox начинается с отправки пакета "Nodes request" известной bootstrap-ноде (одной или нескольким), где содержимое пакета представляет собой разыскиваемый публичный ключ. Нода, получившая пакет «Nodes request», ищет среди известных ей публичных ключей (кроме своего собственного и запрашиваемого) ключи с наименьшим расстоянием от разыскиваемого и отвечает пакетом "Nodes response", содержащим от 1 до 4 найденных ключей и соответствующих им нод (IP/порт). Итеративно повторяя запросы «Nodes request» к нодам из ответа клиент-нода может найти другую ноду с минимальным расстоянием от искомого ключа (параллельно получая информацию о существующих промежуточных нодах).

tox nodes request timeline

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

tox nodes neighbors

Живость каждой известной ноды проверяется периодической отправкой пакета "Ping request", на который получатель должен ответить пакетом "Ping response". Дополнительно с некоторой периодичностью клиент-нода отправляет случайной (из известных) ноде пакет «Nodes Request» для получения информации об изменениях в DHT-сети. Неотвечающие ноды удаляются из списка известных по истечении таймаута.

Необходимость частой отправки пакета «Ping request» для большого списка известных нод приводит к неоправданной нагрузке на сеть. В то же самое время сохранение информации только о ближайших соседях будет приводить к увеличению времени поиска неизвестной ноды. Для достижения баланса в библиотеке libtoxcore введено понятие индекса ключа — это индекс первого отличающегося бита ключа по отношению к ключу ноды. Для каждого нового ключа вычисляется его индекс и для каждого индекса ядро сохраняет до 8 ключей вытесняя ключи с наибольшим расстоянием. Дополнительно ядро хранит 8 ключей ближайших соседей с тем же алгоритмом вытеснения.

tox node index

В текущей реализации libtoxcore длина индекса ограничена 128 «корзинами», что при определенном везении позволяет каждой ноде хранить информацию о 1024 нодах (до некоторого времени в прошлом, пока сеть была очень-очень маленькой, использовалось 32 корзины и 190 нод соответственно). При минимальном размере пакета в 82 байта («Ping request») и опросе каждой ноды раз в 60 секунд, получаем трафик в ~22Kbit при максимальной загрузке индекса.

Из правила вычисления индекса корзины так же следует, что чем меньше расстояние между двумя ключами, тем больший индекс будет иметь ключ и тем меньше будет вероятность встретить такой ключ. В реализации библиотеки libtoxcore ключи с индексом более 127 или становятся «соседями» или попадают в 128-ю корзину в зависимости от расстояния.

tox nodes full-mesh

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

Клиенты DHT-сети

В отличии от DHT-нод, вся информация о которых известна или может быть получена любым клиентом DHT-сети Tox, клиентские приложения скрыты от стороннего наблюдателя — простого знания ToxID контакта (содержащего его публичный ключ) недостаточно для того, чтобы установить местонахождение этого контакта. Для соединения двух приложений Tox используется механизм луковой маршрутизации [5] («onion routing»).

Механизм установления связи между двумя клиентами можно представить следующим образом. Два клиента (A и Z) анонсируют свой публичный ключ на ближайших (для своего публичного ключа) нодах через три случайные промежуточные DHT-ноды, каждая из которых знает только своих соседей по маршрутизации пакета, но не может прочитать содержимое пакета.

tox onion announce

Второй клиент (Z), желающий соединиться с первым (A), так же через три случайные DHT-ноды делает запрос на установку соединения на ближайшую к искомому ключу (A) ноду, которая знает об анонсе первого клиента и маршруте, по которому требуется передать запрос от второго клиента.

tox onion request

Первый клиент (A) в случае принятия запроса на установку соединения, проделывает обратную операцию к ближайшей DHT-ноде второго клиента (Z).

tox onion response

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

tox onion UDP connect

Если клиенты не желают делиться информацией о своем местоположении даже со своими контактами, они могут использовать ноды поддерживающие TCP-relay через прокси типа Tor [6].

tox TCP connect

Особенностью TCP-релеев является то, что они пытаются использовать «широко-известные» («well-known») прты: 443 (HTTPS) и 3389 (RDP), что затрудняет их отслеживание и идентификацию.

«Догнать и перегнать Америку»

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

Исходя из описания выше, если вы пользуетесь любым клиентом Tox, то вы уже являетесь нодой сети (при этом ваша нода никак не связана с вашим ToxID за исключением того, что оба находятся на одном хосте). Если же вы пока не пользуетесь Tox, но желаете помочь проекту, вы можете установить bootstrap-ноду на подконтрольных вам серверах и компьютерах — она не потребляет много трафика или вычислительных ресурсов (в отличии от старых добрых времен Folding@home [7]).

Детальное описание процесса сборки и установки ноды можно найти по ссылке "Вливаемся в tox-сообщество или установка ноды за 5 минут [8]". Однако я постарался максимально упростить данный процесс собрав пакет tox-easy-bootstrap [9] для большинства популярных дистрибутивов Linux.

Для установки пакета tox-easy-bootstrap перейдите по ссылке [10] на репозитории проекта, выберете свой дистрибутив и следуйте простым инструкциям по добавлению репозитория и установке пакета в вашу систему.

Установщик пакета автоматически получит актуальный список публичных bootstrap-нод, создаст конфигурационный файл /etc/tox-bootstrapd.conf и запустит демона tox-bootstrapd под отдельным системным пользователем. Раз в неделю по cron специальный скрипт будет обновлять список публичных bootstrap-нод в конфигурационном файле, по этому вам не нужно будет беспокоиться о его актуальности в случае перезагрузки сервера — «поставил и забыл».

Для случаев, если на сервере используется «нормально закрытый» firewall вам может потребоваться внести разрешающие правила для входящего трафика на UDP:33445 и TCP:3389,33445 (порт TCP:443 не используется, т.к. процесс запускается под непривилегированным пользователем) — во избежании потенциальных «диверсий» эту часть я автоматизировать не стал:

-A INPUT -p tcp --dport 3389 -j ACCEPT
-A INPUT -p tcp --dport 33445 -j ACCEPT
-A INPUT -p udp --dport 33445 -j ACCEPT

Конфигурационный файл пакета /etc/tox-easy-bootstrap.conf [11] позволяет изменить настройки по умолчанию (которые подходят для большинства случаев) и, например, «перелинковать» несколько своих частных нод на случай недоступности всех публичных — как было описано выше, достаточно связности с любой одной нодой в сети для выхода в сеть второй ноды.

Вопрос о том, публиковать ли данные о своей ноде в списке публичных нод [12] остается на ваше личное усмотрение — с технической точки зрения частная нода ни чем не отличается от публичной.

Заключение

Протокол Tox позволяет не только писать ботов [13], обмениваться сообщениями, файлами или совершать аудио-видео вызовы, но и использовать его в качестве базового протокола для других сетевых задач.

Так, например, проекты tuntox [14] и toxvpn [15] используют протокол Tox для организации P2P соединения хостов за NAT пополняя список Full-Mesh VPN решений [16].

Существуют экспериментальные проекты toxmail [17] для организации почтового сообщения, toxscreen [18] для получения доступа к удаленному рабочему столу, toxshare [19] для файлообмена между доверенным кругом лиц.

Для экспериментов по написанию новых приложений вы можете использовать обертки (поддерживаемые и не очень) для других языков и платформ: python [20], rust [21], go [22], node.js [23] — практически неограниченный простор для новых идей и проектов.

Ссылки

Автор: antonbatenev

Источник [29]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/tox/116247

Ссылки в тексте:

[1] заблокировать централизованный Telegram: https://geektimes.ru/post/273340

[2] www.toxstats.com: https://www.toxstats.com

[3] список из известных bootstrap-нод: https://nodes.tox.chat

[4] libtoxcore: https://github.com/irungentoo/toxcore

[5] луковой маршрутизации: https://ru.wikipedia.org/wiki/Луковая_маршрутизация

[6] Tor: https://www.torproject.org/

[7] Folding@home: https://folding.stanford.edu/

[8] Вливаемся в tox-сообщество или установка ноды за 5 минут: https://habrahabr.ru/post/273901/

[9] tox-easy-bootstrap: https://github.com/abbat/tox.pkg/tree/master/tox-easy-bootstrap

[10] ссылке: http://software.opensuse.org/download.html?project=home%3Aantonbatenev%3Atox&package=tox-easy-bootstrap

[11] /etc/tox-easy-bootstrap.conf: https://github.com/abbat/tox.pkg/blob/master/tox-easy-bootstrap/tox-easy-bootstrap.conf

[12] списке публичных нод: https://wiki.tox.chat/users/nodes

[13] писать ботов: https://habrahabr.ru/post/264179/

[14] tuntox: https://github.com/gjedeer/tuntox

[15] toxvpn: https://github.com/cleverca22/toxvpn

[16] Full-Mesh VPN решений: https://habrahabr.ru/post/150151/

[17] toxmail: https://github.com/toxmail/toxmail

[18] toxscreen: https://github.com/saneki/toxscreen

[19] toxshare: https://github.com/TheLastProject/ToxShare

[20] python: https://github.com/abbat/pytoxcore

[21] rust: https://github.com/zetok/tox

[22] go: https://github.com/codedust/go-tox

[23] node.js: https://github.com/saneki/node-toxcore

[24] tox.viktorstanchev.com: http://tox.viktorstanchev.com/

[25] stats.letstox.com: https://stats.letstox.com/

[26] toktok.github.io: https://toktok.github.io/

[27] tox.pkg на github: https://github.com/abbat/tox.pkg

[28] tox.chat: https://tox.chat/

[29] Источник: https://habrahabr.ru/post/280208/