RKNboost
Требования
- Node.js 20+ (проверено на 24)
- npm 10+
Команды
npm install # зависимости + скачивание бинарника Electron
npm run dev # dev-режим: HMR для UI, авто-рестарт main-процесса
npm run start # запуск собранной версии без упаковки
npm run build # typecheck + сборка main/preload/renderer в out/
npm run lint # ESLint
npm run format # Prettier
npm run typecheck # tsc для node- и web-частей отдельно
npm run build:unpack # быстрая проверка: приложение без установщика (release/*-unpacked)
npm run build:mac # .dmg + .zip (x64 + arm64)
npm run build:win # NSIS .exe (x64; arm64 не собираем — нет подписанного WinDivert)
npm run build:linux # AppImage + .deb
Установщики под чужую ОС локально собрать нельзя — для этого есть CI (
.github/workflows/ci.ymlсобирает все три платформы и кладёт артефакты в Actions).
Если после
npm installкомандаnpm run devпадает сError: Electron uninstall— бинарник Electron не докачался; исправляется повторным запускомnode node_modules/electron/install.js.
Структура
src/
main/ # Node-процесс: окна, меню, доступ к ОС
index.ts lifecycle приложения, single instance
window.ts createWindow / createPopupWindow, настройки безопасности
ipc.ts все ipcMain.handle
preload/ # мост между main и renderer (sandbox, contextBridge)
shared/ # ipc-contract.ts — типы каналов, общие для всех процессов
renderer/ # React-приложение (обычный браузерный код, без Node API)
build/ # иконки и entitlements для electron-builder
resources/ # файлы, попадающие в собранное приложение (иконка окна)
out/ # результат electron-vite build
release/ # готовые установщики
Как добавить свой IPC-канал
- Опишите канал в
src/shared/ipc-contract.ts(аргументы и результат). - Зарегистрируйте обработчик в
src/main/ipc.tsчерез хелперhandle(...)— типы проверятся. - Добавьте метод в объект
apiвsrc/preload/index.ts. - Вызывайте из React как
window.api.мойМетод()— тип подтянется автоматически.
События из main в renderer описываются в IpcEvents и подписываются через subscribe(...)
(пример — onThemeChanged, возвращает функцию отписки для useEffect).
Что показывают демо-карточки
| Карточка | Каналы | Что демонстрирует |
|---|---|---|
| Система | app:info |
версии Electron/Chromium/Node, платформа, путь к userData |
| IPC ping | ping |
минимальный invoke/handle |
| Нативный диалог | dialog:open-file |
системный выбор файла + fs.stat в main |
| Всплывающее окно | dialog:message-box, window:open-popup |
модальный диалог ОС и второе BrowserWindow |
| Тема оформления | theme:* |
nativeTheme как источник правды, реакция на смену темы в ОС |
Тайтлбар системный на всех платформах — окно создаётся без frame/titleBarStyle, рамку
и кнопки свернуть/развернуть/закрыть рисует сама ОС.
Безопасность
sandbox: true,contextIsolation: true,nodeIntegration: false;- renderer не имеет доступа к
ipcRenderer— только к методам изwindow.api; setWindowOpenHandlerиwill-navigateне дают уйти на внешний origin, ссылки открываются в системном браузере, причём только с протоколами изALLOWED_EXTERNAL_PROTOCOLS;- в
index.htmlзадан CSP без внешних источников.
Иконки
build/icon.png (1024×1024) — исходник, из него electron-builder делает иконки для всех платформ;
build/icon.icns и build/icon.ico лежат рядом как готовые варианты. resources/icon.png —
иконка окна для Linux. Замените эти файлы своими, имена оставьте прежними.
Подпись и нотаризация
По умолчанию выключены (notarize: false), сборки неподписанные — их можно запускать локально,
но macOS покажет предупреждение Gatekeeper при переносе на другую машину.
Чтобы включить:
- macOS: переменные окружения
CSC_LINK(base64 сертификата Developer ID) иCSC_KEY_PASSWORD, плюсAPPLE_ID,APPLE_APP_SPECIFIC_PASSWORD,APPLE_TEAM_IDиnotarize: trueвelectron-builder.yml. - Windows:
CSC_LINKиCSC_KEY_PASSWORDс .pfx-сертификатом.
В CI эти значения передаются секретами GitHub — место уже отмечено комментарием в
.github/workflows/ci.yml.
Обход блокировок (zapret)
Движки и данные — из двух сторонних проектов, оба MIT, оба скачиваются npm run zapret:fetch
(вызывается автоматически из npm run build) в resources/zapret/ (в git не хранится):
- bol-van/zapret — сами движки:
tpws(macOS, SOCKS5-прокси без root) иwinws.exe+ драйвер WinDivert (Windows, служба с правами администратора). WinDivert — LGPLv3/GPLv2 на выбор; лицензии обоих проектов кладутся рядом с бинарниками (LICENSE.zapret.txt,LICENSE.WinDivert.txt). - Flowseal/zapret-discord-youtube —
списки сайтов (
resources/zapret/lists/) и fake-пакеты (resources/zapret/fakes/). Версия зафиксирована по sha коммита вscripts/fetch-zapret.mjs(FLOWSEAL_COMMIT), лицензия —LICENSE.flowseal.txt.
Свои сгенерированные стратегии для Windows (src/main/zapret/strategies.win32.generated.ts,
22 варианта) — не батники: scripts/import-flowseal-strategies.mjs разбирает general*.bat
из того же репозитория Flowseal и переносит аргументы winws в TypeScript. Файл коммитится;
перегенерировать и свериться через git diff нужно вручную при обновлении FLOWSEAL_COMMIT.
На macOS tpws не умеет ни fake-пакетов, ни UDP — там свои профили
(src/main/zapret/strategies.ts, раздел DARWIN_DEFINITIONS) поверх тех же списков.
Списки сайтов пользователь может редактировать полностью (включая встроенные) — рабочая копия
живёт в userData/zapret-lists и переживает обновление приложения; tpws/winws сами
перечитывают список при изменении файла, перезапуск обхода не нужен (src/main/zapret/lists.ts).
Windows: служба и права
winws требует драйвер WinDivert и права администратора, поэтому на Windows он работает не как
обычный дочерний процесс, а как служба Windows rknboost-zapret (src/main/zapret/service.win32.ts).
Устанавливает и настраивает её само приложение — не инсталлятор, — потому что аргументы winws
зависят от выбранной пользователем стратегии.
-
Приложение запрашивает права администратора при каждом запуске (
win.requestedExecutionLevel: requireAdministratorвelectron-builder.yml). Поэтому все действия со службой выполняются напрямую, без отдельных запросов UAC по ходу работы. Если приложение почему-то запущено без прав (dev-режим — там манифеста нет), включается запасной путь:outer.ps1черезStart-Process -Verb RunAsподнимает само приложение с флагом--elevated-service-task, и UAC запрашивается на него, а не наpowershell.exe— в окне UAC пользователь должен видеть имя приложения, а не постороннюю программу. При установке службы обычным пользователям выдаётся право наstart/stopименно этой службы (sc sdset), так что и без прав включение-выключение обхода работает. -
Автозапуск с системой включён по умолчанию (
sc config start= auto) — обход работает и после перезагрузки, не дожидаясь запуска приложения. Отключается переключателем в настройках (тоже через UAC). Выключение обхода кнопкой на главном экране действует только до следующей перезагрузки, если автозапуск остался включён — служба поднимется вместе с системой заново. -
arm64 не поддерживается: у WinDivert нет подписанной сборки под arm64 (только x64 через эмуляцию на Windows 11), поэтому
electron-builder.ymlсобирает Windows-инсталлятор только для x64. -
Установщик — per-user (ставится в
%LocalAppData%, один клик, без UAC на саму установку).⚠️ Известный компромисс. Каталог установки доступен на запись обычному пользователю, а exe при этом требует администратора — значит подмена
RKNboost.exeдаёт злоумышленнику права администратора с подтверждения самого пользователя. Это осознанный выбор владельца проекта в пользу быстрой установки без UAC. Безопасный вариант —perMachine: true, тогда exe лежит в защищённом от записиProgram Files, но установка снова требует UAC и мастера.Служба работает от
LocalSystem, и еёbinPathне должен указывать в каталог, куда обычный пользователь может писать без прав администратора — поэтому при первом включении обхода приложение копируетwinws.exeи WinDivert в защищённый ACL'ом каталог в%ProgramData%(protectedWinwsPath()вsrc/main/zapret/paths.ts) и указывает службе именно на эту копию, а не на оригинал в папке установки. При удалении приложения деинсталлятор (build/installer.nsh) сам останавливает и снимает службу вместе с этой копией. -
На одну машину служба одна: её конфиг (
%ProgramData%\rknboost\zapret\strategy.cfg) хранит стратегию того пользователя, который последним её менял, — с несколькими пользователями на одной машине это разделяется некорректно.
Авто-обновления
Не подключены. Если понадобятся: npm i electron-updater, добавить секцию publish
в electron-builder.yml и вызвать autoUpdater.checkForUpdatesAndNotify() в src/main/index.ts.