SimpleX Chat: приватный мессенджер без идентификаторов и свой сервер

SimpleX Chat: приватный мессенджер без аккаунта и свой сервер SMP Docker
SimpleX Chat — мессенджер без аккаунта и без номера. Как устроены очереди SMP, чем он отличается от Matrix и как поднять свой сервер сообщений и файлов на VPS.

SimpleX Chat — мессенджер, в котором нет аккаунта. Нет номера телефона, почты и даже случайного номера пользователя, по которому сервер мог бы собрать список контактов. Переписка живёт на телефонах участников, а сервер только доносит уже зашифрованное сообщение до очереди получателя и забывает его, когда получатель забрал.

Ниже — как это устроено, чем отличается от Matrix и от обычного мессенджера с учётной записью, какие приложения ставить и как поднять свой сервер доставки (SMP) и сервер файлов (XFTP) на небольшом VPS. Готовая настройка под ключ описана отдельно: приватный мессенджер SimpleX Chat на своём VPS.

Что такое SimpleX Chat

SimpleX Chat — открытый мессенджер для Android, iPhone и компьютера. Проект прямо формулирует цель: сеть без идентификаторов пользователя. Контакт, группа и история хранятся в базе приложения на устройстве. Серверы сети — это релеи: они принимают пакет и отдают его тому, кто знает адрес очереди.

Сообщения шифруются на устройствах. В описании протокола это Double Ratchet и дополнительный слой шифрования: компрометация одного ключа не должна открывать всю прошлую и будущую переписку. Проект также пишет, что добавил постквантовую защиту; подробности — на странице вопросов и в их заметке про шифрование. Сервер видит шифротекст, а не текст сообщения.

Свой сервер не обязателен. В мобильных приложениях уже прописаны релеи simplex.im. Свой SMP нужен, если очередь «мне присылают сюда» должна стоять на машине, которую вы сами администрируете. Собеседник при этом может принимать сообщения на любом другом сервере SimpleX, в том числе на публичном. Сеть для этого и сделана децентрализованной: клиенты на разных серверах переписываются друг с другом.

Как устроена переписка без аккаунта

В обычном мессенджере есть пользователь. Сервер знает, что этот пользователь существует, кто у него в контактах и в каких чатах он состоит. В SimpleX такого объекта нет. Есть очередь сообщений на релее. Адрес очереди выглядит как ссылка smp://: в ней отпечаток сертификата сервера, при необходимости пароль на создание очередей и имя или IP сервера.

Получатель сам выбирает, на каком SMP-сервере будет его очередь для этого контакта. Отправитель не заводит у вас аккаунт: его приложение кладёт зашифрованный пакет в известный ему адрес очереди. Ваше приложение периодически забирает пакеты из своих очередей. Когда пакет доставлен на устройство, релею он больше не нужен.

Очередь можно сменить. В карточке контакта или участника группы есть смена адреса приёма. Это важно: если в настройках приложения вы прописали свой сервер, на него перейдут новые контакты. Старые останутся на прежних релях, пока вы не перенесёте их вручную. Так написано в документации SMP-сервера.

Знакомство начинается с одноразовой ссылки или QR-кода. В ссылке открытые ключи, и использовать её можно один раз. Её можно передать любым уже существующим каналом. Если нужен постоянный адрес, чтобы к вам могли писать многие, в профиле создаётся SimpleX-адрес: это уже не одноразовая ссылка. Режим инкогнито при новом контакте подставляет случайное имя и не показывает ваш обычный профиль.

SimpleX, Matrix и обычный мессенджер

У трёх схем разные обещания. Путать их не стоит: «свой сервер» в Matrix и «свой сервер» в SimpleX — не одно и то же.

  • Обычный мессенджер хранит аккаунт, список контактов и часто саму историю. Номер или почта — идентификатор, по которому вас находят.
  • Matrix тоже даёт свой сервер, но на нём есть учётные записи, комнаты и история сообщений. Это удобно для команды и для нескольких устройств. Сервер при этом знает состав комнат.
  • SimpleX не хранит историю переписки как почтовый ящик. На реле временно лежат недоставленные пакеты. Профиля «пользователь на сервере» нет. Зато нет и привычной синхронизации одного аккаунта на телефон, планшет и два компьютера.

Связка телефона и компьютера в SimpleX есть, но это не облачный аккаунт. Профиль с телефона открывается на компьютере, когда оба устройства в одной локальной сети. Несколько полноценных телефонов с одной и той же базой проект сознательно не делает: в их разборе мультиустройство у мессенджеров с Double Ratchet почти всегда что-то ломает в свойствах шифрования. Пока официальная позиция такая — связывайте телефон с компьютером в одной сети или заведите отдельные профили.

