MosaicVPN — клиент с открытым исходным кодом на движке sing-box. Если вы держите собственный VPN-сервис, вы можете отдавать своим пользователям этот клиент вместо того, чтобы писать свой: смарт-группы, автовыбор узла, брендирование и биллинг настраиваются одним JSON-манифестом на вашей стороне. Кода писать не нужно.
Клиент понимает обычные форматы подписок «из коробки» — sing-box JSON, Clash YAML, v2ray base64 и SIP008. Если у вас уже есть подписка в любом из них, клиент заработает без изменений на вашей стороне.
Всё, что описано ниже, — это дополнительный слой. Он включается, когда ваша подписка отдаёт манифест, и даёт то, чего нет в обычных подписках: группы с автовыбором, ваш бренд и ваш биллинг внутри клиента.
На тот же URL, что пользователь вставляет в клиент, отвечайте JSON-манифестом
с заголовком Content-Type: application/json. Минимальный рабочий вариант:
{
"provider_name": "Ваш Сервис",
"user_tier": "pro",
"groups": [
{
"id": "auto",
"title": "Автовыбор",
"type": "urltest",
"badge": "Рекомендуется",
"nodes": [
{ "id": "de-01" },
{ "id": "nl-01" },
{ "id": "fi-01" }
]
}
]
}
Поле nodes[].id должно совпадать с идентификаторами серверов, которые
вы отдаёте в конфигурации подписки. Если узел с таким ID не найден, он молча
выпадет из группы — это самая частая ошибка при интеграции.
Добавьте подписку в клиент. На вкладке «Группы» появится ваша группа «Автовыбор» с бейджем. Нажатие на неё замерит задержку до каждого узла и подключит к самому быстрому.
Манифест — необязательное расширение. Клиенты старых версий и другие приложения (Hiddify, NekoBox) продолжат читать вашу подписку как обычно, игнорируя неизвестные им поля.
Манифест — корневой объект, которым вы управляете поведением клиента у своих пользователей. Он состоит из четырёх независимых частей, каждая необязательна.
| Поле | Тип | Назначение |
|---|---|---|
| provider_name | string | Название сервиса в интерфейсе клиента |
| user_tier | string | Уровень пользователя: free, pro, vip |
| telemetry_url | string | Куда клиент шлёт статистику узлов (необязательно) |
| groups | array | Смарт-группы — см. раздел III |
| routing_rules | array | Правила маршрутизации по домену/IP/приложению |
| profile | object | Брендирование и биллинг — см. раздел IV |
Клиент запрашивает манифест по URL подписки и кэширует его локально. Если ваш сервер недоступен, пользователь продолжит работать на последней сохранённой версии — подключение не сломается из-за недоступности вашего API.
Группа — это набор узлов плюс правило, по которому клиент выбирает из них один. Вместо длинного списка серверов пользователь видит несколько понятных вариантов: «Автовыбор», «Германия», «Для стриминга».
Клиент замеряет пинг до каждого узла и берёт самый быстрый. Универсальный вариант по умолчанию.
Учитывает вес узла: чем больше вес, тем чаще узел выбирается. Разгружает популярные серверы.
Берётся первый живой узел из списка. Порядок задаёте вы полем priority.
Без автовыбора — всегда конкретный сервер. Для выделенных или премиальных узлов.
{
"provider_name": "Ваш Сервис",
"user_tier": "pro",
"groups": [
{
"id": "auto",
"title": "Автовыбор",
"type": "urltest",
"badge": "Рекомендуется",
"category": "smart",
"icon": "lightning",
"description": "Самый быстрый узел прямо сейчас",
"ping_interval": 30,
"max_retries": 3,
"failover_delay": 2,
"nodes": [
{ "id": "de-01" },
{ "id": "nl-01" },
{ "id": "fi-01" }
]
},
{
"id": "balanced",
"title": "Распределённая нагрузка",
"type": "weighted_round_robin",
"description": "Мощные узлы принимают больше подключений",
"nodes": [
{ "id": "de-01", "weight": 50 },
{ "id": "de-02", "weight": 30 },
{ "id": "nl-01", "weight": 20 }
]
},
{
"id": "vip-de",
"title": "Германия VIP",
"type": "fallback",
"user_tier": "vip",
"badge": "VIP",
"nodes": [
{ "id": "de-vip-01", "priority": 1 },
{ "id": "de-vip-02", "priority": 2 }
]
}
]
}
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
| id | string | — | Обязательное. Уникальный идентификатор группы |
| title | string | — | Обязательное. Название для пользователя |
| type | string | urltest | Стратегия выбора узла |
| nodes | array | — | Обязательное. Узлы группы |
| user_tier | string | — | Минимальный уровень для доступа к группе |
| badge | string | — | Короткая метка на карточке |
| category | string | — | smart, compatibility, raw |
| icon | string | — | Например shield, lightning, flag_de |
| description | string | — | Пояснение под названием |
| ping_interval | int | 30 | Секунды между проверками живости |
| max_retries | int | 3 | Неудач подряд до пометки «мёртв» |
| failover_delay | int | 2 | Секунды до переключения на следующий узел |
Начиная с версии 1.1, клиент поддерживает динамический многоуровневый выбор из публичного пула нод (Stratified Fair Allocation). Каждая группа ранжирует ноды по комбинированному скору (задержка + джиттер + потеря пакетов + аптайм) и применяет адаптивный failover:
stable (Оптимальный маршрут) — взвешенная балансировка между проверенными узлами Европы.compatibility (Маршрут совместимости / Adaptive TLS) — устойчивый профиль VLESS Reality на порту 443 с CDN-маскировкой для сотовых сетей.max-speed (Максимальная скорость) — выбор наименее загруженных нод с широким каналом.min-latency (Минимальный пинг) — динамический urltest с порогом толерантности 50 мс.germany, finland, great-britain, france, usa, canada, japan, singapore.Профиль превращает клиент в витрину вашего сервиса: ваш логотип, ваш акцентный цвет, ваш тариф и ваша кнопка оплаты. Пользователю не нужно уходить на сайт, чтобы пополнить баланс.
{
"profile": {
"branding": {
"logo_url": "https://example.com/logo.svg",
"accent_color": "#B85C38",
"support_url": "https://t.me/mosaicvpnbot",
"provider_description": "Защищённое сетевое соединение"
}
}
}
Клиент умеет показывать баланс, тариф и кнопку пополнения, связываясь с вашим ботом. Ключи и токены остаются на вашей стороне — клиент только открывает ссылки и читает статус по вашим эндпоинтам.
{
"profile": {
"billing": {
"type": "telegram_bot",
"bot_username": "mosaicvpnbot",
"pricing_model": "daily",
"price_per_day": { "RUB": 1.0, "USDT": 0.01 },
"trial_days": 3,
"payment_methods": ["card", "crypto"],
"endpoints": {
"profile": "https://api.example.com/v1/profile",
"topup": "https://api.example.com/v1/topup",
"status": "https://api.example.com/v1/status"
}
}
}
}
В манифест попадают только публичные URL. API-ключи, токены бота и подписи вебхуков остаются у вас на сервере — клиент их не видит и не хранит.
Личный кабинет доступен как через встроенный в клиент интерфейс, так и на сайте (/cabinet.html).
Архитектура сессий построена на криптографическом обмене кодами (OAuth-style enrollment flow):
mosaicvpn://enroll/callback?code=...&state=.... Приложение подтверждает токен через API сервера и мгновенно активирует подписку без ручного ввода ключей.localStorage на вебе и в SharedPreferences в приложении), гарантируя мгновенную отрисовку баланса и активных дней даже при медленном соединении.@mosaicvpnbot) для моментальной оплаты картами и USDT без комиссии сети.
Секции services и widgets позволяют добавить в клиент
собственные элементы: выбор маршрута, показатель трафика, кнопку действия или
ссылку на ваш ресурс.
{
"profile": {
"services": [
{
"id": "streaming",
"type": "proxy_picker",
"title": "Маршрут для видеосервисов",
"description": "Отдельная группа маршрутов для медиасценариев",
"icon": "play",
"config": { "group_id": "streaming" }
}
],
"widgets": [
{
"id": "traffic",
"type": "progress_bar",
"title": "Трафик за месяц",
"data_source": "billing.profile",
"fields": ["used_gb", "limit_gb"]
}
]
}
}
| Тип сервиса | Что показывает |
|---|---|
| proxy_picker | Выбор узла из указанной группы |
| value_display | Значение из вашего API (баланс, срок) |
| action | Кнопка, вызывающая ваш эндпоинт |
| web_view | Встроенная страница |
| link | Внешняя ссылка |
Уровень пользователя задаётся в корне манифеста полем user_tier,
а требование группы — полем user_tier внутри группы. Группа
с более высоким требованием пользователю недоступна.
| Уровень | Порядок | Типичное применение |
|---|---|---|
| free | 1 | Общий пул, ограниченная скорость |
| pro | 2 | Основной платный тариф |
| vip | 3 | Выделенные узлы, приоритет |
Проверка выполняется на стороне демона: попытка подключиться к группе выше своего
уровня возвращает 403. Группы, недоступные по уровню, показываются
в интерфейсе с пометкой — это работает как апселл, а не как скрытая ошибка.
Тир управляет отображением и доступом к группам внутри клиента. Реальное ограничение доступа к узлам обеспечивается вашим сервером: не отдавайте в подписке те узлы, к которым пользователь не должен подключаться.
| Протокол | Транспорт |
|---|---|
| VLESS | TLS · Reality · ws · grpc · xhttp |
| VMess | TCP · ws · grpc |
| Hysteria2 | QUIC |
| Shadowsocks | TCP · UDP |
| Trojan | TLS |
| Naive | HTTP/2 |
| AmneziaWG | WireGuard |
Формат определяется автоматически, указывать его не нужно:
sing-box JSON, Clash YAML, v2ray base64,
SIP008. Дубликаты узлов отсеиваются при импорте.
Демон mosaicd поднимает HTTP-API на петлевом интерфейсе.
Оно полезно, если вы делаете свою обвязку поверх клиента.
Порт назначается динамически. Демон слушает 127.0.0.1:0,
то есть ОС выдаёт свободный порт при старте. Адрес, PID и токен доступа
записываются в lockfile, откуда их читает клиент:
{
"host": "127.0.0.1",
"port": 51734,
"token": "<токен доступа>",
"pid": 12480,
"version": "0.2.0",
"started": "2026-08-08T21:30:00Z"
}
Расположение lockfile: %LOCALAPPDATA%\Mosaic на Windows,
$XDG_DATA_HOME/mosaic или ~/.local/share/mosaic на Linux,
~/Library/Application Support/Mosaic на macOS.
Каталог можно переопределить переменной MOSAIC_DATA_DIR.
Порт из предыдущего запуска не переиспользуется — читайте lockfile каждый раз,
а не кэшируйте значение.
| Метод и путь | Назначение |
|---|---|
| GET /v1/manifest | Текущий манифест провайдера |
| GET /v1/groups/{id}/select | Выбрать узел по стратегии группы |
| GET /v1/groups/{id}/health | Состояние узлов группы |
| GET /v1/servers | Список серверов |
| POST /v1/subscriptions | Добавить подписку |
| POST /v1/connect | Подключиться к узлу |
| GET /v1/status | Статус подключения |
Демон слушает только петлевой интерфейс и не принимает внешние подключения. Запросы требуют токен из lockfile — это осознанное ограничение безопасности.
Для автоматизации из bash/python-скриптов и AI-агентов (Cursor, Claude Code, Windsurf)
клиент предоставляет прямой REST API мост и полноценный MCP-сервер.
Эндпоинты доступны по пути /mcp/v1/* и поддерживают как стандартный заголовок
Authorization: Bearer <token>, так и заголовок X-MCP-Token или параметр ?token=.
Для локальных GET-запросов на петлевом интерфейсе (127.0.0.1) действует безопасный read-only доступ без передачи токена.
| Метод и путь | Параметры | Описание |
|---|---|---|
| GET /mcp/v1/status | — | Статус туннеля, активная нода/группа, трафик и аптайм |
| GET /mcp/v1/servers | — | Список всех доступных серверов подписок |
| GET /mcp/v1/groups | — | Список Smart-групп (min-latency, stable, max-speed, страны) |
| POST /mcp/v1/connect | server_id, group_id, country_code | Мгновенное подключение к серверу или смарт-группе |
| POST /mcp/v1/disconnect | — | Остановка активного VPN туннеля |
| GET /mcp/v1/egresses | — | Список локальных прокси-слушателей (SOCKS5/HTTP) |
| POST /mcp/v1/egresses | name, protocol, listen | Создание нового локального egress-порта с горячей перезагрузкой |
| DELETE /mcp/v1/egresses/{id} | — | Удаление egress-слушателя с синхронизацией sing-box |
| POST /mcp/v1/egresses/{id}/toggle | active (optional) | Включение / отключение egress-прокси без разрыва VPN |
import requests
BASE = "http://127.0.0.1:51734/mcp/v1"
HEADERS = {"X-MCP-Token": "ваш_токен_из_lockfile"}
# 1. Подключиться к маршруту с минимальным пингом
requests.post(f"{BASE}/connect", json={"group_id": "min-latency"}, headers=HEADERS)
# 2. Создать выделенный локальный SOCKS5 порт для парсера или Telegram-бота
res = requests.post(f"{BASE}/egresses", json={
"name": "Scraper Egress",
"protocol": "socks",
"listen": "127.0.0.1:1082"
}, headers=HEADERS).json()
egress_id = res["data"]["egress"]["id"]
print(f"Egress поднят на 127.0.0.1:1082 (ID: {egress_id})")
# 3. Временно отключить egress при необходимости
requests.post(f"{BASE}/egresses/{egress_id}/toggle", json={"active": False}, headers=HEADERS)
Для подключения к AI-ассистентам добавьте MCP-сервер Mosaic в конфигурационный файл mcpServers:
{
"mcpServers": {
"mosaic-vpn": {
"url": "http://127.0.0.1:51734/mcp",
"headers": {
"Authorization": "Bearer ваш_токен_из_lockfile"
}
}
}
}
Агентам становятся доступны нативные функции: mosaic_status, mosaic_connect (с поддержкой group_id),
mosaic_disconnect, mosaic_list_egresses, mosaic_add_egress, mosaic_toggle_egress, mosaic_test_url.
Нет. Брендирование, группы и биллинг задаются манифестом с вашего сервера. Форк нужен только если вы хотите менять саму логику приложения.
Клиент использует последний сохранённый манифест. Пользователь продолжит подключаться к узлам, которые уже знает.
Да. Клиент построен на sing-box под лицензией GPL-3.0, поэтому коммерческое использование разрешено, но при распространении собственной сборки вы обязаны раскрыть исходный код своей производной работы и сохранить лицензию. Использование оригинальных сборок с вашим манифестом никаких дополнительных обязательств не создаёт.
github.com/DangerousANEN/mosaicvpn — исходники клиента, демона и готовые сборки под Windows, Linux и Android.
Поднимите его на любом статическом хостинге, добавьте ссылку как подписку в клиент и проверьте вкладку «Группы». Ошибки разбора видны в разделе «Логи» внутри приложения.