Matrix: децентрализованные открытые мессенджеры с E2E-шифрованием. Обзор возможностей и настройка своего сервера

от автора

В этой статье я расскажу о протоколе Matrix и мессенджерах, основанных на нем, а так же приведу инструкцию по настройке своего сервера и клиентов.

Matrix — открытый протокол мгновенного обмена сообщениями и файлами с поддержкой голосовой и видеосвязи. Почему стоит обратить на него внимание, если у нас уже есть WhatsApp и Telegram? Причин несколько.

Во-первых, в последние дни Роскомнадзор снова начал развлекаться блокировками WhatsApp и Telegram, и иногда у него это даже получается более-менее успешно. В таких условиях всегда неплохо иметь запасной вариант, и Matrix здесь очень хорошо подходит, потому что во-первых он позволяет создавать свои собственные сервера, а во-вторых его протокол со стороны выглядит как самый обычный HTTPS.

Во-вторых, все больше и больше людей не доверяют WhatsApp и Telegram. В случае с Matrix же можно поднять свой личный сервер, протокол Matrix — открытый, исходники клиентов — открыты, исходники серверов — тоже открыты, а в самом протоколе end-to-end шифрование включено для чатов по умолчанию из коробки (в отличие, например, от Telegram, где оно доступно только в «секретных чатах»). Ну и само собой, не требуется нигде вводить телефонный номер для регистрации.

Как уже было сказано, Matrix позволяет делать все то, к чему мы привыкли в современных мессенджерах — чаты, групповые чаты, передача файлов, аудио- и видео-звонки.

Сервер Matrix может работать как изолированно («только для своих»), так и в составе «федерации» — когда разные серверы общаются между собой, и пользователи, подключенные к разным серверам, могут общаться друг с другом. Есть здесь олды, которые помнят Jabber и IRC? Ну вот, здесь такой же принцип. Я бы даже сказал, что Matrix — это этакий хипстерский Jabber на стероидах.

В принципе, чтобы начать пользоваться Matrix, не нужен даже свой сервер — можно зарегистрироваться на каком-нибудь публичном сервере (самый известный из которых, неожиданно, matrix.org), установить какой-нибудь из клиентов (самый популярный — Element, он есть под Android, iOS, десктопы, и веб), и вперед.

Но мы с вами, как настоящие партизаны, поднимем свой сервер.

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

Окей, будем считать, что у вас уже есть VPS (если нет, то обратите внимание на этот комментарий), на нем установлен какой-нибудь дистрибутив Linux (я предпочитаю Debian или Ubuntu) и произведена базовая настройка (создан пользователь, настроены ssh-ключи, или хотя бы запрещен root-доступ по ssh, настроен fail2ban и обновлены системные пакеты).

Мы будем для простоты устанавливать с помощью Docker (я уже слышу осуждающее «ууууууууу!» со стороны параноиков, но параноики могут собрать контейнеры самостоятельно, или вообще ставиться сразу из исходников). Еще нам нужен будет домен, потому что Matrix работает через TLS/HTTPS. Домен в наши дни стоит копейки, но если совсем жаба душит, можно использовать бесплатный DynDNS-поддомен, например, от dynu.com.

Из чего состоит инсталляция сервера? Из нескольких составляющих.

  1. Сам Matrix-сервер. Мы будем использовать Synapse, он самый популярный и стабильный;

  2. ACME-клиент, чтобы получать TLS-сертификаты, например, от LetsEncrypt;

  3. (опционально) База данных. Synapse может использовать SQLite, но разработчики не рекомендуют делать так на проде (видимо, будет тормозить при более-менее существенной нагрузке) и советуют использовать PostgreSQL. Так мы и поступим;

  4. (опционально) TURN-сервер, мы будем использовать coturn. Он нужен для видео- и аудио-звонков. Matrix использует WebRTC, который подразумевает прямое подключение между пользователями, однако в наши времена повсеместного NAT’а (а нередко даже двойного, один на роутере, другой у провайдера) прямые подключения зачастую невозможны. TURN-сервер работает как «ретранслятор», являясь посредником, позволяющим связаться двум клиентам. Можно использовать публичные TURN-сервера, но раз уж мы ставим все свое, до давайте делать по максимуму все свое;

  5. (опционально) Веб-морда веб-клиент для общения из браузера.

В качестве второго пункта частоприменяют certbot, но с docker его использовать, прямо скажем, неудобно. Вы, конечно, можете создать для него контейнер, пошарить volume сертификатами между контейнерами, но при этом еще придется поломать голову над обновлением сертификатов раз в три месяца и над автоматическим перезапуском контейнеров после этого. Поэтому я сделал все гораздо проще. Мы используем популярный веб-сервер Caddy, и одним выстрелом убьем нескольких зайцев:

  1. Caddy умеет сам автоматически запрашивать и обновлять сертификаты Let’s Encrypt для вашего домена;

  2. Caddy у нас будет выступать не только как фронтенд для Matrix-сервера, но и обеспечивать работу веб-клиента из пункта 5 (если он вам нужен);

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

Итак, начнем. Устанавливаете docker и docker-compose (apt install docker.io docker-compose в debian-like системах). Создаете где-нибудь (хорошо подходит /opt) новую папку для всего нашего барахла. Кладем в нее сначала наш docker-compose.yml файл:

version: '3' services:   coturn:     image: coturn/coturn:latest     restart: unless-stopped     network_mode: host     volumes:       - "./turnserver.conf:/etc/turnserver.conf:ro"    caddy:     image: caddy:latest     restart: unless-stopped     ports:       - 80:80       - 443:443       - 8448:443     volumes:       - ./Caddyfile:/etc/caddy/Caddyfile       - ./html:/var/www/html/    synapse:     image: docker.io/matrixdotorg/synapse:latest     restart: unless-stopped     environment:       - SYNAPSE_CONFIG_PATH=/data/homeserver.yaml       - SYNAPSE_SERVER_NAME=YOUR_DOMAIN       - SYNAPSE_SERVER_ADDRESS=https://YOUR_DOMAIN       - SYNAPSE_REPORT_STATS=yes     volumes:       - ./synapse:/data     depends_on:       - db    db:     image: docker.io/postgres:12-alpine     restart: unless-stopped     environment:       - POSTGRES_USER=synapse       - POSTGRES_PASSWORD=changeme       - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C     volumes:       - ./postgres:/var/lib/postgresql/data

Здесь обратите внимание, важно заменить YOUR_DOMAIN на ваш домен. И давайте пройдемся, что из этого что.

coturn — TURN-сервер. В разных мануалах упоминаются разные порты, которые для него необходимо открыть (WebRTC в этом плане вообще штука сложная), я для простоты вынес его в host network. К контейнеру подмонтирован файл ./turnserver.conf с конфигом, к нему мы вернемся чуть позже.

caddy — веб-сервер. Наружу открыты порты 80, 443 и 8448 (последний нужен для федерации серверов, можно и без него, но с ним проще). Файл ./Caddyfile — конфиг веб-сервера, а дира ./html — корень сайта.

synapse — собственно, matrix-сервер. Там все говорит само за себя. И напоминаю о необходимости изменить YOUR_DOMAIN на ваш домен. Данные и конфиги будут лежать в ./synapse .

db — PostgreSQL. POSTGRES_PASSWORD лучше измените на какой-нибудь свой. При первом запуске Постгрес по умолчанию создает базу данных, совпадающую с именем пользователя (у нас synapse) — так проще для нас. Данные самой БД будут лежать в дире ./postgres.

Теперь перейдем к конфигам.

Запустим специальный скрипт, создающий конфиг Synapse:

 docker-compose run --rm synapse generate

Docker создаст контейнеры synapse и db (postgresql), и в ./synapse/homeserver.yaml появится сгенерированный конфиг. Нужно его немного отредактировать: во-первых, поменять SQLite на PostgreSQL, во-вторых настроить TURN.

Для TURN нам понадобится секретный ключ, сгенерировать его можно командой pwgen -s 64 1 .

Закомментируем в homeserver.yaml строки, относящиеся к sqlite, а вместо этого добавим относящиеся к postgresql и turn. Мой конфиг после этого выглядит примерно так:

server_name: "YOUR_DOMAIN" pid_file: /data/homeserver.pid listeners:   - port: 8008     tls: false     type: http     x_forwarded: true     resources:       - names: [client, federation]         compress: false  # Это про SQLite, я закомментировал #database: #  name: sqlite3 #  args: #    database: /data/homeserver.db  # это про PostgreSQL, я добавил database:     name: psycopg2     args:         user: synapse         password: ваш_POSTGRES_PASSWORD         host: db         database: synapse         cp_min: 5         cp_max: 10  # это для TURN, тоже добавляем: turn_uris: [ "turn:YOUR_DOMAIN?transport=udp", "turn:YOUR_DOMAIN?transport=tcp" ] turn_shared_secret: "YOUR_KEY" turn_user_lifetime: 86400000 turn_allow_guests: true  log_config: "/data/YOUR_DOMAIN.log.config" media_store_path: /data/media_store registration_shared_secret: "..." report_stats: true macaroon_secret_key: "..." form_secret: "..." signing_key_path: "/data/YOUR_DOMAIN.me.signing.key" trusted_key_servers:   - server_name: "matrix.org"   # vim:ft=yaml

YOUR_DOMAIN заменяете на ваш домен, а YOUR_KEY — на ключ, который вы до этого сгенерировали pwgen.

Дальше, создаем конфиг coturn в файле ./turnserver.conf:

listening-port=3478  min-port=49152 max-port=65535  static-auth-secret=YOUR_KEY realm=YOUR_DOMAIN  syslog  no-tcp-relay  denied-peer-ip=10.0.0.0-10.255.255.255 denied-peer-ip=192.168.0.0-192.168.255.255 denied-peer-ip=172.16.0.0-172.31.255.255  no-multicast-peers denied-peer-ip=0.0.0.0-0.255.255.255 denied-peer-ip=100.64.0.0-100.127.255.255 denied-peer-ip=127.0.0.0-127.255.255.255 denied-peer-ip=169.254.0.0-169.254.255.255 denied-peer-ip=192.0.0.0-192.0.0.255 denied-peer-ip=192.0.2.0-192.0.2.255 denied-peer-ip=192.88.99.0-192.88.99.255 denied-peer-ip=198.18.0.0-198.19.255.255 denied-peer-ip=198.51.100.0-198.51.100.255 denied-peer-ip=203.0.113.0-203.0.113.255 denied-peer-ip=240.0.0.0-255.255.255.255  allowed-peer-ip=YOUR_SERVER_IP  user-quota=12 total-quota=1200

Конфиг взят из примеров в документации Synapse. Тут все то же самое, YOUR_DOMAIN меняем на ваш домен, YOUR_KEY на ключ который вам сгенерировал pwgen, и YOUR_SERVER_IP на айпишник вашего сервера.

Заканчиваем настройку конфигом Caddy в файле ./Caddyfile:

