Sing-Box Launcher теперь на macOS
- суббота, 20 декабря 2025 г. в 00:00:09
Месяц назад я описывал wizard-подход к настройке sing-box без ручного JSON. Теперь это полноценный нативный macOS-клиент и Windows-клиент с TUN, системным прокси, menu bar, быстрым переключением узлов и решением бага Fyne через Objective-C.

В прошлой публикации я разбирал две главные боли при работе с sing-box: ручное редактирование JSON и теги узлов, которые «плывут» после обновления подписки. Решением стал wizard — он собирает конфиг из проверенных блоков, а не редактирует текст напрямую. Статья зашла, в комментариях спрашивали про macOS. Вот он.
Если не читали первую статью и хотите понять контекст глубже — ссылка выше. Здесь я не буду повторять теорию, а расскажу, что изменилось на практике.
Я очень активно использую AI-помощников при разработке. Честно говоря, без них я бы лет пять назад даже не взялся за такое.
Последние годы я больше CEO и фронтмен своей команды, чем разработчик. Было интересно самому понять, насколько можно поднять производительность, используя новые инструменты. Оказалось — можно. Go я до этого проекта не писал, Fyne не трогал, CGO с Objective-C — тем более. AI помогает разобраться быстрее, чем читать документацию с нуля.
Отдельный бонус — документация. Раньше я бы её точно забросил: писать README и гайды по шаблонам — не самое увлекательное занятие. С AI получилось сделать подробную документацию на двух языках, описать формат шаблонов, настройку парсера. Без AI на это просто не хватило бы времени.
Текст писал я сам, это не генерированный мусор от GPT :)
Нет. Хочу сделать удобный. Однокнопочный (или минимум лишних кнопок), точно не IDE вокруг конфигов.
У того же Hiddify много функционала. Но я не представляю, как объяснить этот функционал друзьям или родне. А вот моё приложение они ставят легко: скачал, запустил, прошёл wizard, работает.
Цель — не «самый мощный клиент», а «клиент, который можно дать человеку без технического бэкграунда».
Часто езжу с ноутбуком и удивляюсь, когда из Стамбула не открываются госуслуги. Правильно настроенная маршрутизация позволяет открывать и госуслуги, и Gemini, и GitHub, смотреть Netflix и слушать Яндекс.Музыку — из любой точки мира. Один клиент, одна кнопка.
Как это работает:
1. Парсер группирует узлы по регионам на основе тегов из подписки. В @ParserConfig указываем фильтры:
{
"tag": "us-ca-selector",
"type": "selector",
"options": { "default": "us-ca-fast" },
"filters": {
"tag": "/(🇺🇸|US|USA|United States|🇨🇦|CA|Canada)/i"
},
"comment": "Ручной выбор узлов США/Канады"
}
Парсер находит все узлы с тегами, содержащими флаги или названия стран, и добавляет их в этот selector.
2. Правила маршрутизации направляют трафик. В шаблоне конфига это выглядит так:
/** @SelectableRule
@label Gemini через США/Канаду
@default
@description Gemini требует узлы из США или Канады для работы
{ "rule_set": "gemini", "outbound": "us-ca-selector" },
*/
/** @SelectableRule
@label Российские домены через российские узлы
@default
{ "rule_set": "ru-domains", "outbound": "ru-selector" },
*/
В wizard эти правила превращаются в чекбоксы с выпадающим списком outbound'ов. Пользователь просто ставит галочки — не нужно редактировать JSON.
Результат из любой точки мира:
✅ Госуслуги открываются (видят российский IP)
✅ Gemini работает (видит IP из США)
✅ Яндекс.Музыка играет (геоблокировка обходится)
✅ Netflix показывает контент
✅ Локальные проекты (localhost, *.local) идут напрямую
✅ Рабочий VPN работает параллельно — корпоративные ресурсы не ломаются
Всё автоматически, без ручного переключения. Всё это настраивается один раз в wizard и продолжает работать при обновлении подписки.
Если вы админ или просто «тот человек, который настраивает интернет» для друзей и родни — знаете эту боль. Нужно раздать 100 людям работающий прокси. Каждому объяснять, что такое JSON и где менять server — не вариант.
С wizard это решается иначе:
Создаёте свой шаблон — один раз. Прописываете правила маршрутизации, selectors, rule-sets. Формат полностью открыт и задокументирован.
Кладёте шаблон в папку приложения — config_template.json.
Раздаёте людям приложение + ссылку на подписку. Они запускают wizard, вводят подписку, жмут «Сохранить». Всё.
Шаблон — ваш. Вы контролируете, какие правила будут у пользователей. Они видят только простой интерфейс с чекбоксами. Обновилась подписка — пользователь прошёл wizard заново, конфиг пересобрался с теми же правилами.
Это не «дать человеку JSON и надеяться, что он не сломает». Это «дать готовый инструмент, где сломать нечего».
На момент первой статьи был рабочий Windows-клиент и идея wizard-подхода. Парсер подписок работал, но в базовом виде.
Сейчас:
Полноценный macOS-клиент (версия 0.5.0)
Wizard и парсер отработаны на реальных сценариях
Системный прокси с автоматической регистрацией
Трей с быстрым переключением прокси
Wizard показал себя хорошо: с одной стороны, его можно гибко конфигурировать через шаблон, с другой — для пользователя он выглядит максимально просто.
Перенести приложение на macOS — это не «пересобрать с другим флагом». Пришлось разбираться с платформенными нюансами.
На Windows лаунчер работает через TUN-интерфейс (wintun.dll). На macOS — другой подход: системный прокси.
Как это устроено:
В конфиге sing-box используется mixed inbound с флагом set_system_proxy: true
sing-box сам регистрирует прокси в системных настройках
Браузеры и большинство приложений подхватывают настройки автоматически
Не нужны права администратора для базового сценария
Для определения текущих настроек прокси приложение использует networksetup — стандартную утилиту macOS. Парсит вывод, определяет приоритет сетевых интерфейсов (Wi-Fi, Ethernet и т.д.) и находит активный.
Для 90% задач — достаточно. Если приложение игнорирует системный прокси (некоторые игры, торрент-клиенты) — да, TUN был бы нужен. Но TUN на macOS требует Network Extension, Apple Developer Account ($99/год) и нотаризацию. Для open-source проекта это пока избыточно.
macOS-специфика, которую ожидаешь от нативного приложения:
Иконка в menu bar
Быстрое переключение прокси без открытия главного окна
При закрытии окна приложение остаётся в трее, а не завершается
Здесь была интересная техническая проблема.
Fyne (GUI-фреймворк на Go) имеет известный баг: после Hide() окна при клике на иконку в Dock окно показывается, но становится неотзывчивым — не реагирует на клики, кнопки close/minimize/maximize не работают.
Стандартного решения в Fyne нет. Пришлось написать обработчик на Objective-C через CGO: динамически создать класс DockReopenHandler, добавить метод applicationShouldHandleReopen:hasVisibleWindows: через Objective-C runtime и установить его как NSApplicationDelegate. Когда пользователь кликает на иконку в Dock — вызывается Go-callback, который корректно показывает окно.
// Создаём класс динамически через Objective-C runtime
Class delegateClass = objc_allocateClassPair(nsObjectClass, "DockReopenHandler", 0);
// Добавляем метод applicationShouldHandleReopen:hasVisibleWindows:
SEL selector = sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:");
class_addMethod(delegateClass, selector, (IMP)handleApplicationShouldHandleReopen, "c@:@c");
// Регистрируем класс и назначаем делегатом NSApp
objc_registerClassPair(delegateClass);
[NSApp setDelegate:dockDelegate];
Полный код: internal/platform/dock_handler.go
Теперь клик по Dock работает как ожидается: окно появляется и реагирует на ввод. Решение универсальное — работает на всех версиях macOS от 11 до 15, протестировано на Intel и Apple Silicon.
Не буду в деталях, как устроен wizard — это в документации. Расскажу, что показало практическое использование.
Конфиг не ломается при обновлениях. Wizard собирает его заново из тех же блоков. Шаги те же — результат предсказуемый.
Валидация до сохранения ловит ошибки. Раньше типичный сценарий: сохранил конфиг → sing-box не стартует → ищешь, где ошибка в JSON. Теперь wizard проверяет структуру до записи на диск.
Резервное копирование спасает. Перед каждым сохранением нового конфига приложение делает копию старого. Когда экспериментируешь с правилами маршрутизации — это важно.
После публикации пришёл фидбек, часть вещей поправили:
Улучшили обработку ошибок при парсинге подписок
Добавили поддержку большего количества форматов узлов
Исправили краевые случаи в миграции конфигов между версиями
Полная документация: ParserConfig
Парсер поддерживает основные протоколы:
VLESS (включая Reality) — мой основной выбор
VMess (base64 JSON)
Trojan
Shadowsocks (SIP002)
Hysteria2
Напомню проблему одним предложением: провайдер переименовал узлы после обновления, и правила маршрутизации перестали работать.
Пример: было HK-1, стало Hong Kong #12. Правило ссылалось на HK-1 — теперь оно не матчится ни с чем.
Что делает парсер:
Нормализует теги (можно задать префиксы, постфиксы, маски с переменными)
Группирует узлы в селекторы по фильтрам (regex, literal, negation)
При дубликатах тегов автоматически добавляет суффикс (HK-1, HK-1-2, HK-1-3)
Правила ссылаются на группы, а не на конкретные имена узлов
Результат: обновление подписки не ломает маршрутизацию. Узлы могут переименовываться — группы остаются стабильными.
Пять шагов от скачивания до работающего прокси. Подробнее — в README.
Скачать .zip с GitHub Releases
Распаковать, перетащить в Applications
Запустить. Gatekeeper спросит разрешение — это нормально для приложений не из App Store
Приложение само скачает sing-box — ничего ставить руками не нужно
Пройти wizard: указать подписку, выбрать правила, сохранить. Запустить.
Системный прокси включится автоматически. Проверить можно здесь: System Preferences → Network → (ваше подключение) → Advanced → Proxies.
Если уже есть рабочий config.json — положите его в папку приложения. Wizard сделает бэкап перед перезаписью.
Честно о том, чего нет.
TUN-режим. Требует Apple Developer Account, Network Extension и нотаризацию. Пока не в приоритете. Если это критично для вас — напишите в issues, посмотрим на спрос.
Автообновление приложения. Пока ручное. Проверяйте релизы на GitHub.
Часть опций sing-box. Это не «IDE для sing-box». Фокус — на повторяемой настройке и стабильных обновлениях подписок. Если нужны все опции — есть ручной JSON.
Не roadmap с датами, а направления.
Главное — развитие wizard. Идея оказалась рабочей: шаблон + визуальный выбор правил + автоматическая сборка конфига. Хочется развивать:
Больше готовых шаблонов под разные сценарии (путешествия, работа, gaming)
Упрощение создания своих шаблонов, (может быть колекции шаблонов?)
Визуальный редактор правил маршрутизации
Парсер подписок: больше протоколов, обработка edge-кейсов.
Linux-версия: нужна помощь с тестированием в разных DE и дистрибутивах.
Если хотите помочь — пишите в issues или PR.
Wizard-подход оказался рабочим. Теперь это не прототип, а полноценный macOS-клиент с системным прокси, треем и предсказуемым поведением.
Если пользуетесь sing-box на маке — попробуйте. Буду рад фидбеку в комментариях или в issues на GitHub.
Ссылки:
Первая статья: habr.com/ru/articles/973754
Лицензия: MIT
Что важнее всего для вас в macOS-клиенте sing-box?
Стабильная работа системного прокси
Быстрое переключение прокси из трея
Wizard для настройки без JSON
TUN-режим (даже если сложнее в настройке)