Новая жизнь для XMPP. Делаем мессенджер, который не получится заблокировать

_6r83zc147s5n5_ckq5vdmakl24.jpeg


Идея сделать независимый от корпораций P2P мессенджер не нова, однако разработка нового протокола и клиентских приложений для него достаточно дорогой и долгий процесс. А что, если использовать старый добрый XMPP, в котором уже все давно продумано и запилено?


Но это же не настоящий peer-to-peer, скажете вы, для работы XMPP нужен собственный сервер и домен. Это так, но мы можем запустить сервер на локалхосте, а для связи с серверами других пользователей использовать скрытый сервис в виртуальной сети I2P. Использование I2P избавит нас от необходимости платить за домен с хостингом, а так же защитит наши коммуникации от преступной онлайн-слежки.


Таким образом, получаем:


  • Гибридный P2P мессенджер, который можно запускать и на пользовательских устройствах, и на полноценном сервере.
  • Фичи, которых не хватает другим P2P мессенджерам: оффлайн сообщения, хранение контактов и истории «в облаке», работа нескольких клиентов с одним аккаунтом.
  • Готовые клиентские приложения на любой вкус.
  • За счет использования I2P, неуязвим для различных *надзоров (сори за мат).


Приступим же к реализации…


Установка I2P и создание серверного тоннеля

В данном руководстве, в качестве I2P роутера будем использовать легковесный C++ клиент i2pd. Инструкция по установке есть в документации.


После установки создаем серверный I2P туннель — это виртуальный адрес, по которому наш XMPP сервер будет доступен для остального мира. В файл tunnels.conf дописываем следующие строки:


[prosody-s2s]
type=server
host=127.0.0.1
port=5269
inport=5269
keys=prosody.dat

[prosody-c2s]
type=server
host=127.0.0.1
port=5222
inport=5222
keys=prosody.dat


Если планируется использование только на локалхосте, секцию prosody-c2s можно не добавлять. Перезагружаем i2pd, чтобы применить настройки. Ищем I2P адрес созданного туннеля в веб-консоли http://127.0.0.1:7070/ на странице I2P tunnels.


9wcsctrhsufhijv8vcs0ch7e0x0.png


Можно так же узнать b32 адрес нового туннеля, грепнув логи:


grep "New private keys file" /var/log/i2pd/i2pd.log | grep -Eo "([a-z0-9]+).b32.i2p" | tail -n1


Сохраните этот xxx.b32.i2p адрес, это будет домен для вашего XMPP сервера.


Установка и настройка XMPP сервера

В качестве XMPP сервера будем использовать prosody, он самый легкий и под него есть готовый модуль для работы через I2P. Установка описана в официальной документации, в Ubuntu делается элементарно apt install prosody.


Для работы mod_darknet нужна lua библиотека bit32. Если у вас lua версии меньше 5.2 (скорее всего) выполняем apt install lua-bit32.


Устанавливаем модуль mod_darknet. Он нужен, чтобы prosody делал исходящие соединения через Socks5 сервер i2pd. Скачиваем этот файл в директорию модулей prosody, обычно это /usr/lib/prosody/modules.


Теперь редактируем конфиг /etc/prosody/prosody.cfg.lua. Замените xxx.b32.i2p на свой адрес:


interfaces = { "127.0.0.1" };
admins = { "admin@xxx.b32.i2p" };
modules_enabled = {
    "roster"; "saslauth"; "tls"; "dialback"; "disco"; "posix"; "private"; "vcard";  "ping";  "register"; "admin_adhoc"; "darknet"; 
};
modules_disabled = {};
allow_registration = false;
darknet_only = true;
c2s_require_encryption = true;
s2s_secure_auth = false;
authentication = "internal_plain";

-- On Debian/Ubuntu
daemonize = true;
pidfile = "/var/run/prosody/prosody.pid";
log = {
    error = "/var/log/prosody/prosody.err";
    "*syslog";
}
certificates = "certs";

VirtualHost "xxx.b32.i2p";
ssl = {
    key = "/etc/prosody/certs/xxx.b32.i2p.key";
    certificate = "/etc/prosody/certs/xxx.b32.i2p.crt";
}


Последний шаг в настройке prosody — генерация сертификатов шифрования. В никсах это делается так:


openssl genrsa -out /etc/prosody/certs/xxx.b32.i2p.key 2048
openssl req -new -x509 -key /etc/prosody/certs/xxx.b32.i2p.key -out /etc/prosody/certs/xxx.b32.i2p.crt -days 3650
chown root:prosody /etc/prosody/certs/*.b32.i2p.{key,crt}
chmod 640 /etc/prosody/certs/*.b32.i2p.{key,crt}


Перезагрузите сервер prosody для применения настроек.


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


Создание аккаунтов и подключение клиентов

Добавляем админский аккаунт:


prosodyctl adduser admin@xxx.b32.i2p


Теперь настраиваем XMPP клиент (например Pidgin).


9qrspnexmf7c76xxudtbyq5gywy.png


Если вы подключаетесь к локалхосту, то в настройках клиента указываем подключение к серверу 127.0.0.1 порт 5222.


chaqyudpt9_klboqzh8js266qvq.png


Если подключаетесь к серверу удаленно через I2P, то указывайте в настройках прокси Socks5 127.0.0.1:4447.


tho1mild7peimdh1hznm9botvzs.png


Если все сделано правильно, вы сможете добавлять других пользователей в I2P федерации и переписываться с ними. Так же, возможно настроить ваш уже работающий сервер в обычном интернете на переписку с серверами внутри I2P. Для этого все остальные пользователи должны будут добавить в свой конфиг prosody маппинг для вашего домена. Например, так это сделано у меня для общения с сервером i2p.rocks:


darknet_map = {
    ["i2p.rocks"] = "ynkz7ebfkllljitiodcq52pa7fgqziomz4wa7tv4qiqldghpx4uq.b32.i2p";
    ["muc.i2p.rocks"] = "ynkz7ebfkllljitiodcq52pa7fgqziomz4wa7tv4qiqldghpx4uq.b32.i2p";
}


Вот собственно и все. Happy chatting!

© Habrahabr.ru