Прочтений («прочитано в 14:41») в SimpleX нет и, по их FAQ, не планируется даже как опция. Одна галочка значит, что пакет принял релей. Две — что он оказался на устройстве собеседника. Собеседник может отключить уведомления о доставке.

Что сервер всё-таки видит

Фраза «сервер не знает, с кем вы говорите» легко прочитать сильнее, чем она значит. Текст сообщения и имя контакта релей не получает. Каталога пользователей у него нет. Но машина, через которую идут пакеты, видит сам факт трафика.

  • Релей вашей очереди видит, что очередь жива, когда с неё забирают сообщения и примерно в каком объёме. Он не видит, из какой очереди на чужом сервере это сообщение отправили.
  • Если ваше приложение ходит на сервер собеседника напрямую, тот сервер видит ваш IP. С версии протокола, где включена частная маршрутизация, клиент может отдать пакет знакомому релеу, а тот перешлёт его дальше. Тогда сервер назначения не видит ваш адрес. Это описано в FAQ проекта, включается настройками сети приложения и требует, чтобы серверы по пути поддерживали эту функцию.
  • Оператор сервера и дата-центр видят, что с IP сервера идёт шифрованный трафик SimpleX. Содержимое переписки из этого не складывается.
  • Пуш-уведомления на телефон по умолчанию идут через инфраструктуру simplex.im. В приложении можно переключить доставку на периодический опрос: тогда клиент сам спрашивает ваш SMP и не зависит от их пуш-сервера. Опрос сажает батарею сильнее, чем пуш.

По запросу «выдать переписку пользователя» оператору своего SMP отвечать почти нечем: нет учётной записи и нет архива чатов. Недоставленные пакеты, если они ещё не истекли, на диске есть — это шифротекст конкретных очередей, а не лента переписки. Политика проекта — хранить минимум метаданных; прозрачные отчёты они публикуют у себя.

Приложения

Ставить клиент лучше со страницы загрузок simplex.chat. Там собраны актуальные ссылки, и они меняются реже, чем зеркала.

База приложения зашифрована парольной фразой, которую задаёте вы. Восстановить её разработчик не может. Если фраза потеряна, профиль, контакты и сообщения с этого устройства не открыть. Перенос на новый телефон делайте встроенным переносом SimpleX, а не копией каталога через облачный бэкап телефона: проект прямо пишет, что чужой перенос ломает базу.

Свой сервер: SMP и XFTP

Для переписки нужен SMP-сервер. Это релей очередей. Образ Docker называется simplexchat/smp-server, исходники — в репозитории simplexmq. Протокол поверх своего TLS. В ручной схеме Docker порт снаружи — 5223. В автоматической схеме рядом поднимается Caddy: страница сервера и протокол доступны ещё и на 443, а 5223 остаётся запасным. Для автоматической схемы порты 80 и 443 должны быть свободны.

Файлы, фото и голосовые идут отдельным протоколом XFTP. Файл режется на блоки фиксированного размера, блоки шифруются и могут уйти через разные релеи. Получатель собирает файл у себя. Отправителю не нужно оставаться в сети, пока файл скачивают: релей хранит его ограниченное время. В документации XFTP сейчас указано 48 часов или до удаления отправителем. Образ — simplexchat/xftp-server, руководство — Hosting your own XFTP Server.

На одном VPS эти две службы не должны занимать один и тот же внешний порт. Удобная пара из официальных примеров: SMP в ручном режиме на 5223 и XFTP на 443. Если SMP поставлен «автоматом» с Caddy, 443 уже занят, и XFTP нужно либо вынести на другой адрес, либо опубликовать на другом внешнем порту. Ниже как раз первая пара: 5223 для сообщений и 443 для файлов.

Звонки — это WebRTC, не SMP. По умолчанию приложение использует stun.simplex.im и turn.simplex.im. Свой TURN нужен, если медиапоток звонка тоже должен идти через вашу машину. Как его поднять, разобрано в разделе «Свой сервер звонков». Для переписки и файлов он не требуется.

Пароль сервера, если его задать, защищает только создание новых очередей или загрузку новых файлов. Отправлять сообщения в уже существующую очередь можно без этого пароля. Пароль попадает в адрес вида smp://отпечаток:пароль@сервер и его имеют те, кому вы разрешили заводить очереди у вас. Собеседникам, которые только пишут вам, он не нужен.

Домен и VPS

