CocoaPods trunk is moving to be read-only. Read more on the blog, there are 9 months to go.

SwByeDPI 0.17.3

SwByeDPI 0.17.3

Maintained by mIwr.



SwByeDPI 0.17.3

  • By
  • mIwr

SwByeDPI - Swift wrapper for byedpi

ByeDPI Logo

Русский | English

Swift5 Swift6 LatestRelease

Swift Package Manager compatible SPMPlatform SPMLicense

PodVersion PodPlatform PodLicense

Repository represents the Swift framework, which is native C byedpi wrapper

Thanks to romanvht for his byedpi-based Android app fork. It inspired the creation of this project along with an iOS app running on this module

Content

Introduction

The module is primarily targeted at iOS, min version 10.0 and newer. Other Apple platforms (macOS 10.12+, tvOS 10.0+, watchOS 3.0+, visionOS 1.0+) are listed as available but have experimental support.

It's also possible to build a solution for other platforms (Android, Linux), but it's not guaranteed to work properly. It's better to build byedpi natively for a specific platform as an executable and use it directly. Such feature also can be used for module development on Linux, which is what was used, as this solution was written in parallel on macOS (XCode) and Linux (VSCode with Swift SDK).

Setup

Swift Package Manager

SwByeDPI is available through SPM

There are 3 modules-libraries:

  1. ByeDPIC - Low-level compiled C-module. It doesn't contain any ObjC/Swift sources, so it can be used on the oldest Apple devices. Not recomended for use
  2. ByeDPIKit - ByeDPIC minimal wrapper. It allows to start/stop native byedpi SOCKS proxy with DPI-evasion parameters. This module doesn't containt any Apple platform-specific checks for byedpi command-line arguments
  3. SwByeDPI - ByeDPIC extended wrapper, which is based on ByeDPIKit. It contains byedpi launch config abstractions, proxified (SOCKS) URLSession's init tools, bundled strategies' and domains' sets for testing and further use. Also it contains strategy testing and analyzing features

SwByeDPI SPM setup

//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: "SwByeDPI", package: "ByeDPIKit")
//Target dependencies parameter (ByeDPIC)
.product(name: "SwByeDPI", package: "ByeDPIC")

CocoaPods

All three pods, similar to SPM, are available for import via CocoaPods. The pod names are identical to those of SPM.

Note: According to CocoaPods information, module updates will be published on CocoaPods until December 2026.

Working with ByeDPI

Launching byedpi in ByeDPIKit and SwByeDPI is identical:

  1. Define the command to launch the byedpi SOCKS proxy according to the documentation
  2. Launch by passing the byedpi SOCKS proxy command-line arguments
#if canImport(SwByeDPI)
import SwByeDPI
#else
    #if canImport(ByeDPIKit)
import ByeDPIKit
    #endif
#endif

var args: [String] = []
//...Define the command-line arguments
ByeDPI.startDPI(args: args) { BDError in
    //byedpi launch error processing
}
  1. After some time, ByeDPI stop
// General stop procedure
_ = ByeDPI.stopDPI()
// If, upon restarting, the error bind error: Address already in use occurs, it is better to stop using via force stop
_ = ByeDPI.forceStopDPI()

Additional

SwByeDPI. Strategy testing

To ensure ByeDPI operates more efficiently under various conditions (different internet providers, geolocation, devices, operating systems, etc.), a strategy testing mechanism was implemented on a domain lists

The following parameters can be set for testing:

  • Delay between domain requests (seconds). Increasing this value improves test reliability. Optimal value during testing - 1 second
  • Domain requests count. Increasing this value improves accuracy but reduces overall testing speed. Optimal value during testing - 2 requests
  • Worker threads count. Increasing this value speeds up testing but reduces test reliability. Optimal value during testing - Number of CPU cores * 2
  • Response wait timeout (seconds). Increasing this value slows down overall testing speed but improves test reliability. Optimal value during testing - 5 seconds
  • Domain lists for testing. To select a more comprehensive strategy and analyze the results later, it is recommended to select more domains. If the goal is to open access to only certain resources, then it is worth selecting only those (if there are none, then first add a new list). A large pool of domains for testing naturally slows overall test speed.
  • Strategy lists for testing. By default, only the strategy list built into SwByeDPI is available.

