Prosody позволяет обмениваться мгновенными сообщениями по протоколу XMPP. По сравнению с другими аналогами, в его копилке есть низкое потребление ресурсов, простота в использовании и расширяемость.
Ссылки на документацию:
На офф. сайте представлена хорошая документация, в процессе настройки будем опираться на нее.
Blog:
Обязательно к прочтению для обновления с v0.11.x.
Устанавливать будем на примере:
- Single-Board Computer: ASUS Tinker Board | Proxmox VE: KVM VM;
- OS: Armbian Buster | Debian Bullseye;
- Prosody IM: 0.12.3.
Краткая сводка:
Для хранилища архива сообщений и информации о созданных пользователях будет использоваться MariaDB.
Архив сообщений будет реализован с помощью "mod_mam: (XEP-0313)", он присутствует в стандартном наборе модулей. В качестве бэкенда хранилища базы данных SQL, будет выступать "mod_storage_sql", он также присутствует в стандартном наборе. Для того, чтобы у клиентских приложений была возможность загружать файлы на сервер по HTTP(S), будет использоваться "mod_http_file_share: (XEP-0363)", доступен в стандартном наборе начиная с "v0.12.0".
Установка: [link]
Импортируем новый репозиторий, скачаем и добавим ключ от него. Обновим списки пакетов для дистрибутива с добавленным репозиторием. И установим пакет.
# echo deb http://packages.prosody.im/debian $(lsb_release -sc) main | tee /etc/apt/sources.list.d/prosody.list
# wget https://prosody.im/files/prosody-debian-packages.key -O/etc/apt/trusted.gpg.d/prosody.gpg
# apt update
# apt install prosody
- Указываем предпочитаемую версию Lua: (v5.1)
# update-alternatives --config lua-interpreter
- Узнать информацию о установленном пакете;
# prosodyctl about
--- Или через инструмент для управления внешними репозиториями:
# apt install extrepo
# extrepo enable prosody
# apt update
# apt install prosody
Подготовка:
Пропишем админов и название виртуального хоста:
- Создаем бекап конфигурационного файла;
# cp /etc/prosody/prosody.cfg.lua{,.bkp}
- Прописываем:
# nano /etc/prosody/prosody.cfg.lua
admins = { "mtv@im.open-networks.ru" }
VirtualHost "im.open-networks.ru"
Удалим стандартные сертификаты:
# rm -R /etc/prosody/certs/localhost.*
Создание самоподписанных сертификатов:
Prosody сам может сгенерировать самоподписанные сертификаты.
# prosodyctl cert generate im.open-networks.ru
- Config written to /var/lib/prosody/im.open-networks.ru.cnf
- Certificate written to /var/lib/prosody/im.open-networks.ru.crt
# mv /var/lib/prosody/im.open-networks.ru.* /etc/prosody/certs/
# chown prosody:prosody /etc/prosody/certs/im.open-networks.ru*
# chmod 0640 /etc/prosody/certs/im.open-networks.ru*
- Или же можно воспользоваться средствами openssl, и сгенерировать также сертификаты,
# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/prosody/certs/im.open-networks.ru.key -out /etc/prosody/certs/im.open-networks.ru.crt
- Усилим защиту, используя алгоритм Диффи-Хеллмана для создания ключа.
# openssl dhparam -out /etc/prosody/certs/dhparam_p.pem 2048
Включаем шифрование: [link]
Пропишем сгенерированные ключи и сертификаты. Для каждого "VirtualHost" они свои. "tls_profile" или "ciphers" - оставляем что-то одно.
# nano /etc/prosody/prosody.cfg.lua
certificates = "certs"
c2s_require_encryption = true
s2s_require_encryption = true
tls_profile = "modern"
ssl = {
key = "/etc/prosody/certs/im.open-networks.ru.key";
certificate = "/etc/prosody/certs/im.open-networks.ru.crt";
dhparam = "/etc/prosody/certs/dhparam_p.pem";
ciphers = "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256";
}
В переменной "ciphers" указываем использовать более стойкие наборы шифрования.
Проверка правильности конфигурации сертификата:
# prosodyctl check certs
Или ипорт от Let's Encrypt: [link]
Уже сгенерированных сертификатов. Они автоматически скопируются в "/etc/prosody/certs/".
# cd /etc/prosody/
# prosodyctl --root cert import /etc/letsencrypt/live
Установка Mariadb-Server:
# apt install mariadb-server
Создаем новую базу, пользователя и присваиваем ей привилегии:
# mysql -u root -p'pass'
# Создаем пользователя:
MariaDB> create user 'prosody'@'localhost' identified by 'pass';
# Создаем БД:
MariaDB> create database `prosody` character set = 'utf8';
# Присваиваем права:
MariaDB> GRANT ALL PRIVILEGES ON `prosody`.* to `prosody`@localhost;
MariaDB> FLUSH PRIVILEGES;
MariaDB> quit;
+++
- Удалить базу:
MariaDB> DROP DATABASE prosody;
- Удалить пользователя:
MariaDB> DROP USER 'prosody'@'localhost';
- Изменить пароль пользователю:
MariaDB> SET PASSWORD FOR 'prosody'@'localhost' = PASSWORD('pass');
Использование с MySQL: mod_mam (XEP-0313) + mod_storage_sql: [link] | [link]
# apt install lua-dbi-mysql
# nano /etc/prosody/prosody.cfg.lua
modules_enabled = {
-- Nice to have
"mam"; -- Store recent messages to allow multi-device synchronization
}
storage = "sql" -- Default is "internal"
sql = { driver = "MySQL", database = "prosody", host = "localhost", port = "3306", username = "prosody", password = "pass" }
archive_expires_after = "1w" -- Remove archived messages after 1 week
Применяем изменения:
- Проверям конфиг на наличие ошибок:
# prosodyctl check config
- Перезапускаем сервис:
# systemctl restart prosody.service && systemctl status prosody.service
Управление пользователями:
- Основные команды:
# prosodyctl adduser test@im.open-networks.ru
# prosodyctl register mtv im.open-networks.ru 'pass'
# prosodyctl register bel im.open-networks.ru 'pass'
# prosodyctl passwd JID
# prosodyctl deluser JID
- Просмотреть доступные команды:
# prosodyctl
- Загруженные файлы будут хранится на отдельном примонтированном разделе:
# mkdir -p /mnt/data/prosody/http_file_share
# chown -R prosody:prosody /mnt/data/prosody
# chmod 0700 /mnt/data/prosody
# ln -s /mnt/data/prosody/http_file_share/ /var/lib/prosody/upload%2eim%2eopen%2dnetworks%2eru/http_file_share
# chown prosody:prosody /var/lib/prosody/upload%2eim%2eopen%2dnetworks%2eru/http_file_share
- Чтобы избежать дополнительных записей для DNS и сертификатов, установим свой основной домен в http_host = "im.open-networks.ru" и поместим его над VirtualHost.
# nano /etc/prosody/prosody.cfg.lua
http_host = "im.open-networks.ru"
---Set up a file sharing component
Component "upload.im.open-networks.ru" "http_file_share"
http_file_share_expires_after = 14 * 24 * 60 * 60 -- 14 Days
http_file_share_size_limit = 64*1024*1024 -- 64 MiB
http_file_share_daily_quota = 128*1024*1024 -- 128 MiB per day per user
http_file_share_global_quota = 4608*1024*1024 -- 4.5 GiB total
- Или добавить в глобальную конфигурацию (предварительно получив сертификаты):
https_ssl = {
key = "/etc/prosody/certs/upload.im.open-networks.ru.key";
certificate = "/etc/prosody/certs/upload.im.open-networks.ru.crt";
dhparam = "/etc/prosody/certs/dhparam_p.pem";
}
- Проверяем настройки:
# prosodyctl shell module info http_file_share
Modules:
- Prosody Community Modules: [link];
- Prosody Plugin Installer: [link];
- Installing modules: [link].
Prosody всегда будет искать в своей исходной директории модули:
*/usr/lib/prosody/modules
- Ее можно узнать через команду:
# prosodyctl about
Plugin directories:
/var/lib/prosody/modules
/usr/lib/prosody/modules/
Но эта опция позволяет указать дополнительные места, где модули будут искаться в первую очередь.
plugin_paths = { "/var/lib/prosody/modules" }
Via LuaRocks:
# nano /etc/prosody/prosody.cfg.lua
plugin_server = "https://modules.prosody.im/rocks/"
Полезные модули:
- mod_limit_auth - Позволяет установить ограничение на количество неудачных попыток аутентификации для каждого IP-адреса.
- mod_log_auth - Позволяет регестрировать IP-адрес при неудачной попытке аутентификации. Необходим в связке с Fail2Ban.
Установка:
# prosodyctl install mod_limit_auth
# prosodyctl install mod_log_auth
- Полезные команды:
# prosodyctl list
# prosodyctl list --outdated
# prosodyctl remove mod_example_module
Настройка:
# nano /etc/prosody/prosody.cfg.lua
- Добавляем в секцию:
modules_enabled = {
-- External modules
--"limit_auth";
"log_auth";
}
- Должно находиться над параметром VirtualHost;
-- Conf external modules
--mod_limit_auth
limit_auth_period = 60 -- 1 min
limit_auth_max = 3
limit_auth_tarpit_delay = 900 -- 15 min
# systemctl restart prosody.service
Via Mercurial (hg):
Скачиваем общедоступное хранилище модулей. У меня директория "/mnt/data" - это примонтированный раздел;
# mkdir /mnt/data/prosody && cd /mnt/data/prosody/
# apt install mercurial
# hg clone https://hg.prosody.im/prosody-modules/ prosody-modules
# chown -R prosody:prosody /mnt/data/prosody/
- Для обновления,
# hg pull --update
# mkdir /var/lib/prosody/modules
# cp -R prosody-modules/mod_limit_auth/ /var/lib/prosody/modules/
# cp -R prosody-modules/mod_log_auth/ /var/lib/prosody/modules/
# chown -R prosody:prosody /var/lib/prosody/modules/
SRV records: [link]
_xmpp-client._tcp.open-networks.ru. 3600 IN SRV 0 5 5222 im.open-networks.ru.
> nslookup -type=srv _xmpp-client._tcp.open-networks.ru. ns1.firstbytedns.net.
# prosodyctl check dns
Настройка Fail2ban + Nftables:
# systemctl start nftables.service
# systemctl status nftables.service
# systemctl enable nftables.service
# apt install fail2ban
# systemctl status fail2ban.service
Для работы необходима установка модуля:
Установка модуля:
# prosodyctl install mod_log_auth
- Или:
# cd /mnt/data/prosody/
# apt install mercurial
# hg clone https://hg.prosody.im/prosody-modules/ prosody-modules
# cp -R prosody-modules/mod_log_auth/ /var/lib/prosody/modules/
# chown -R prosody:prosody /var/lib/prosody/modules/
Настройка основного конфига F2B: fail2ban.local
Зададим время, после которого необходимо удалять баны из базы данных. Должно быть ">=" чем "bantime".
# cp /etc/fail2ban/fail2ban.{conf,local}
# cat > /etc/fail2ban/fail2ban.local << EOF
[Definition]
dbpurgeage = 3w
EOF
Настройка конфига: jail.local
# cp /etc/fail2ban/jail.{conf,local}
# cat > /etc/fail2ban/jail.local << EOF -или- (# cat << EOF > /etc/fail2ban/jail.local)
[DEFAULT]
findtime = 1d
bantime = 2w
maxretry = 1
ignoreip = 127.0.0.1 127.0.0.0/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
# banning action
banaction = nftables-multiport
banaction_allports = nftables-allports
EOF
../action.d/nftables.conf:
В файле ../action.d/nftables.conf в разделе [Init] - можно просмотреть дополнительные настройки.
Например (blocktype = reject, table = f2b-table).
- Задаем действие для заблокированных IP в цепочке f2b-chain:
# nano /etc/fail2ban/action.d/nftables.conf
[Init]
blocktype = drop
### Правила F2B:
- Jail:
# nano /etc/fail2ban/jail.d/prosody.conf
[prosody]
enabled = true
port = 5222
filter = prosody-auth
logpath = /var/log/prosody/prosody*.log
Filter:
# nano /etc/fail2ban/filter.d/prosody-auth.conf
[Definition]
failregex = Failed authentication attempt \(not-authorized\) for user .* from IP: <HOST>
ignoreregex =
- Перезапускаем сервисы:
# systemctl restart nftables.service fail2ban.service
- Перечитать настройки:
# fail2ban-client reload
Проверка работы:
- f2b:
# fail2ban-client status
# fail2ban-client status prosody
# fail2ban-client set prosody unbanip 1.2.3.4 | banip - забанить
# fail2ban-client unban --all
- nft:
# nft list ruleset
# nft list table inet f2b-table
- Проверка Regex:
# fail2ban-regex /var/log/prosody/prosody.log /etc/fail2ban/filter.d/prosody-auth.conf
A/V звонки в Conversations (XEP-0215): [link] | [link]
Для работы аудио/видео звонков небходим клиент начиная с версии 2.8.0+, поддержка на стороне сервера/клиента мода XEP-0215, а так же, для прохождения NAT - настроенный сервер Coturn.
Ссылки на документацию:
Заметки:
UDP vs TCP vs TLS: Использование TLS не увеличивает безопасность, поскольку вызовы всегда шифруются сквозным шифрованием с помощью DTLS-SRTP. Также использование TCP(TLS) вместо UDP может отрицательно сказаться на задержке и производительности. Единственное преимущество использования TURN over TLS на порту 443 состоит в том, что у вас больше шансов пройти через ограничения брандмауэров. Однако это должен быть только запасной вариант, а не механизм подключения по умолчанию.
Настройка сервера Coturn:
- STUN (Session Traversal Utilities for NAT) - позволяет клиенту, находящемуся за сервером трансляции адресов (или за несколькими такими серверами), определить свой внешний IP-адрес. та информация используется для установления соединения UDP между двумя хостами в случае, если они оба находятся за маршрутизатором NAT.
- TURN (Traversal Using Relay NAT) - позволяет узлу за NAT или брандмауэром получать входящие данные через TCP или UDP соединения. Такая возможность особенно актуальна для узлов позади симметричных NAT, или брандмауэров, которые собираются стать принимающей стороной в соединении с одним конкретным узлом (peer-ом).
Устанавливаем пакет:
# apt install coturn
- Проверяем статус службы:
# systemctl status coturn
- Делаем бекап основного конфигурационного файла:
# cp /etc/turnserver.conf{,.bkp}
Выполняем базовую настройку:
Т.к. сервер coturn находится за NAT, то указываем в "istening-ip" наш внутренний адрес. В роутере настраиваем DNAT по протоколу UDP с внешнего IP:3478 на внутренний.
# nano /etc/turnserver.conf
listening-port=3478 # Порт для прослушивания;
listening-ip=local_ip # IP для прослушивания ( м.б. как WAN/LAN);
external-ip=global_ip/local_ip # Сопоставление внешнего с внутренним IP, в случае с NAT;
fingerprint # Включить использование отпечатков для TURN сообщений;
use-auth-secret # Включить использование секретной фразы. Переопределяет lt-cred-mech;
static-auth-secret=pass_secret # Секретная фраза;
realm=im.open-networks.ru # Область действия, указывается домен;
no-tcp # Отключение tcp протокола;
no-tls # Отключение tls протокола;
no-dtls # Отключение dtls протокола;
no-stdout-log # Перевести ведение логов в файл;
log-file=/var/log/turn.log # Путь к файлу для логов;
#syslog # Отклаем ведение логов в системный журнал;
simple-log # Не добавлять в название к файлу логов PID и дату;
secure-stun # Требовать аутентификацию при запросах привязки STUN;
no-software-attribute # Скрыть версию программного обеспечения;
Применяем изменения:
Переопределение вывода логов. По умолчанию логи выводятся в системный журнал - syslog.
# touch /var/log/turn.log
# chown turnserver:turnserver /var/log/turn.log
# chmod 0640 /var/log/turn.log
# systemctl restart coturn
Настройка автозапуска coturn:
# nano /etc/default/coturn
# sed -i '/TURNSERVER_ENABLED/c\TURNSERVER_ENABLED=1' /etc/default/coturn
Настройка ротации логов:
# nano /etc/logrotate.d/coturn
/var/log/coturn.log {
weekly
rotate 3
compress
delaycompress
missingok
notifempty
postrotate
systemctl kill -sHUP coturn.service
endscript
create 640 turnserver turnserver
}
Для связи Coturn с Prosody: relay
Т.к. Coturn установлен на том же сервере что Prosody, то эти порты пробрасывать не нужно.
#min-port=49152
#max-port=65535
Настройка XEP-0215 в реализации mod_turn_external:
# nano /etc/prosody/prosody.cfg.lua
modules_enabled = {
-- Nice to have
turn_external"; -- Provide external STUN/TURN service for e.g. audio/video calls
turn_external_host = "im.open-networks.ru"
turn_external_secret = "pass_secret"
# systemctl restart prosody.service && systemctl status prosody.service
Сервис проверки работоспособности STUN/TURN: [link]
Для проверки, необходимо отключить опцию "secure-stun" в /etc/turnserver.conf. Если используется "use-auth-secret", то работу "relay - turn" проверить не получится т.к. работает только с "lt-cred-mech".
stun:im.open-networks.ru:3478
turn:im.open-networks.ru:3478 [mtv:mtv]
Для работы сервера TURN:
Параметр "lt-cred-mech" - only long-term users.
- Обязательно необходимо отключить:
# nano /etc/turnserver.conf
#use-auth-secret
#static-auth-secret
- Вместо этого включить:
relay-ip=local_ip - можно опустить;
lt-cred-mech
- И задать пользователя и пароль:
# turnadmin -a -u mtv -p pass -r im.open-networks.ru
Далее проверяем в тесте relay чтобы были записи напротив каждого relay.
Управление Turnadmin:
По умолчанию сервер TURN использует анонимный доступ. Но при условии выключенного "use-auth-secret".
- Через консоль: ( флаги: -A: админ, -a: обычный пользователь)
# turnadmin -A -u MTv -p pass
# turnadmin -a -u mtv -p pass -r im.open-networks.ru
- Вывести список пользователей или админов:
# turnadmin -l / -L
- Удалить админа:
# turnadmin -D -u MTv -r im.open-networks.ru
- Удалить пользователя:
# turnadmin -d -u mtv -r im.open-networks.ru
Проблемы с TURN: