Справочник по клиенту

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

Сначала — про границу

У клиента две независимые вещи, и их часто путают. Аккаунт — это ключ входа, подписка MakeItFree, срок действия и список устройств. Прокси-часть — это импорт подписок и конфигов, он провайдеро-независимый.

Аккаунт замкнут на наш сервис: адрес личного кабинета зашит в обе сборки, а ключ проверяется в базе MakeItFree. Выдать такой ключ со стороны нельзя — это не ограничение лицензии, а то, как устроена проверка.

Authorization: Bearer <ключ входа> → lk.makeitfree.online
  • Работает с любым провайдером: импорт подписки по ссылке и прямых конфигов vless://, vmess://, trojan://, ss://, hysteria2://. Ключ входа для этого не нужен.
  • Только MakeItFree: mif://auth, срок подписки, список и удаление устройств, автоподхват подписки после входа. Клиент ходит за этим только на наш адрес.
  • Клиент не принимает произвольный хост для аккаунта: сменить адрес кабинета через deeplink, настройку или конфиг нельзя.
  • Хотите отдавать свои серверы в этом клиенте — отдавайте ссылку на подписку. Всё, что ниже про форматы и заголовки, к ней применимо полностью.
Поток входа

Как подписка попадает в приложение

Шаги 1 и 2 — путь подписчика MakeItFree. Шаг 2 работает и с чужой подпиской: это обычный импорт по ссылке.

  1. 1
    Вход по ключу — только через нашего бота

    Бот отдаёт пользователю кнопку с его ключом входа. Клиент ловит deeplink, кладёт ключ в защищённое хранилище (DPAPI / Keystore) и дальше подставляет его в заголовок Authorization: Bearer при запросах к личному кабинету MakeItFree. Ключ выдаётся один раз на Telegram-аккаунт и не меняется при продлении подписки.

    авторизация · только MakeItFree
    mif://auth?token=<ключ входа>

    Telegram не пропускает кастомные схемы в кнопках, поэтому бот ведёт на https-обёртку lk.makeitfree.online/app/auth, а она уже открывает mif://.

  2. 2
    Импорт подписки — с любым источником

    Ссылка открывается через deeplink или вставляется руками в разделе импорта. Клиент сам определит формат и подтянет список серверов. Импорт идемпотентен по URL источника: повторный вызов обновляет запись на месте, сохраняя её позицию в списке.

    импорт · любой провайдер
    mif://import?sub=<url>
    Happ metadataRemnawave Base64Xray JSON
  3. 3
    Заголовки устройства при запросе подписки

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

    HTTP headers
    x-hwid: <отпечаток устройства>
    x-device-os: windows | android
    x-ver-os: <версия ОС>
    x-device-model: <модель>

    Как формируется отпечаток на каждой платформе — в разделе HWID и устройства. Список устройств в интерфейсе приложения показывается только для подписки MakeItFree.

Настройка панели

Правила ответа в Remnawave

Чтобы клиент получил полноценный Xray JSON — с Reality, XHTTP и Hysteria2, — панель должна узнавать его по User-Agent. Иначе она отдаст обычный список share-ссылок, и часть возможностей просто не поднимется.

Два правила в Response Rules

Добавляются в конфигурацию правил ответа подписки. Оба отдают XRAY_JSON: десктоп и Android разбирают один и тот же формат.

response rules
{
  "name": "MakeItFree Desktop",
  "description": "Native MakeItFree VPN desktop client (Windows/macOS) — full Xray JSON (Reality/XHTTP/Hysteria2).",
  "enabled": true,
  "operator": "AND",
  "conditions": [
    {
      "headerName": "user-agent",
      "operator": "CONTAINS",
      "value": "MakeItFree-VPN (",
      "caseSensitive": true
    }
  ],
  "responseType": "XRAY_JSON"
},
{
  "name": "MakeItFree Android",
  "description": "Native MakeItFree VPN Android client — Happ-equivalent payload",
  "enabled": true,
  "operator": "AND",
  "conditions": [
    {
      "headerName": "user-agent",
      "operator": "CONTAINS",
      "value": "MakeItFree-VPN-Android",
      "caseSensitive": true
    }
  ],
  "responseType": "XRAY_JSON"
}

Пробел и скобка в значении обязательны

В правиле Desktop значение — "MakeItFree-VPN (", вместе с пробелом и открывающей скобкой. Если сократить до "MakeItFree-VPN", условие начнёт совпадать и с Android-клиентом, потому что его User-Agent тоже начинается с этой подстроки. Разделение правил держится ровно на этих двух символах.

что реально шлют клиенты
// Windows — попадает в правило Desktop
MakeItFree/0.8.0 MakeItFree-VPN (Windows 10.0.26200; DESKTOP-ABC)

// Android — попадает в правило Android
MakeItFree-VPN-Android/0.5.0 (Android 13; Xiaomi 2112123AG)

Регистр учитывается (caseSensitive: true), поэтому строки должны совпадать буква в букву. Проверить, что панель видит нужный UA, проще всего в её журнале доступа.

Что даёт XRAY_JSON

  • Reality и XHTTP приезжают со всеми параметрами — из плоской share-ссылки часть из них теряется.
  • Hysteria2 на Android поднимается только отсюда: из обычного списка ссылок клиент его не соберёт.
  • Полные имена серверов и тонкая настройка QUIC — port-hopping, обфускация, ограничение полосы.

Если правило не сработало, клиент не сломается: он разберёт обычный список ссылок и подключится — просто без XHTTP и Hysteria2.

Справочник

Форматы и схемы ссылок

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

Схема mif:// и Happ

deeplink schemes
mif://auth?token=<ключ входа>   // только MakeItFree
mif://import?sub=<url>          // любой провайдер
happ://add/<base64>              // любой провайдер

Параметры token, secret, key, auth вычищаются из логов перед записью — учитывайте это, если добавляете новые параметры.

Прямые конфиги серверов

СхемаНазначение
vless://VLESS-сервер (TCP / WS / HTTP-2 / gRPC / XHTTP, Reality)
vmess://VMess-сервер
trojan://Trojan-сервер
ss://Shadowsocks (плагины v2ray-plugin и xray-plugin)
hysteria2:// · hy2://Hysteria2 (QUIC)

Одиночный конфиг импортируется как подписка из одного сервера. На Android Hysteria2 приходит только в формате Xray JSON — из обычного списка share-ссылок он не поднимается.

Метаданные подписки

Клиент читает Happ-совместимые метаданные из HTTP-заголовков ответа и из инлайн-строк # key: value в начале тела. При конфликте выигрывает HTTP-заголовок.

ПолеЧто показывает
profile-titleНазвание подписки в списке
subscription-userinfoТрафик и дата окончания
profile-update-intervalКак часто обновлять в фоне
announceСообщение от провайдера в интерфейсе
support-urlКуда вести пользователя за помощью

Значения с префиксом base64: декодируются автоматически. Голые base64-похожие строки не трогаются — иначе название вроде «Premium» превратилось бы в мусор.