A successful request to a domain via ByeDPI is defined as a response with a status code of 200..299 or any other, but with a Content-Length header (the fact that information was sent and received in the response body).

So, after testing, you can select a universal strategy (Important clarification - not the best one for the specific domains being tested) based on the criterion More successful requests to domains count - better strategy

For more fine-tuning, you should analyze the strategy testing results.

SwByeDPI. Testing results analyzing and optimal strategy define

Strategies tested on specific domains and proven effective (highest number of successful requests passed DPI) can already be used in ByeDPI. However, when fine-tuning ByeDPI's operation is required (configuring bypass for specific domains, using the most effective strategies for specific domains, or defining a universal strategy), simply selecting a strategy from test results is not enough.

To achieve this, a results analysis module was implemented in SwByeDPI, the output of which will be a composite strategy consisting of:

  • Bypass for DNS (port 53) - more used when ByeDPI is running in a tunnel
  • A Domain lists on which ByeDPI won't work - a blacklist block or ByeDPI-bypass. According to the byedpi documentation, in the "More details --auto --hosts" section, this block will always appear at the beginning of the composite strategy.
  • A list or lists of domains for which the most effective strategies have been selected from those tested - a ByeDPI whitelist block. This block can be located at the beginning if there is no blacklist of domains, or in the middle/end of the composite strategy.
  • A strategy that may not be the best for a specific domain, but has demonstrated the best results (the highest number of successful requests that passed DPI), is a universal strategy and can be used for "other" domains when ByeDPI is enabled. This block will always be located at the end of the composite strategy.

The basic operation on strategy testing results, which underlies all analysis, is calculating strategy coverage for a domain list (successful queries to domains in the list). All analysis logic is located in SBDTestResultAnalyticsUtil.swift

Note 1: Using each block is optional, meaning you can specify the use of all blocks in the composite, use only whitelists, etc.

Note 2: Using the default domain lists for testing in ByeDPI --hosts is not optimal. Since ByeDPI only needs to specify second-level domains (Example: if you specify googlevideo.com in --hosts, ByeDPI will also process all subdomains), you can generate a new list (this is what the Strategy Analyzer does) consisting only of unique second-level domains. To do this, you can use the retrieveSLDList() function.

var domainList: SBDDomainList
//...
let sldList = domainList.retrieveSLDList()

Note 3: To ensure consistency between blocks (Black/White List and Universal Strategy) and the strategies within them (Strategies for Different Domain Lists in the Whitelist), a -An-like mapping is used.

SwByeDPI. Code generation

SwByeDPI module includes lists of sites for testing and ByeDPI bypass, as well as strategies in the form of text files. These files are then used to generate *.swift files, which are then compiled into the resulting module (Built-in domains and strategies). You can edit or delete existing lists, or add new ones.

Generation is performed manually using the code generator script, which defines all files with the *.strategies and *.domains extensions in Assets. Note: The list file format is the same for both strategies and domains—one list per line.

Example app

The Example app is an iOS app (iOS 14+, SwiftUI). The project can be built for other platforms (Experimental support for tvOS 17.0+ and macOS 11.0+).

The app runs ByeDPI locally and can redirect traffic from other apps and devices on the local network through it.

Capabilities

The application allows you to:

  • Set byedpi launch settings (bind IP address, SOCKS proxy port, command-line arguments)
  • Automatically correct byedpi strategy parameters if they are not supported by the device and/or OS
  • Test strategies and save the last test run
  • Analyze and create the most optimal strategies based on test results
  • When creating optimal strategies, you can specify blacklists (byedpi bypass) and whitelists (specific strategies only work for specific domains). More details --auto --hosts
  • Add/modify/remove domains for testing strategies, filtering domains for byedpi bypass
  • Add/modify/remove strategies for testing
  • Set DNS (DoH/DoT) - available only when building a full VPN client