Домен не обязателен. В поле ADDR у SMP и XFTP, в --realm у TURN и в строках, которые вставляете в приложение, укажите публичный IP сервера, например 203.0.113.10. Записи DNS тогда не нужны. Домен удобнее, если IP позже сменится: имя останется в сертификате и в адресе, который уже прописан в приложении. В документации SMP также сказано, что клиенты будут использовать имя сервера в ссылках-приглашениях; у сервера без имени и без страницы ссылки уедут в схему simplex:, которую браузер не откроет. На работу очередей по адресу smp://отпечаток@203.0.113.10:5223 это не влияет.

Домен удобно купить в Timeweb, а сам сервер взять отдельным небольшим VPS в Timeweb Cloud. Для личного SMP и XFTP с небольшим архивом файлов хватает 1 ядра, 1 ГБ памяти и диска на 10–20 ГБ. Квота XFTP задаётся отдельно и не должна быть больше диска.

Система — Ubuntu LTS. Официальный скрипт установки в виде службы systemd проект проверяет на Ubuntu; Docker-образ от этой оговорки свободнее, его и ставим ниже. Docker Engine и плагин Compose — по документации Docker: установка движка и Compose для Linux.

Записи DNS

Если в ADDR указан IP, записи не создавайте. Для домена сделайте две записи типа A на IPv4 VPS. Если есть IPv6, к каждой добавляется AAAA.

  • smp.example.ru — SMP, порт 5223.
  • files.example.ru — XFTP, порт 443.

Имена можно заменить на свои. Пока запись не видна снаружи, клиент адрес сервера не откроет. Проверка с вашей стороны — 2ip.ru/dig. Для SMP в ручном режиме веб-сервер и порт 80 не нужны: сертификат протокола сервер выпускает сам при инициализации.

Установка SMP

Это ручной вариант из документации: без Caddy, протокол на порту 5223. Полный автоматический вариант с сертификатом Let’s Encrypt и страницей сервера на 443 — в Hosting your own SMP Server, раздел Docker: Automatic setup. Его берите, если 443 свободен и страница сервера вам нужна. Тогда XFTP на 443 этого же VPS уже не встанет.

Откройте порты. SSH не закрывайте, иначе потеряете сервер.

ufw allow OpenSSH
ufw allow 5223/tcp
ufw allow 443/tcp
ufw enable

Каталог и файл docker-compose.yml. В ADDR пишите домен или публичный IP сервера. Без домена это IP, тот же 203.0.113.10, и раздел про DNS пропускаете.

mkdir -p ~/simplex/smp && cd ~/simplex/smp
name: SimpleX Chat - smp-server

services:
  smp-server:
    image: simplexchat/smp-server:latest
    environment:
      WEB_MANUAL: "1"
      ADDR: smp.example.ru
    volumes:
      - ./smp_configs:/etc/opt/simplex
      - ./smp_state:/var/opt/simplex
    ports:
      - 5223:5223
    restart: unless-stopped

Запуск в фоне: docker compose up -d. В логах (docker compose logs) сервер печатает отпечаток и адрес вида smp://отпечаток@smp.example.ru. Адрес копируйте целиком. Рядом будет путь к ключу CA, обычно /etc/opt/simplex/ca.key внутри контейнера, на хосте это файл в smp_configs. Ключ CA нужен, чтобы выпустить новый сертификат сервера, не сменив личность сервера и не оборвав уже созданные очереди. Его копируют в надёжное место и с сервера удаляют. Если ключ останется рядом с рабочим сертификатом, кража диска VPS позволит подписать новый сертификат от вашего имени.

Журнал очередей при инициализации образом обычно включён: без него очереди и недоставленные сообщения пропадут при перезапуске контейнера. В примере конфигурации из документации срок хранения недоставленных сообщений — 21 день (expire_messages_days). Это не архив чата. Доставленный пакет клиенту на сервере не остаётся как история.

Исходный код сервера — AGPL. Если вы меняете код и пускаете на него пользователей, правки нужно отдать пользователям. Поле source_code в smp-server.ini для этого и существует. Готовый образ без ваших правок указывает на репозиторий проекта.

Установка XFTP

Отдельный каталог, порт 443. В ADDR имя files.example.ru или тот же публичный IP, что и у SMP. QUOTA — потолок хранилища. Поставьте его меньше свободного диска. Пароль на загрузку новых файлов по желанию: в документации он задаётся в file-server.ini, секция AUTH, параметр create_password.

mkdir -p ~/simplex/xftp && cd ~/simplex/xftp
name: SimpleX Chat - xftp-server

services:
  xftp-server:
    image: simplexchat/xftp-server:latest
    environment:
      ADDR: files.example.ru
      QUOTA: 20gb
    volumes:
      - ./xftp_configs:/etc/opt/simplex-xftp
      - ./xftp_state:/var/opt/simplex-xftp
      - ./xftp_files:/srv/xftp
    ports:
      - 443:443
    restart: unless-stopped

Снова docker compose up -d и адрес xftp://отпечаток@files.example.ru из журнала. Ключ CA файлового сервера храните так же, как ключ SMP: копия вне сервера, с диска VPS убрать.

Официальный скрипт systemd ставит и SMP, и XFTP одной программой и сам считает контрольную сумму. Команда и актуальный хеш — на страницах SMP и XFTP. Хеш в чужой статье быстро устаревает, поэтому здесь его нет: сверяйте строку на simplex.chat в день установки.

Адрес сервера в приложении

В приложении: настройки, сеть и серверы, список SMP и отдельно список XFTP. Вставьте адреса, которые напечатал контейнер, включая отпечаток. Отпечаток — это защита от подмены сервера: клиент сверяет сертификат с тем, что записан в ссылке.

Для стабильного соединения зайдите в настройки, «Сеть и серверы», «Настройки сети» и поставьте «Интервал пинг» 120 секунд. По умолчанию там 1200 секунд, и с таким промежутком связь чаще замирает.

После сохранения новые одноразовые ссылки и новые контакты смогут принимать сообщения через ваш SMP. Старые диалоги останутся на прежних серверах, пока в карточке контакта вы не смените адрес приёма. Имеет смысл сначала написать тестовый контакт самому себе со второго устройства и убедиться, что обе галочки доходят.

Порт 5223 иногда закрыт в гостевом Wi-Fi и в корпоративных сетях. Если тестовое сообщение с такого Wi-Fi не уходит, а с домашней сети уходит, дело в фильтре порта, а не в шифровании. На странице услуги сервер поэтому публикуют на портах, которые в таких сетях обычно открыты. В домашней и мобильной сети стандартного 5223 достаточно.

Приглашения, группы и звонки

Новый чат: кнопка создания одноразовой ссылки, её отправляете человеку или показываете QR рядом. Человек вставляет ссылку в поиск приложения или открывает её, когда приложение уже стоит. Пока оба хотя бы раз одновременно держат приложение онлайн, соединение устанавливается. Дальше писать можно по очереди, одновременно быть в сети не нужно.

Группа в SimpleX — не комната на сервере с архивом. Состав группы знают клиенты участников. Сервер по-прежнему видит очереди, а не «чат отдела продаж». Роли в группе настраиваются в приложении. Удалить сообщение у собеседника можно, только если оба включили «удалить у всех» и уложились в сутки после отправки. Реакций немного, ответ на конкретное сообщение есть.

Голосовые и видеозвонки идут через WebRTC. На время звонка приложение показывает, есть ли сквозное шифрование медиа. На старом Android его может не быть, если системный WebView не умеет шифровать поток: обновление WebView это обычно чинит. Если звонок не собирается, в FAQ предлагают проверить доступность stun.simplex.im и turn.simplex.im — пока вы не заменили их на свой TURN, звонок зависит от этих узлов, даже если сообщения ходят через ваш SMP.

Картинка может открыться не сразу. Пока файл не догружен, на превью нет отметки о полной загрузке. Если получатель не забрал файл за двое суток, XFTP его уже не отдаст.

Свой сервер звонков

Голос и видео в SimpleX идут через WebRTC. Пока в приложении стоят серверы simplex.im, медиапоток звонка зависит от них, даже если сообщения уже ходят через ваш SMP. Свой STUN/TURN поднимается отдельно, программой coturn. Переписке и файлам он не нужен.

Пароль для TURN не должен содержать символы, которые ломают ссылку turn:. Удобная команда оставляет 24 случайных символа без слэша, плюса и знака равенства:

openssl rand -base64 24 | tr -d '/+=' | cut -c1-24

Запомните эту строку. В примерах ниже она записана как ПАРОЛЬ. Имя пользователя — simplex. Имя или IP, по которому клиенты видят сервер, — turn.example.ru. Это может быть отдельная A-запись на тот же VPS или сам IP. Порт сигнализации — 3478, и TCP, и UDP. Сам звук идёт по широкому диапазону UDP 49152–65535: его тоже нужно открыть, иначе звонок «соединяется», но тишина.

ufw allow 3478/tcp
ufw allow 3478/udp
ufw allow 49152:65535/udp

Контейнер coturn запускается в сети хоста, а не за отдельным адресом Docker. Иначе ответные медиапорты не доходят до телефона. Каталог отдельный от SMP и XFTP.

