Skip to main content
Всё на этой странице — о переносе одной строки. Подписка провижинится в Remnawave, Remnawave выпускает для неё ссылку доступа, и устройство считается подключённым, когда клиентское приложение держит эту ссылку. Ничего другого в подключении интересного нет: нет ни отдельных учётных данных на устройство, ни аккаунта, который нужно вводить в приложении, ни файла конфигурации, который надо править. Эта единственная строка одновременно является предъявительскими учётными данными. Подключиться может любой, кто ею владеет, и поэтому Omniflow показывает её только на том экране, чья цель — её передать, никогда не хранит её, никогда не пишет в логи и никогда не помещает в выгрузку персональных данных. Вся конструкция экрана подключения — QR-код, рисуемый в браузере, усечённое отображение, запрос по требованию — следует из этого одного факта. Обе клиентские поверхности отрисовывают это из одного источника. И бот Telegram, и веб-панель читают таблицу клиентских приложений из internal/commerce, потому что клиенту, которому в чате велят поставить одно приложение, а в браузере — другое, вручили два продукта.

Ссылка на подписку

Что это. URL, выпущенный и принадлежащий Remnawave, для одной подписки. Клиентское приложение запрашивает его, получает конфигурацию, которую даёт эта подписка, и подключается. Почему Omniflow не хранит копию. Ссылка — это учётные данные, а самый дешёвый способ гарантировать, что учётные данные никогда не попадут в резервную копию, строку лога или отчёт о сбое, — никогда их не держать. Omniflow читает ссылку из Remnawave в тот момент, когда клиент её запрашивает, и передаёт прямо на экран. Последствия видны по всему продукту:
  • GET /v1/account/overview — payload дашборда — намеренно не несёт URL подписки. Ответ дашборда, всегда несущий его, поместил бы ссылку в каждый кэш, лог и запись истории браузера, которые касаются страницы.
  • Каждый ответ /v1/account отправляется с Cache-Control: no-store, Referrer-Policy: no-referrer и Content-Security-Policy со значением default-src 'none'. Комментарий у этого промежуточного обработчика называет причину: клиентский ответ может содержать ссылку на подписку.
  • Выгрузка персональных данных объявляет subscription_links среди своих постоянных изъятий, а не включает их. См. Приватность и ваши данные.
  • Собственный журнал безопасности клиента записывает смену ссылки по подписи подписки и ничего более: помещение ссылки в журнал свело бы на нет ту самую смену, которую он записывает.
Откуда она берётся. Ссылка есть только у провижиненной подписки. Между платежом и выдачей доступа пользователя в Remnawave ещё нет, поэтому экран подключения отвечает 409 not_provisioned и показывает «Ещё настраивается» вместо пустого поля. Что происходит в это время, описано в Выдаче доступа.

Как перенести ссылку на устройство

Из веб-панели

1

Откройте подписку

На /account нажмите Подключить на карточке подписки. Это ведёт на /account/subscriptions/{id}/connect. Экран также принимает параметр запроса ?platform=, поэтому ссылка на него может заранее выбрать платформу.
2

Выберите платформу

Выбор предлагает iOS, Android, Windows, macOS и Linux в этом фиксированном порядке. Неизвестная или пустая платформа приводит к первой из них, а не к ошибке.
3

Пройдите три шага

Установите первое рекомендованное приложение для этой платформы; нажмите кнопку, которая добавляет подписку; если ничего не открылось, скопируйте ссылку и вставьте её в приложение. Шаги называют конкретное приложение, а не «ваше VPN-приложение», потому что клиенту придётся найти его в магазине.
4

Передайте ссылку

Нажмите кнопку Открыть в … для установленного вами приложения, наведите камеру второго устройства на QR-код или нажмите Копировать и вставьте ссылку вручную. Все три способа несут одну и ту же строку.

Из бота Telegram

На экране подписки есть кнопка Подключить. Она открывает тот же выбор платформы, и каждая платформа показывает те же пронумерованные шаги, называющие то же первое рекомендованное приложение. Разница — в кнопках. Встроенные кнопки Telegram принимают только URL со схемами http, https и tg, поэтому deep-ссылка приложения вроде happ://add/… вообще не может быть кнопкой-ссылкой. Поэтому бот отрисовывает по одной кнопке копирования текста на каждое приложение, плюс кнопку копирования самой ссылки, плюс кнопку-ссылку «Открыть подписку» для https-URL подписки. Копирование — документированный запасной вариант везде, в том числе в десктопном браузере, где для схемы не зарегистрирован обработчик. Каждый экран бота отправляется как защищённое содержимое, поэтому Telegram не позволит переслать сообщение со ссылкой на подписку. Полный путь в Telegram описан на странице бота Telegram.

Клиентские приложения, которые документирует Omniflow

Каталог хранится в базе, а не вкомпилирован, и обе поверхности читают одни и те же строки — поэтому бот и браузер не могут рекомендовать разные приложения. Редактируется он по адресу /admin/settings/connect. Порядок — это порядок рекомендации: первая запись — то приложение, которое называют шаги настройки. Новая установка засевается ровно тем, что прежние версии носили в бинарнике: Deep-ссылка — это схема с приписанным к ней URL подписки, и ничего больше: happ://add/https://panel.example.com/sub/…. Никакого сервиса редиректов между ними нет, поэтому приложение, поддерживающее свою схему, импортирует подписку так, что ни одна часть Omniflow не наблюдает этого события. Оператор может также указать адрес загрузки приложения и написать собственные инструкции по установке — для каждой платформы и каждого языка. Инструкции заменяют общие три шага, а не добавляются к ним: тот, кто описал собственную настройку, знает что-то, чего не знает общий текст, а показ обоих оставил бы клиента выбирать между двумя рассказами об одном и том же.
Засеянный список намеренно короткий. Это приложения, которые установка документирует и поддерживает, а не все приложения, способные прочитать ссылку на подписку: клиент, использующий что-то другое, всё равно может вставить ссылку туда, но шаги на экране не будут описывать его приложение.

Три способа, которыми путешествует ссылка

Deep-ссылки

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

QR-код

QR генерируется в браузере. Кодировщик импортируется лениво, чтобы не попадать в бандл всех остальных экранов, а результат отрисовывается из data URL в обычном элементе <img>. Стоит сказать, почему это не изображение, отрисованное сервером: URL изображения, несущий ссылку на подписку, поместил бы эти учётные данные в строку запроса, лог прокси и кэш браузера, а прогон через конвейер изображений Next.js отправил бы несущий учётные данные payload на сервер для кэширования. Если кодировщик даёт сбой, блок с QR не отрисовывается вовсе, а не показывается сломанным. Наведите камеру другого устройства на код, и оно получит ту же строку, которую несла бы deep-ссылка.

Копирование вручную

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

Когда экран подключения не показывает ссылку

В боте подписка, у которой ещё нет ссылки, показывает вместо кнопок строку «Ссылка на подписку появится, как только доступ станет активен». API. GET /v1/account/subscriptions/{subscriptionID}/connection?platform= возвращает {subscriptionUrl, platform, platforms[], clients[{name, deepLink}]}.

Подключённые устройства

Что это. Устройства, сейчас привязанные к пользователю Remnawave одной подписки, со счётчиком относительно лимита устройств тарифа, элементом управления удалением для каждого устройства и элементом удаления всех. Зачем это нужно. Лимит устройств выполним, только если клиент может сам освободить слот. Без списка устройств достижение лимита означает открытие обращения в поддержку, чтобы отключить телефон, заменённый год назад. Как туда попасть. Устройств нет на панели вкладок: замена телефона — действие раз в год, а пять вкладок упорядочены по частоте потребности. Откройте /account/profile и перейдите в Устройства либо попадите на /account/devices напрямую. Устройства принадлежат подписке, а не аккаунту, поэтому, когда у клиента их больше одной, экран показывает над списком кнопки для переключения между ними. Каждая строка показывает иконку, выбранную по платформе, о которой сообщило приложение (ноутбук для mac, Windows или Linux, планшет для планшета, иначе телефон), модель устройства, о которой приложение сообщило само, — или «Неизвестное устройство», если оно не сообщило ничего, — и дату. Под списком: «Одна ссылка работает на всех устройствах. Отключение освобождает слот сразу».

Что намеренно не показывается

Ни на этом экране, ни в стоящем за ним ответе нет ни аппаратного идентификатора, ни IP-адреса. Это решение, а не упущение:
  • HWID никогда не покидает сервер. Он идентифицирует чью-то физическую машину. Устройство называется клиенту дескриптором — base64url первых 16 байт SHA-256("omniflow.device." + hwid), 128 бит, — который не раскрывает ничего об устройстве, за которое он стоит.
  • Дескриптор разрешается повторным хэшированием, а не сохранённым сопоставлением. Когда приходит запрос на удаление, сервер запрашивает текущий список устройств, хэширует каждый HWID, который держит, и сопоставляет. Поэтому вызывающий никогда не передаёт идентификатор, над которым выполняется действие. Индекс в массиве не подошёл бы: список может измениться между чтением и удалением, поэтому к моменту использования индекс может указывать на другое устройство.
  • Последняя активность — это дата, а не момент. Достаточно, чтобы клиент узнал свой ноутбук, и недостаточно, чтобы построить журнал перемещений.
  • IP-адрес не возвращается вообще, в том числе для домашней сети или соединения, которым пользуется кто-то ещё. Выгрузка персональных данных объявляет device_and_network_identifiers постоянным изъятием по той же причине.
Дескриптор, которому ничего не соответствует, отвечает 404 not_found — ровно так же выглядит и устройство, удалённое из другой вкладки мгновение назад.

Удаление устройств

1

Удалите одно устройство

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

Удалите все устройства

Когда в списке больше одного устройства, появляется кнопка во всю ширину Отключить все устройства с собственным диалогом. Это один вызов Remnawave, а не цикл, потому что поустройственное отключение оставило бы частично отключённую подписку, если бы третий вызов провалился.
Удаление всех устройств требует входа, выполненного в последние пятнадцать минут. Устаревшей сессии отказывают с 401 reauthentication_required, и панель показывает «Войдите снова, чтобы подтвердить это действие», а не сырой отказ: средство исправления доступно самому клиенту. Удаление одного устройства такого требования не имеет: оно стоит одному устройству переподключения, а не всей настройки. Удаление всех без ?confirm=true отклоняется с 422 confirmation_required. При нуле подключённых устройств оно возвращает {"removed": 0}, вовсе не обращаясь к Remnawave. Оба вида удаления пишутся в собственный журнал безопасности клиента — device_removed с подписью подписки и сообщённым именем устройства, devices_removed_all с подписью и числом удалённых. Ни то, ни другое не записывает аппаратный идентификатор, а сам журнал доступен клиенту для чтения на /account/security.
Оператор также может перечислить и удалить устройства из профиля клиента в админ-панели под правами subscriptions.read и subscriptions.write. Этот путь пишет событие аудита с собственной ссылкой на устройство, но никогда с HWID. См. Операции администратора.

Смена ссылки на подписку

Что это. Отзыв текущей ссылки доступа и чтение новой обратно из Remnawave. Зачем это нужно. Это единственное средство исправления, когда ссылку передали или она утекла. Это же и самое разрушительное, что клиент может сделать со своей работающей настройкой: каждое устройство перестаёт подключаться, пока не будет импортирована новая ссылка. Обе половины этой фразы объясняют, зачем этот элемент управления существует и почему он защищён именно так.
Смена ссылки разом ломает подключение каждого устройства. Трафик и дата окончания не затрагиваются, но каждое устройство должно импортировать новую ссылку, прежде чем снова подключится.
Как этим пользоваться. Откройте /account/subscriptions/{id} и прокрутите до раздела Ссылка доступа. Карточка с предупреждением точно указывает, что сломается. Нажмите Выпустить новую ссылку; диалог требует, чтобы клиент ввёл фразу NEW LINK и вдобавок нажал подтверждение. При успехе всплывающее уведомление подтверждает это, а подсказка отсылает обратно к экрану подключения, чтобы добавить новую ссылку на каждое устройство. В Telegram то же действие находится на экране подписки за клавиатурой подтверждения/отмены, и его выполнение возвращает экран подключения с уже свежей ссылкой. API. POST /v1/account/subscriptions/{subscriptionID}/rotate-link, тело {"confirm": true}, за требованием недавнего входа. Отвечает {"subscriptionUrl": "…"}. Новая ссылка читается обратно из Remnawave, а не предполагается: её выпускает Remnawave, и показать клиенту старую после смены было бы хуже, чем не показать никакой. В журнал безопасности клиента пишется запись subscription_key_rotated, называющая только подпись подписки.

Смежные страницы

Веб-панель клиента

Остальная часть браузерного продукта: дашборд, оформление заказа, кошелёк, поддержка.

Бот Telegram

Тот же путь подключения в чате, с кнопками копирования текста.

Подписки

Права на услуги, лимиты устройств, окончание срока и что означает фаза.

Интеграция с Remnawave

Какая панель владеет ссылкой, устройствами и счётчиками трафика.