Note: Compared to Android, the VPN Network Extension in iOS cannot manage tunneling for specific apps. This is done using byedpi's own functionality, specifying specific second-level domains (blacklists/whitelists).

For advanced use, you can refer to the comprehensive instructions from the ByeByeDPI-Manual community.

Build

There are two possible app build options:

  • VPN client (ByeByeDPI) ByeDPI -> Tun2SocksKit -> NEVPN + DNS - requires a paid developer license: an individual account is sufficient for development, debugging, and uploading to TestFlight; a legal entity or sole proprietorship account is required for release in the App Store according to Apple Developer Guidelines 5.4. Note: The app is not a general VPN client, as ByeDPI runs locally on the device. The VPN trick is needed to enable ByeDPI functionality in the background (when the app is minimized or not running) and to process ByeDPI internet traffic from all apps on the phone and devices on the local network (you must grant the app permission to access the local network). Support for DoH/DoT in the app allows you to bypass geoblocks imposed by the services themselves.
  • ByeDPI SOCKS proxy server (ByeDPI) - for running on your own devices, does not require a paid developer license. This build is ideal for testing app functionality on endpoints: you can test strategies and create an optimal composite using an analyzer. The caveat here is that ByeDPI will only work while the app is open (foreground).
  1. Clone the current repository with submodules:
git clone --recurse-submodules
  1. Add certificates and private keys for signing the application to your keyring, import the development profiles

In Apple Developer, for your app (VPN client), you need to do the following (assuming you already have at least a development certificate and are managing signatures manually):

  • Register an App Group ID that will link the host app and Network Extension
  • Register an App ID for the host app. In Entitlements, specify App Groups (indicating the one you created earlier), Network Extensions, and Personal VPN
  • Register an App ID for the Network Extension. In Entitlements, specify the same items as for the host app
  • Create development profiles for the host app and Network Extension
  • Import the profiles into Xcode
  1. Run the application build (ByeByeDPI or ByeDPI) via the XCode GUI or Terminal

Problems and soltions

  • The VPN tunnel has been started, but websites won't be opened, and the logs (Console.app) show a cyclical 'udp session start - connect - destruct' sequence. Related to the ByeDPI address 127.0.0.1 - on iOS prior to 18.0, you must specify any other local address (192.168.20.3, for example, or any other, regardless of the network interface (mobile network or Wi-Fi) and whether this address is actually in the local network. Note: For DEBUG and when Wi-Fi is connected, Network Extension automatically determines the local IP address if 127.0.0.1 or ::1 is specified as input
  • Establishing a VPN tunnel with ByeDPI listening on 0.0.0.0 is not possible. To access ByeDPI from other devices on the local network, you must specify the IP address of the device on the network
  • Before iOS 14, the application will be extremely unstable due to the hard limits for Network Extension - 15 MB. After exceeding this limit, the OS will kill the VPN tunnel without warning and crash. The solution is to use the application on smartphones with iOS 15+, where the limit is already 50 MB. Note: during tests, it was found that when With the correct Tun2SOCKS config, RAM consumption doesn't even exceed 15 MB (on average, it stayed at 4.3-4.8 MB), so, theoretically, this NetworkExtension could be ported to UIKit to provide support even for iOS 10.0+ with its 15 MB limit per Network Extension
  • Constant increase in RAM usage during tunnel operation (web surfing, etc.) from the very start up until SIGKILL from the OS. - Log redirection from stdout/stderr is enabled (hev-socks-tunnel, byedpi), which needs to be disabled/commented out in the code, including the commands for setting the logging level for byedpi/Tun2SOCKS

Screenshots