Читачі дізнаються, які клієнти підходять для Android, iOS, Linux, Windows та веб-інтерфейсів, як правильно організувати адміністрацію користувачів і забезпечити конфіденційність. Це покроковий гайд, який допоможе створити власний месенджер для сім’ї, команди або невеликої організації, зберігаючи максимальний рівень приватності та стабільності.
Сьогодні багато хто починає замислюватися над тим, щоб підняти власний сервер для обміну повідомленнями. Проблема з «самопальними» серверами та непопулярними протоколами полягає в тому, що важко перетягнути всіх знайомих чи колег у нову систему. Але якщо йдеться лише про спілкування в межах родини, невеликої групи однодумців або всередині компанії — це може бути чудовим рішенням.
Сьогодні як self-hosted альтернативу популярним месенджерам часто згадують Matrix, наприклад, з клієнтом Element. Я спробував і мені не сподобалося. Клієнти гальмівні, через нестабільний інтернет-канал все працює просто огидно, а сам сервер просто неповороткий і вкладає не надто багатий на процесор і пам’ять VPS навіть із парою клієнтів.
І тут мені згадалося про XMPP, він же Jabber. Він родом ще з тих часів, коли люди користувалися процесорами на 200-300 мегагерц і підключалися до інтернету через dial-up модеми – тобто він дуже невибагливий до ресурсів. Тим часом, розвиток його не завмер на місці, а на сьогоднішній день він вміє майже все те, що потрібно від сучасного месенджера: зберігання історії, передача файлів, аудіо-відео дзвінки, end-to-end шифрування, та інше.
Я налаштовуватиму XMPP-сервер Prosody. Система у мене на сервері Ubuntu 22.04
Підключаємо офіційні deb-репозиторії від проекту Prosody. Сам prosody є у звичайних ріпах Debian і Ubuntu, але там старі версії, а я раджу використовувати версію сервера не нижче 0.12, а в ідеалі версію 13.x, тому що в старіших версіях не вистачає деяких корисних фіч, і деякі модулі не включені в постачання і їх потрібно встановлювати.
Тому підключаємо ріпи від розробників, щоб мати найсвіжіші версії:
wget https://prosody.im/downloads/repos/$(lsb_release -sc)/prosody.sources -O/etc/apt/sources.list.d/prosody.sources apt update apt install prosody
В мене встановилася версія 13.0.2. Вона вимагає досить нового інтерпретатора Lua (Prosody написаний на Lua), і якщо при запуску сервісу воно лається на інтерпретатор, потрібно доустановити і вибрати правильний:
update-alternatives --config lua-interpreter # у списку вибираємо версію 5.4
Далі нам потрібний домен для роботи сервера, XMPP працює через TLS з усіма витікаючими. В принципі, можна використовувати і безкоштовний домен з якого-небудь dynu.com, freedns.afraid.org, або навіть sslip.io, але тут все впирається в довіру до сервісу – хто володіє доменом, той має доступ до всього (якщо ви не зробите certificate pinning). Параноїки можуть і без доменів використовувати самозгенеровані сертифікати, вручну додаючи їх до списку довірених – в prosody генерація самопідписаних сертифікатів робиться дуже легко командою prosodyctl cert generate hackyourmom.com (або використовуйте пряму IP-адресу сервера замість домену).
Окей, скажімо, ми використовуємо домен hackyourmom.com. Нам потрібно буде направити на IP-адресу вашого сервера сам hackyourmom.com, а також зробити піддомен типу upload.hackyourmom.com (трохи пізніше розповім навіщо), який теж буде вказувати на IP сервера.
Далі робимо отримання сертифікатів через LetsEncrypt для вашого домену (якщо воно вже є, можете пропустити):
apt install certbot certbot certonly --standalone -d hackyourmom.com -d upload.hackyourmom.com
Воно отримає від LetsEncrypt сертифікати та налаштує їх автоматичне оновлення.
Тепер настав час відредагувати конфіг сервера, він зазвичай знаходиться в /etc/prosody/prosody.cfg.lua.
На початку там йде список модулів, активованих на сервері. Я наведу те, що в результаті вийшло у мене, а коментарем – ! відзначу ті, що були відключені в конфізі за замовчуванням і які я увімкнув спеціально:
modules_enabled = {
"disco";
"roster";
"saslauth";
"tls";
"blocklist";
"bookmarks";
"carbons";
"dialback";
"limits";
"pep";
"private";
"smacks";
"vcard4";
"vcard_legacy";
"account_activity";
"cloud_notify";
"csi_simple";
"invites";
"invites_adhoc";
"invites_register";
"ping";
"register";
"time";
"uptime";
"version";
"cloud_notify_extensions"; -- ! додав
"turn_external"; -- ! додав
"mam"; -- ! додав
"muc_mam"; ! -- теж
"csi_simple"; -- ! додав
"pubsub"; -- ! може бути корисним
-- "http_file_share"; -- ! ось цей використовується, але закоментований, трохи згодом розповім чому
"admin_adhoc";
"admin_shell";
}
Модуль mod_cloud_notify_extensionsне входить у стандартне постачання, тому його треба буде встановити окремо:
apt install liblua5.4-dev prosodyctl install --server=https://modules.prosody.im/rocks/ mod_cloud_notify_extensions
XMPP працює за принципом федерації – тобто користувачі вашого сервера можуть спілкуватися з користувачами, підключеними до інших серверів, і навпаки. Якщо вам потрібно зробити ізольований сервер, щоб ніхто не заходив на нього збоку, відключіть модуль s2s:
modules_disabled = {
"s2s"; -- Handle server-to-server connections
}
Також Prosody дозволяє вибрати, як зберігатимуться дані користувачів (акаунти, повідомлення, тощо). За промовчанням використовується сховище на простих файлах. Можна вибрати, щоб використовувалася база SQLite, це буде більш ефективно. Для серверів з великою кількістю користувачів та повідомлень можна використовувати MySQL та PostgreSQL.
Далі скролимо нижче до розділу VirtualHost. За промовчанням там прописаний localhost, замінюємо його на наш основний домен:
VirtualHost "hackyourmom.com"
Зберігаємо конфіг, запускаємо:
prosodyctl --root cert import /etc/letsencrypt/live
Prosody автоматично знайде сертифікати для доменів та скопіює їх до себе для використання. Щоб вони оновлювалися автоматично, можна додати хук, створивши тип файлу/etc/letsencrypt/renewal-hooks/deploy/prosody.sh з вмістом.
#!/bin/sh /usr/bin/prosodyctl --root cert import /etc/letsencrypt/live
І зробити його виконуваним:chmod +x /etc/letsencrypt/renewal-hooks/deploy/prosody.sh
У принципі, все майже готове. Ми налаштували сервер з усіма необхідними модулями, сертифікатами та іншим. І навіть E2E-шифрування (OMEMO) буде працювати з коробки, якщо воно підтримується клієнтами.
Але є ще кілька нюансів.
Перше – це передача файлів. Сам собою XMPP передбачає передачу файлів лише peer to peer без участі сервера. Це вимагає, щоб обидва клієнти в момент передачі знаходилися онлайн, та й у наші часи повсюдного NAT’а практично не працює.
Є рішення – використовувати модуль http.file_share. Тоді при відправці файлу через чат, клієнт заллє його на сервер HTTP, а співрозмовники отримають посилання на завантажений файл. URL представляє собою величезний UUID, так що перебором зібрати файли на сервері не вийде.
Додамо до конфігу наступний текст прямо під описом вашого VirtualHost:
VirtualHost "hackyourmom.com"
disco_items = {
{ "upload.hackyourmom.com", "file sharing service" },
}
Component "upload.hackyourmom.com" "http_file_share"
http_file_share_expires_after = 31 * 24 * 60 * 60 -- скільки повинні зберігатися файли на сервері, у моєму прикладі 31 день
http_file_share_global_quota = 1024*1024*1024*10 -- обмеження об'єму сховища на сервері, в моєму випадку 10 гігабайт
Оскільки ви тут явно оголосили “component”, не треба перераховувати “http_file_share” у списку модулів на початку конфігу (у мене він там закоментований), інакше сервер свариться.
Якщо з якихось причин вам не подобається ідея з HTTP-посиланнями, є ще модуль proxy_65(https://prosody.im/doc/modules/mod_proxy65), який дозволяє передавати файли через сервер (використовуючи його як проксі, щоб обійти проблему прямих підключень через NAT), але не зберігаючи їх на сервері.
Друге – це аудіо/відео дзвінки. В принципі, того, що ми маємо у конфізі, вже достатньо для них. Для встановлення з’єднань між клієнтами для аудіо-відео дзвінків в умовах неможливості прямих підключень через NAT’ клієнти будуть використовувати публічні STUN/TURN сервери.
Однак якщо ви параноїк, або хочеться ні від кого не залежати, можна підняти свій TURN-сервер:
apt install coturn
Далі редагуємо /etc/turnserver.conf:
realm=hackyourmom.com use-auth-secret static-auth-secret=verysecretsecret
Перезапускаємо coturn: systemctl restart coturnі додамо до конфіг Prosody вище опису вашого VirtualHost наступні рядки:
turn_external_host = "hackyourmom.com" turn_external_port = 3478 turn_external_secret = "verysecretsecret"
Звичайно, coturn ви можете розмістити на окремому сервері, наприклад, зробивши для нього домен turn.hackyourmom.com І ще маленький штрих – налаштувати розраховані на багато користувачів кімнати (типу як “групи” в Телезі).
Додамо:
Component "conference.hackyourmom.com" "muc"
Під вашим VirtualHost. За промовчанням кімнати можна створювати всім, але є параметр:
restrict_room_creation = false
з варіантами “false” (можна всім), “true” (можна тільки адмінам) або “local” (можна тільки користувачам вашого сервера, чужинці, що прийшли по server2server у прольоті). Там є опція:
component_admins_as_room_owners = true
Автоматична дає адмінам сервера права власника у всіх кімнатах, та:
max_history_messages = 2000
Визначальна, скільки повідомлень зберігати історія. Ось тепер усе готове. Можна запустити перевірку конфіга командою prosodyctl check– утиліта перевірить, що все налаштовано правильно і дасть поради, якщо щось можна покращити. Не забуваємо після виправлення конфігу перезапустити сервер: systemctl restart prosodyі можна підключатися.
Як створювати нові облікові записи на сервер? У конфізі можна дозволити реєстрацію для всіх бажаючих через клієнти (з цим акуратніше), а можна додавати когось треба вручну:
prosodyctl adduser [email protected]
Доданого користувача можна також занести в конфізі до списку адмінів сервера, що дасть йому більше повноважень (управління користувачами, якщо клієнт це підтримує, ad-hoc-команди, перегляд статистики, і т.д.):
admins = { "[email protected]" }
З мобільними клієнтами все досить непогано. Для Android найкращим з них вважається Conversations. У Google Play він коштує пару доларів, але можна безкоштовно встановити його з F-Droid. З альтернатив мені ще сподобався Blabber.im Відеодзвінки працюють і там і там.
На iOS традиційно хорошими клієнтами вважаються Siskin IM та його форк Snikket (я чесно кажучи, різниці не помітив). Відеодзвінки працюють. Ще іноді згадують клієнта ChatSecure, з ним обережніше – він здається в напівмертвому стані, принаймні домен, який там використовується для push-повідомлень вже не існує.
Під дестктоп… Ну, там таке. Є багато старих “класичних” клієнтів типу Gajim, Pidjin, Psi, але вони мають інтерфейс із 90-х і часто не підтримують сучасні фічі. Якщо у вас немає алергії на Electron, раджу ConverseJS – стильний та зручний інтерфейс, вміє все що треба (крім аудіодзвінків), може запускатися як Electron-додаток, а можна поставити його на свій сервер та підключатися з браузера.
З клієнтів, у яких заявлена підтримка аудіовідіодзвінків – Movim (теж веб), і хтось хвалив Dino (Linux, але є неофіційне складання під Windows), і BeagleIM під MacOS. Kaidan під Linux виглядає дуже схоже на Віз, але відеодзвінки, здається, не вміє.
І ще є пропрієтарний AstraChat, який, як заявлено, вміє все, але скачати просто так з сайту розробника його не можна (потрібна реєстрація на корп. емайл), на гітхабі хтось викладає бінарники, але це вже на ваш страх та ризик.
І насамкінець питання – а наскільки вся ця справа стійка до блокувань, якщо РКН вирішить якось обчислити і заблокувати саме ваш сервер з якоїсь причини? XMPP за замовчуванням працює за стандартним портом 5222. Можна поставити на 443 порт щось типу sslh, за яким ще стоятиме нешкідливий веб-сервер, і коннектитися клієнтами на порт 443 як це звичайний HTTPS.
Веб-сервер для файлів у Prosody також висить на нестандартному порту і віддає сторінку prosody при запиті з урлом /. Можна сховати його за веб-сервером типу Nginx або Caddy, щоб по / вони віддавали свою сторінку, і при 404 помилці – теж (ну і само собою слухали на 443 порту, в модулі http_file_share є параметр, який повідомляє користувачам куди треба стукатися).
Як ще ефективніше рішення, існують розширення XMPP до роботи через чистий HTTP (модуль bosh) і вебсокеты (модуль websocket), що у теорії дозволяє повністю замаскуватися під звичайний веб-сервер і навіть працювати через CDN. Але клієнтів, які вміють подібне, мені поки що не зустрілося, якщо хтось знає – напишіть у коментарях.