SwByeDPI - Swift-обертка для byedpi
Русский | English
Репозиторий является Swift-библиотекой, которая является оберткой над нативным C byedpi
Благодарность romanvht за его форк реализации Android-приложения над byedpi, которая вдохновила на создание данного проекта вместе с iOS-приложением, работающим на данном модуле
Модуль, в первую очередь, нацелен на iOS, минимальная версия - 10.0 и новее. Другие Apple-платформы (macOS 10.12+, tvOS 10.0+, watchOS 3.0+, visionOS 1.0+) заявлены как доступные, но имеют экспериментальную поддержку
Также есть возможность собрать решение для других платформ (Android, Linux), но не факт, что оно будет нормально работать - лучше нативно собрать byedpi под конкретную платформу как исполняемый файл и использовать напрямую. Может быть использовано скорее для целей разработки модуля на ОС Linux, нежели использования, что и применялось, так как данное решение писалось параллельно на macOS (XCode) и Linux (VSCode с Swift SDK)
SwByeDPI доступен к подключению в проект через SPM
Для работы доступны 3 модуля-библиотеки:
- ByeDPIC - Низкроуровневый скомпилированный C-модуль в режиме C-interoperability. Не содержит какого-либо ObjC/Swift кода и, в теории, может быть использован на самых старых устройствах экосистемы Apple. Не рекомендовано к использованию
- ByeDPIKit - Минимальная обертка над ByeDPIC, позволяющая запускать/останавливать нативный byedpi SOCKS-прокси с параметрами для DPI. Не содержит никаких Apple-платформенных проверок параметров ByeDPI в контексте Swift-окружения
- SwByeDPI - Расширенная обертка над ByeDPIC, которая базируется на ByeDPIKit'е. Содержит абстракции для конфигураций запуска, инструменты для создания URL-сессий под SOCKS-пркоси, предварительно добавленные наборы стратегий и доменов для тестирования и дальнейшего использования в byeDPI, а также функционал по тестированию и аналитике стратегий и доменов
Подключение SwByeDPI
//Package dependencies parameter
.package(url: "https://github.com/mIwr/SwByeDPI.git", .from(from: "0.17.3"))
//Target dependencies parameter (SwByeDPI)
.product(name: "SwByeDPI", package: "SwByeDPI")
//Target dependencies parameter (ByeDPIKit)
.product(name: "ByeDPIKit", package: "SwByeDPI")
//Target dependencies parameter (ByeDPIC)
.product(name: "ByeDPIC", package: "SwByeDPI")Все 3 модуля, по аналогии с SPM, доступны к подключению через CocoaPods. Имена pod'ов идентичны SPM
Примечание: согласно информации по CocoaPods, обновления модулей будут публиковаться на CocoaPods до декабря 2026 г.
Запуск byedpi в ByeDPIKit и SwByeDPI идентичен:
- Определяется команда для запуска ByeDPI SOCKS прокси, согласно документации
- Непосредственно запуск с передачей аргументов запуска ByeDPI SOCKS прокси
#if canImport(SwByeDPI)
import SwByeDPI
#else
#if canImport(ByeDPIKit)
import ByeDPIKit
#endif
#endif
var args: [String] = []
//...Определение команды для запуска
ByeDPI.start(args: args) { BDError in
//Обработка ошибки запуска
}- Спустя время, завершение работы ByeDPI
// В общем случае работу можно завершать так
_ = ByeDPI.stop()
// Если же при повторном запуске возникает ошибка bind error: Address already in use, то лучше останавливать через forceStopDPI()
_ = ByeDPI.forceStop()Для более эффективной работы ByeDPI в разных условиях (различные провайдеры интернета, геолокация, устройства, ОСи итд) был реализован механизм проверки стратегий на некотором списке доменов.
Для тестирования можно задать следующие параметры:
- Задержка между запросами к доменам (секунды). Увеличение значения улучшает достоверность тестирования. Оптимальное значение в ходе тестов - 1 секунда
- Количество запросов к домену. Увеличение значения увеличивает точность, но снижает общую скорость проверки. Оптимальное значение в ходе тестов - 2 запроса
- Количество потоков-worker'ов. Увеличение значения ускоряет проверку, но снижает достоверность проверки. Оптимальное значение в ходе тестов - Колиество ядер CPU * 2
- Ожидание ответа на запрос (секунды). Увеличение значения замедляет общую скорость проверки, но улучшает достоверность тестирования. Оптимальное значение в ходе тестов - 5 секунд
- Списки доменов для тестирования. Для подбора более универсальной стратегии и будущего анализа результатов лучше выбрать больше доменов. Если же задача открыть доступ только к некоторым ресурсам, то стоит выбрать (Если же их нет, то сначала добавить новый список) только их. Большой пулл доменов для проверки, логично, замедляет общую скорость теста
- Списки стратегий для тестирования. По умолчанию доступен только встроенный в SwByeDPI список стратегий
Под успешным запросом к домену через ByeDPI подразумевается ответ со статус-кодом 200..299 или любой другой, но с заголовком Content-Length (факт отправки и получения информации в теле ответа)
Так, проведя тестирование, можно отобрать универсальную стратегию (Важное уточнение - не самую лучшую для конкретных тестируемых доменов) по критерию Больше успешных запросов к доменам - лучше стратегия
Для более тонкой настройки необходимо использовать анализ результатов тестирования стратегий
Стратегии, проверенные на определенных доменах и показавшие свою эффективность (Наибольшее количество успешных запросов, прошедших DPI), уже можно использовать в ByeDPI. Однако в случае, когда необходимо тонко настроить работу ByeDPI (Настроить bypass для определенных доменов, использовать для определенных доменов самые эффективные стратегии, определить универсальную стратегию), простого выбора стратегии из результатов тестов недостаточно
Для этого в SwByeDPI был реализован модуль анализа результатов, результатом работы которого будет композитная стратегия, состоящая из:
- Bypass для DNS (53 порт) - больше используется при работе ByeDPI в туннеле
- Список доменов, на которых ByeDPI работать не будет - блок черного списка или ByeDPI-bypass. По документации byedpi в секции "Подробнее --auto --hosts" этот блок всегда будет идти в начале композитной стратегии
- Список или списки доменов, для которых из протестированных отобраны самые эффективные стратегии - блок белого списка ByeDPI. Данный блок может находиться в начале, если отсутствует черный список доменов, или в середине/конце композитной стратегии
- Стратегия, которая может быть не самой лучшей для конкретного домена, но показавшая наилучшие результаты (Наибольшее количество успешных запросов, прошедших DPI), является универсальной, и может быть использована для "остальных" доменов при работе ByeDPI - блок универсальной стратегии. Этот блок всегда будет находиться в конце композитной стратегии
Базовая операция над результатами тестирования стратегий, на которой работает весь анализ - расчет покрытия стратегии на список доменов (Успешные запросы к доменам в списке). Вся логика по анализу расположена в SBDTestResultAnalyticsUtil.swift
Примечание 1: Использование каждого блока опционально, т.е. можно задать использование всех блоков в композите, использование только белых списков итд
Примечание 2: Списки доменов для тестирования в исходном виде не оптимально использовать в ByeDPI --hosts. Так как для ByeDPI достаточно указать лишь домены второго уровня (Пример: если указать в --hosts домен googlevideo.com, то ByeDPI будет обрабатывать и все поддомены), можно сгенерировать новый список (Анализатор стратегии именно это и делает), состоящий только из уникальных доменов второго уровня. Чтобы сделать это, можно воспользоваться функицей retrieveSLDList()
var domainList: SBDDomainList
//...
let sldList = domainList.retrieveSLDList()Примечание 3: Для связности между блоками (Черный/белый список и универсальная стратегия) и стратегиями внутри (Стратегии под разные списки доменов в белом списке) используется связка вида -An
В SwByeDPI добавлены списки сайтов для тестирования и ByeDPI-bypass, а также стратегии в виде текстовых файлов, из которых потом генерируются *.swift-файлы, компилируемые в результирующий модуль (Built-in домены и стратегии). Можно изменять или удалять текущие списки, а также добавлять новые.
Генерация происходит через скрипт-кодогенератор в ручном режиме, который определяет в Assets все файлы с расширениями *.strategies и *.domains. Примечание: формат файлов списков един и для стратегий, и для доменов - по одной(-ому) на строку
В качестве Example-приложения реализовано iOS-приложение (iOS 14+, SwiftUI). Проект может быть собран и под другие платформы (Экспериментальная поддержка для tvOS 17.0+ и macOS 11.0+)
Приложение локально запускает ByeDPI и может перенаправлять трафик других приложений и устройств в локальной сети через него
Приложение позволяет:
- Устанавливать настройки запуска ByeDPI (прослушиваемый IP адрес, порт SOCKS прокси, аргументы командной строки)
- Автоматически исправлять параметры стратегии ByeDPI, если они не поддерживаются устройством и/или ОСью
- Проводить тестирование стратегий и сохранять последний прогон тестирования
- Анализировать и составлять наиболее оптимальные стратегии на основе результатов тестирования
- При составлении оптимальных стратегий можно указывать черные (ByeDPI bypass), белые (конкретные стратегии работают только для конкретных доменов) списки доменов. Подробнее --auto --hosts
- Добавлять/изменять/удалять домены для тестирования стратегий, фильтрации доменов для ByeDPI bypass
- Добавлять/изменять/удалять стратегии для их тестирования
- Устанавливать DNS (DoH/DoT) - доступно только в контексте сборки полноценного VPN-клиента
Примечание: по сравнению с Android, VPN Network Extension в iOS не может управлять туннелированием для конкретных приложений. Для этого используется функционал самого byedpi с указанием конкретных доменов второго уровня (черные/белые списки)
Для продвинутого использования можно ознакомиться с комплексной инструкцией от комьюнити ByeByeDPI-Manual.
Возможны 2 варианта сборки приложения:
- Полноценный VPN клиент (ByeByeDPI) ByeDPI -> Tun2SocksKit -> NEVPN + DNS - требует наличия платной лицензии разработчика: для разработки, отладки и загрузки в TestFlight достаточно уч. записи физ. лица, для релиза в App Store - только юр. лицо или ИП, согласно нормативами Apple Developer 5.4. Примечание: приложение не является VPN-клиентом в чистом виде, так как ByeDPI работает локально на устройстве - трюк с VPN нужен для возможности работы функционала ByeDPI в фоне (приложение свернуто или вовсе не запущено) и возможности обработки интернет-трафика всех приложений в смартфоне и устройств в локальной сети (Необходимо дать разрешение на доступ к локальной сети приложению). Поддержка в NetworkExtension DoH/DoT дает возможность обходить гео-блокировки некоторых сервисов
- ByeDPI SOCKS прокси-сервер (ByeDPI) - для запуска на собственных устройствах, не требует наличия платной лицензии разработчика. Данная сборка идеально подходит для отладки и тестирования функционала приложения на конечных устройствах: можно протестировать стратегии, собрать оптимальный композит через анализатор. Нюанс здесь в том, что ByeDPI будет работать, только пока приложение открыто (foreground)
- Клонируйте текущий репозиторий:
git clone https://github.com/mIwr/SwByeDPI
- Добавьте в связку ключей сертификаты и закрытые ключи для подписи приложения, импортируйте профили разработки
В Apple Developer для приложения (VPN клиент) необходимо выполнить следующее (При условии, что уже есть сертификат хотя бы для разработки и управление подписями идет в ручном режиме):
- Зарегистрировать App Group ID, который будет объединять приложение-хост и Network Extension
- Зарегистрировать App ID для приложения-хоста. В Entitlements указать App Groups (с указанием ранее созданной), Network Extensions и Personal VPN
- Зарегистрировать App ID для Network Extension. В Entitlements указать те же пункты, что и для приложения-хоста
- Создать профили разработки для приложения-хоста и Network Extension
- Импортировать профили в XCode
- Запустите сборку приложения (ByeByeDPI или ByeDPI) через GUI XCode или Terminal
- VPN-туннель запустился, но сайты не открываются и в логах (Console.app) циклично появляется лог 'udp session start - connect - destruct'. Связано с адресом ByeDPI 127.0.0.1/localhost - В Network Extenson ОС отбрасывает все пакеты на такой адрес. Необходимо указывать любой другой локальный адрес. Примечание: при подключенном Wi-Fi в провайдере локальный IP адрес автоматом подставится, если указан на вход 127.0.0.1, ::1, 0.0.0.0 или ::.
- До iOS 14 приложение будет работать крайне нестабильно ввиду жестких лимитов для Network Extension - 15 Мб. После превышения этого лимита ОС без предупреждения и краша убьет VPN туннель. Решение - использовать приложение на смартфонах iOS 15+, где лимит уже 50 Мб. Примечание: в ходе тестов было установлено, что при правильном конфиге Tun2SOCKS потребление ОЗУ не превышает даже 15 мб (В среднем держалось на уровне 4.3-4.8 мб), так что, теоретически, данный NetworkExtension можно перенести на рельсы UIKit'а, чтобы дать поддержку даже для iOS 10.0+ с ограничением 15 мб на Network Extension
- Постоянное нарастание используемой ОЗУ в процессе работы тунеля (веб-серфинг итд) от самого старта вплоть до SIGKILL от ОС - включен редирект логов из stdout/stderr (hev-socks-tunnel, byedpi), который необходимо выключить/закомментить в коде, включая команды для установки уровня логирования для byedpi/Tun2SOCKS