mkdir -p ~/simplex/turn && cd ~/simplex/turn
services:
  coturn:
    image: coturn/coturn:latest
    container_name: simplex-turn
    restart: unless-stopped
    network_mode: host
    command: >
      -n
      --lt-cred-mech
      --fingerprint
      --no-tls
      --no-dtls
      --realm=turn.example.ru
      --user=simplex:ПАРОЛЬ
      --listening-port=3478
      --min-port=49152
      --max-port=65535
      --log-file=stdout

docker compose up -d. Флаг -n значит «без файла конфигурации, всё в командной строке». --lt-cred-mech включает вход по имени и паролю. --no-tls и --no-dtls оставляют сам TURN на порту 3478 без своего сертификата. Звук между телефонами при этом шифрует WebRTC: в звонке приложение показывает, есть ли сквозное шифрование. Coturn видит, что разговор идёт, и адреса участников, но не расшифровывает медиа, пока это шифрование есть.

В приложении откройте настройки, затем «Конфиденциальность и безопасность», затем «WebRTC ICE серверы». Выключите серверы по умолчанию и добавьте три строки. Пароль и имя подставьте свои.

turn:simplex:ПАРОЛЬ@turn.example.ru:3478?transport=udp
turn:simplex:ПАРОЛЬ@turn.example.ru:3478?transport=tcp
stun:turn.example.ru:3478

Первая строка — обычный путь для звонка, по UDP. Вторая — тот же TURN по TCP, если UDP до сервера не проходит. Третья — STUN: клиенты узнают свой внешний адрес. После сохранения позвоните между двумя своими устройствами в домашней сети и в мобильной. Если статуса «звонок» нет вообще, проверьте 3478. Если статус есть, а звука нет — диапазон 49152–65535/udp.

Копии и обновление

Копировать нужно и телефон, и сервер. Это разные вещи.

  • Приложение: встроенный экспорт или перенос профиля и парольная фраза базы. Без фразы копия бесполезна. Копия каталога «как получится» из облака телефона — плохой способ, проект от него предостерегает.
  • SMP: каталоги smp_configs и smp_state, плюс ключ CA, который вы унесли с сервера.
  • XFTP: xftp_configs, xftp_state и xftp_files. Файлы старше двух суток получателю уже не нужны, но недокачанные ещё могут лежать.

Перед копией каталогов контейнеры лучше остановить (docker compose stop), иначе журнал на диске может порваться. После копии — docker compose start.

Обновление образа:

docker compose pull
docker compose up -d

Сначала SMP, потом XFTP, каждый в своём каталоге. После обновления отправьте себе тестовое сообщение со второго устройства. Если очередь не поднялась, не удаляйте smp_state: в нём журнал очередей. Имеет смысл на время обновления держать под рукой копию, снятую до pull.

Частые вопросы

Можно ли пользоваться SimpleX без своего сервера?

Да. Приложение уже знает публичные релеи. Свой сервер меняет только то, где лежат ваши очереди приёма и файлы, которые вы отправляете через свой XFTP. Собеседник может оставаться на публичных серверах.

Видит ли хостер текст сообщений?

Нет. На диске VPS шифротекст недоставленных пакетов и файловые блоки XFTP. Ключи переписки на сервер не попадают. Хостер видит, что сервер ваш и что на него ходят клиенты.

Почему нельзя просто войти с того же аккаунта на втором телефоне?

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

Что будет, если VPS выключат?

Новые сообщения в очереди на этом SMP не примут, пока сервер выключен. Уже доставленная переписка останется в приложении. Контакты на других серверах продолжат работать. После включения сервера журнал очередей поднимет те очереди, которые были сохранены. Сообщения, которые не успели забрать и которые истекли по сроку, не вернутся.

Нужен ли домен, если есть IP?

Да. В ADDR у SMP и XFTP, в --realm у TURN и в адресах для приложения укажите публичный IP сервера вместо имени. DNS не нужен. Домен имеет смысл, чтобы не переписывать адреса в приложении при смене IP и чтобы приглашения открывались как обычные https-ссылки, а не как схема simplex:, с которой браузер не знает, что делать.

Читайте также

  • Настройка SimpleX Chat на VPS под ключ — SMP, файлы и звонки, если поднимать сервер самим некогда.
  • Matrix Synapse — свой мессенджер с аккаунтами, комнатами и историей на сервере.
  • Vaultwarden — пароли приложений Bitwarden на своём сервере, отдельно от переписки.

Рубрики: Docker Безопасность Веб-приложения
Подписаться на новые статьи (RSS)

Без почты и трекеров — только лента обновлений.

Также есть английская лента

Оцените статью
Добавить комментарий