YOUR_DOMAIN {         reverse_proxy /_matrix/* synapse:8008         reverse_proxy /_synapse/* synapse:8008         header /.well-known/matrix/* Content-Type application/json         header /.well-known/matrix/* Access-Control-Allow-Origin *         respond /.well-known/matrix/server `{"m.server": "YOUR_DOMAIN:443"}`         respond /.well-known/matrix/client `{"m.homeserver":{"base_url":"https://YOUR_DOMAIN"}}`          root /var/www/html         file_server         # если вместо локального сайта хотите отдавать какой-нибудь левый сайт,          # то вместо root и file_server используйте что-то вроде такого:         # reverse_proxy http://lib.ru }

Как обычно, везде меняем YOUR_DOMAIN на ваш домен (и в самом начале тоже!). Этот конфиг говорит, что все запросы с путями /_matrix/ и /_synapse/ нужно передавать на сервер Synapse. То что в .well-known — по идее не обязательно, оно нужно или для федерации если сервер не доступен на 8448 порту (у нас доступен), либо для некоторых тупых клиентов, которые почему-то пытаются туда залезть, поэтому лучше это тоже иметь в конфиге.

А все остальные запросы мы будем обрабатывать как обычный статический сайт, лежащий в локально в ./html снаружи докер-контейнера. Не забудьте создать эту папочку и положить в нее index.html с каким-нибудь содержимым.
Либо, по желанию, вместо этого можно отдавать контент какого-нибудь чужого сайта.

Все готово! Запускаем:

 docker-compose up -d

И после создания контейнеров, проверяем. В браузере по https://YOUR_DOMAIN должно открываться содержимое index.html (фейкового сайта), а при запросе https://YOUR_DOMAIN/_matrix/ выдаваться ошибка типа «Unrecognized request».

Если что-то не работает, ну либо просто ради интереса, чтобы убедиться, что все нормально, можно сделать docker ps, а потом docker logs <container_id> , чтобы посмотреть логи.

Создание пользователей

Можно разрешить регистрацию кому попало в конфиге homeserver.yaml параметром enable_registration: true (там даже можно добавить rate limit и капчу для регистрации, см. документацию Synapse). Либо же можно не разрешать регистрироваться кому попало, а создавать пользователей самому:

docker exec -it synapse_synapse_1 register_new_matrix_user https://YOUR_DOMAIN:8448 -c /data/homeserver.yaml -u USERNAME -a -p PASSWORD

где synapse_synapse_1 — имя вашего контейнера synapse (можно посмотреть его в docker ps ), YOUR_DOMAIN — ваш домен, USERNAME и PASSWORD — логин и пароль для нового пользователя соответственно, пользователь сможет поменять пароль позже из клиента.

Подключаемся клиентом

На примере Element, все очень просто. Устанавливаем его из сторов (если на телефон) или скачивая с сайта.

Жмем sign in:

Далее, предлагается подключиться к серверу matrix.org — мы же нажимаем Edit и вместо этого вводим там ваш домен. После этого вводим логин и пароль, жмем Next… и мы подключились!

После этого можно писать лично, создавать и писать в группы, отправлять файлы и звонить:

Есть только пара нюансов касательно того, как добавлять пользователей. При нажатии «Start chat» нужно выбрать пользователя с которым вы хотите пообщаться (либо нескольких). Я не знаю, почему по умолчанию там не показываются другие зарегистрированные на сервере пользователи, возможно это by design, либо надо что-то докрутить в конфиге, но можно добавить пользователя в список вручную, зная его логин. Делается это в формате @username:your_domain . После этого клиент «находит» пользователя и показывает его в списке, и вы можете отправить приглашение пообщаться, а после принятия приглашения — писать и звонить. Пользователями, которые у вас уже есть в контактах, можно делиться кнопкой «Share user» — клиент генерирует ссылку и QR-код, которые можно открыть/отсканировать у другого человека на устройстве.

В Matrix возможна еще такая вещь, как identity-сервер — что-то типа книги контактов, позволяющей искать пользователей в пределах сервера или даже на разных серверах по номеру телефона, емайлу, или еще каким-нибудь другим образом. Но это уже выходит за пределы этой статьи 🙂

Можно создавать группы (групповые чаты), как личные, так и публичные. Для групп формат похожий: #groupname:your_domain .

Ну и да — если все настроено правильно, то вы со своего сервера можете коммуницировать и с людьми/группами с других серверов (например, того самого matrix.org).

Веб-клиент

Если нужен веб-клиент, то доустановить его очень просто. Я пробовал Element (он более функциональный) и Hydrogen. Для установки достаточно скачать архив со страницы Releases гитхаба и распаковать его куда-нибудь в диру ./html — и все работает 🙂

Дополнительно можно подправить конфиг, например, разрешить подключаться только к вашему серверу, а не к другим. Для Element содержимое config.json будет таким:

{     "default_server_config": {         "m.homeserver": {             "base_url": "https://YOUR_DOMAIN",             "server_name": "YOUR_DOMAIN"         }     },     "disable_custom_urls": true,     "disable_guests": false,     "disable_login_language_selector": false,     "disable_3pid_login": false } 

Ну и да, не рекомендуется использовать веб-клиент на том же домене, что и сам matrix-сервер, потому что это может сделать сервер уязвимым к CORS-атакам. Поэтому лучше сделать отдельный поддомен (если у вас уже бесплатный поддомен, то просто создать еще один), и добавить его соответствующим образом в Caddyfile.

Прокси на том же сервере, что и Matrix

Если у вас на сервере уже установлен XRay, то установка Matrix — отличная возможность использовать вариант «steal-from-yourself» для XTLS-Reality. В Docker-compose замените для caddy строку - 443:443 на - 127.0.0.1:8443:443 . После этого в конфиге XRay для inbound’а с XTLS-Reality вместо чужого домена используйте ваш домен, а в dest укажите 127.0.0.1:8443.

А если вы используете OpenConnect — можно разруливать подключения на 443 порту по SNI, например с помощью haproxy.

Огораживаемся от РКН

И еще маленькая штука, которая может быть полезной для вашего сервера:
Раз — Скрипт для блокировки пауков РКН для серверов на Линуксе
Два — freemedia-tech/iptables-rugov-block (github.com)
Три — РКН — добавить все их IP в черный список — Все о VPN, прокси и свободном интернете (checkvpn.net)


ссылка на оригинал статьи https://habr.com/ru/articles/837904/