Идея сделать независимый от корпораций P2P мессенджер не нова, однако разработка нового протокола и клиентских приложений для него достаточно дорогой и долгий процесс. А что, если использовать старый добрый XMPP, в котором уже все давно продумано и запилено?
Но это же не настоящий peer-to-peer, скажете вы, для работы XMPP нужен собственный сервер и домен. Это так, но мы можем запустить сервер на локалхосте, а для связи с серверами других пользователей использовать скрытый сервис в виртуальной сети I2P. Использование I2P избавит нас от необходимости платить за домен с хостингом, а так же защитит наши коммуникации от преступной онлайн-слежки.
Таким образом, получаем:
- Гибридный P2P мессенджер, который можно запускать и на пользовательских устройствах, и на полноценном сервере.
- Фичи, которых не хватает другим P2P мессенджерам: оффлайн сообщения, хранение контактов и истории "в облаке", работа нескольких клиентов с одним аккаунтом.
- Готовые клиентские приложения на любой вкус.
- За счет использования I2P, неуязвим для различных \*надзоров (сори за мат).
Приступим же к реализации...
Установка I2P и создание серверного тоннеля
В данном руководстве, в качестве I2P роутера будем использовать легковесный C++ клиент i2pd. Инструкция по установке есть в документации.
После установки создаем серверный I2P туннель -- это виртуальный адрес, по которому наш XMPP сервер будет доступен для остального мира. В файл tunnels.conf дописываем следующие строки:
Code: Select all
[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
Можно так же узнать b32 адрес нового туннеля, грепнув логи:
Code: Select all
grep "New private keys file" /var/log/i2pd/i2pd.log | grep -Eo "([a-z0-9]+).b32.i2p" | tail -n1
Установка и настройка XMPP сервера
В качестве XMPP сервера будем использовать prosody, он самый легкий и под него есть готовый модуль для работы через I2P. Установка описана в официальной документации, в Ubuntu делается элементарно
Code: Select all
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 на свой адрес:
Code: Select all
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";
}
Code: Select all
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}
Тут нужно небольшое отступление. В сети I2P любые соединения зашифрованы сквозным шифрованием и, казалось бы, дополнительное шифрование тут излишне. Но, на практике, оказалось проще сгенерировать ключи, чем пытаться настроить все программы на использование открытого текста. Вы можете попробовать, но я вас предупреждал.
Создание аккаунтов и подключение клиентов
Добавляем админский аккаунт:
Code: Select all
prosodyctl adduser admin@xxx.b32.i2p
Если вы подключаетесь к локалхосту, то в настройках клиента указываем подключение к серверу 127.0.0.1 порт 5222.
Если подключаетесь к серверу удаленно через I2P, то указывайте в настройках прокси Socks5 127.0.0.1:4447.
Если все сделано правильно, вы сможете добавлять других пользователей в I2P федерации и переписываться с ними. Так же, возможно настроить ваш уже работающий сервер в обычном интернете на переписку с серверами внутри I2P. Для этого все остальные пользователи должны будут добавить в свой конфиг prosody маппинг для вашего домена. Например, так это сделано у меня для общения с сервером i2p.rocks:
Code: Select all
darknet_map = {
["i2p.rocks"] = "ynkz7ebfkllljitiodcq52pa7fgqziomz4wa7tv4qiqldghpx4uq.b32.i2p";
["muc.i2p.rocks"] = "ynkz7ebfkllljitiodcq52pa7fgqziomz4wa7tv4qiqldghpx4uq.b32.i2p";
}
Вот собственно и все. Happy chatting!