How OpenFlux Integrates with iOS: Network Extension Architecture and Swift Implementation
OpenFlux integrates with iOS through a three-component architecture consisting of a PacketTunnelProvider system extension, a VPNController management layer, and a SwiftUI interface, enabling both per-app SOCKS5 proxy and system-wide VPN functionality via a Go-based tun2socks stack.
The p1neappleXpress/OpenFlux repository implements a native iOS client that bridges Apple's Network Extension framework with a Go networking core. This integration allows users to route device traffic through remote exit nodes using either a local SOCKS5 proxy for specific applications or a full-device VPN tunnel that captures all network traffic.
Three-Layer Architecture
OpenFlux integrates with iOS through tightly-coupled Swift components that handle system-level packet tunneling, VPN profile management, and user interaction.
PacketTunnelProvider: The System Extension Core
The PacketTunnelProvider class in ios-app/OpenFluxTunnel/PacketTunnelProvider.swift implements the NEPacketTunnelProvider API to create a virtual TAP interface. This system extension initializes the packet tunnel, configures network settings, and bridges raw IP packets to the Go tun2socks stack through C function calls.
Key responsibilities include:
- Building
NEPacketTunnelNetworkSettingswith virtual address10.10.10.2and DNS198.18.0.1 - Defining
bypassRoutesto exclude Yandex backend ranges and public DoT DNS servers from the tunnel - Exporting C functions
OpenFluxStartPacketTunnel,OpenFluxTunWritePacket, andOpenFluxTunReadPacketto interface with the Go binary
VPNController: Profile and Lifecycle Management
Located in ios-app/OpenFlux/VPNController.swift, the VPNController wraps NETunnelProviderManager to manage the system-wide VPN profile. It handles the creation, configuration, and persistence of the packet tunnel, passing transport credentials—such as Yandex Docs URLs or MAX tokens—via the providerConfiguration dictionary.
When users enable system-wide routing, this controller calls startVPNTunnel() to install the VPN profile that captures all device traffic at the operating system level.
SwiftUI Interface Layer
The user-facing components in ios-app/OpenFlux/ContentView.swift provide controls for transport selection, credential entry, and tunnel management. The interface supports two operational modes:
- SOCKS5 Proxy Mode: Routes specific application traffic through a local port (default
10808) - VPN Mode: Routes all device traffic through the virtual interface managed by
PacketTunnelProvider
Packet Flow and Data Routing
OpenFlux integrates with iOS network stacks through a bidirectional packet pumping mechanism that operates asynchronously.
Tunnel Initialization Sequence
When a user starts the tunnel via TunnelController.start() or enables the VPN through VPNController.start(), the system triggers PacketTunnelProvider.startTunnel. This method:
- Instantiates
NEPacketTunnelNetworkSettingswith the virtual IPv4 configuration - Sets default routes while excluding Yandex infrastructure to prevent routing loops
- Invokes
OpenFluxStartPacketTunnelto initialize the Go-side networking stack
Bidirectional Packet Processing
Two concurrent loops handle packet movement between the iOS system and the Go stack:
Read Loop (Device → Go Stack):
packetFlow.readPackets { [weak self] packets, _ in
for p in packets {
p.withUnsafeBytes { raw in
if let base = raw.bindMemory(to: CChar.self).baseAddress {
OpenFluxTunWritePacket(UnsafeMutablePointer(mutating: base),
Int32(p.count))
}
}
}
self?.startReadLoop()
}
Write Loop (Go Stack → Device):
while true {
let n = OpenFluxTunReadPacket(buf, maxLen)
if n <= 0 { break }
let data = Data(bytes: buf, count: Int(n))
self.packetFlow.writePackets([data],
withProtocols: [NSNumber(value: AF_INET)])
}
Implementation Examples
Starting the SOCKS5 Proxy
To initialize the local proxy without system-wide VPN:
tunnel.start(
transport: transport,
url: docURL,
maxToken: maxToken,
maxUid: maxUid,
port: Int(socksPort) ?? 10808
)
Configuring System-Wide VPN
To route all device traffic through the exit node:
vpn.start(
transport: transport.rawValue,
url: docURL,
maxToken: maxToken,
maxUid: maxUid
)
Network Settings Configuration
The virtual interface setup excludes specific routes to prevent traffic loops:
let settings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "127.0.0.1")
let ipv4 = NEIPv4Settings(addresses: ["10.10.10.2"],
subnetMasks: ["255.255.255.0"])
ipv4.includedRoutes = [NEIPv4Route.default()]
ipv4.excludedRoutes = Self.bypassRoutes
settings.ipv4Settings = ipv4
settings.dnsSettings = NEDNSSettings(servers: ["198.18.0.1"])
Required Capabilities and Entitlements
OpenFlux integrates with iOS system APIs through specific entitlements defined in OpenFlux.entitlements and OpenFluxTunnel.entitlements:
- App Groups: Enables data sharing between the main app and the packet tunnel extension
- Network Extension: Grants permission to create VPN configurations and packet tunnel providers
- Background Modes: Supports continuous packet processing while the app operates in the background
Summary
- OpenFlux integrates with iOS through a
PacketTunnelProvidersystem extension that implementsNEPacketTunnelProviderto create virtual network interfaces. - The
VPNControllermanages theNETunnelProviderManagerlifecycle, handling system-wide VPN profiles and credential configuration. - Bidirectional packet pumping occurs through C bridge functions
OpenFluxTunWritePacketandOpenFluxTunReadPacket, connecting Swift code with the Go tun2socks implementation. - The architecture supports dual operation modes: a local SOCKS5 proxy for selective traffic routing and a full-device VPN capturing all network traffic with DNS-over-TCP resolution.
Frequently Asked Questions
How does OpenFlux handle packet routing at the system level?
OpenFlux creates a virtual TAP interface using NEPacketTunnelNetworkSettings with IP address 10.10.10.2. The PacketTunnelProvider class reads raw IP packets from packetFlow.readPackets and forwards them to the Go stack via OpenFluxTunWritePacket, while continuously polling OpenFluxTunReadPacket to write processed packets back to the system.
What transport protocols does the iOS client support?
According to the source code in VPNController.swift and ContentView.swift, the iOS client supports Yandex and MAX transports. Users provide either a Yandex Docs URL or MAX token/UID credentials, which the app passes through providerConfiguration to the packet tunnel extension.
Can OpenFlux run without enabling the system VPN?
Yes. The TunnelController (referenced in ios-app/OpenFlux/TunnelController.swift) allows users to start a local SOCKS5 proxy on a configurable port without installing the system VPN profile. This mode routes traffic only from applications explicitly configured to use the local proxy address, while the VPN mode routes all device traffic through PacketTunnelProvider.
How does the app prevent routing loops for its own backend traffic?
The PacketTunnelProvider defines bypassRoutes that exclude Yandex backend IP ranges and public DNS-over-TLS servers from the tunnel's included routes. This exclusion prevents the tunnel from attempting to route its own control traffic back through the encrypted tunnel, which would cause connectivity failures.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →