Add proxy subscription runtime support

Add daemon RPCs, Apple and GTK import flows, packet proxy runtime support, diagnostics, and BEPs for proxy subscription handling.

Redact subscription URL secrets from fetch errors before they reach logs or UI surfaces.
This commit is contained in:
JettChenT 2026-06-01 15:23:17 +08:00
parent 97c569fb35
commit d1638726ca
46 changed files with 15079 additions and 456 deletions

View file

@ -9,3 +9,5 @@ CODE_SIGN_ENTITLEMENTS = NetworkExtension/NetworkExtension-iOS.entitlements
CODE_SIGN_ENTITLEMENTS[sdk=macosx*] = NetworkExtension/NetworkExtension-macOS.entitlements
SWIFT_INCLUDE_PATHS = $(inherited) $(PROJECT_DIR)/NetworkExtension
OTHER_LDFLAGS = $(inherited) -framework SystemConfiguration

View file

@ -28,13 +28,13 @@ final class PacketTunnelProvider: NEPacketTunnelProvider, @unchecked Sendable {
get throws { try _client.get() }
}
private let _client: Result<TunnelClient, Swift.Error> = Result {
try TunnelClient.unix(socketURL: Constants.socketURL)
try TunnelClient.unix(socketURL: Constants.packetTunnelSocketURL)
}
override init() {
do {
libburrow.spawnInProcess(
socketPath: try Constants.socketURL.path(percentEncoded: false),
socketPath: try Constants.packetTunnelSocketURL.path(percentEncoded: false),
databasePath: try Constants.databaseURL.path(percentEncoded: false)
)
} catch {
@ -54,6 +54,11 @@ final class PacketTunnelProvider: NEPacketTunnelProvider, @unchecked Sendable {
guard let settings = configuration?.settings else {
throw Error.missingTunnelConfiguration
}
if let configuration {
logger.log(
"Applying tunnel configuration addresses=\(configuration.addresses.joined(separator: ","), privacy: .public) routes=\(configuration.routes.joined(separator: ","), privacy: .public) excludedRoutes=\(configuration.excludedRoutes.joined(separator: ","), privacy: .public) dns=\(configuration.dnsServers.joined(separator: ","), privacy: .public) includeDefaultRoute=\(configuration.includeDefaultRoute, privacy: .public)"
)
}
try await setTunnelNetworkSettings(settings)
try startPacketBridge()
logger.log("Started tunnel with network settings: \(settings)")
@ -88,15 +93,22 @@ extension PacketTunnelProvider {
private func startPacketBridge() throws {
stopPacketBridge()
let packetClient = TunnelPacketClient.unix(socketURL: try Constants.socketURL)
let packetClient = TunnelPacketClient.unix(socketURL: try Constants.packetTunnelSocketURL)
let call = packetClient.makeTunnelPacketsCall()
self.packetCall = call
inboundPacketTask = Task { [weak self] in
guard let self else { return }
var packetCount = 0
var byteCount = 0
do {
for try await packet in call.responseStream {
let payload = packet.payload
packetCount += 1
byteCount += payload.count
if packetCount == 1 || packetCount % 1024 == 0 {
self.logger.log("Tunnel packet receive progress packets=\(packetCount, privacy: .public) bytes=\(byteCount, privacy: .public) lastBytes=\(payload.count, privacy: .public)")
}
self.packetFlow.writePackets(
[payload],
withProtocols: [Self.protocolNumber(for: payload)]
@ -111,10 +123,17 @@ extension PacketTunnelProvider {
outboundPacketTask = Task { [weak self] in
guard let self else { return }
defer { call.requestStream.finish() }
var packetCount = 0
var byteCount = 0
do {
while !Task.isCancelled {
let packets = await self.readPacketsBatch()
for (payload, _) in packets {
packetCount += 1
byteCount += payload.count
if packetCount == 1 || packetCount % 1024 == 0 {
self.logger.log("Tunnel packet send progress packets=\(packetCount, privacy: .public) bytes=\(byteCount, privacy: .public) lastBytes=\(payload.count, privacy: .public)")
}
var packet = Burrow_TunnelPacket()
packet.payload = payload
try await call.requestStream.send(packet)
@ -128,6 +147,7 @@ extension PacketTunnelProvider {
}
private func stopPacketBridge() {
logger.log("Stopping tunnel packet bridge")
inboundPacketTask?.cancel()
inboundPacketTask = nil
outboundPacketTask?.cancel()
@ -165,6 +185,9 @@ extension Burrow_TunnelConfigurationResponse {
let parsedRoutes = routes.compactMap(ParsedTunnelRoute.init(rawValue:))
var ipv4Routes = parsedRoutes.compactMap(\.ipv4Route)
var ipv6Routes = parsedRoutes.compactMap(\.ipv6Route)
let parsedExcludedRoutes = excludedRoutes.compactMap(ParsedTunnelRoute.init(rawValue:))
let excludedIPv4Routes = parsedExcludedRoutes.compactMap(\.ipv4Route)
let excludedIPv6Routes = parsedExcludedRoutes.compactMap(\.ipv6Route)
if includeDefaultRoute {
ipv4Routes.append(.default())
ipv6Routes.append(.default())
@ -180,6 +203,9 @@ extension Burrow_TunnelConfigurationResponse {
if !ipv4Routes.isEmpty {
ipv4Settings.includedRoutes = ipv4Routes
}
if !excludedIPv4Routes.isEmpty {
ipv4Settings.excludedRoutes = excludedIPv4Routes
}
settings.ipv4Settings = ipv4Settings
}
if !ipv6Addresses.isEmpty {
@ -190,6 +216,9 @@ extension Burrow_TunnelConfigurationResponse {
if !ipv6Routes.isEmpty {
ipv6Settings.includedRoutes = ipv6Routes
}
if !excludedIPv6Routes.isEmpty {
ipv6Settings.excludedRoutes = excludedIPv6Routes
}
settings.ipv6Settings = ipv6Settings
}
if !dnsServers.isEmpty {

View file

@ -3,7 +3,7 @@
# This is a build script. It is run by Xcode as a build step.
# The type of build is described in various environment variables set by Xcode.
export PATH="${PATH}:${HOME}/.cargo/bin:/opt/homebrew/bin:/usr/local/bin:/etc/profiles/per-user/${USER}/bin"
export PATH="${PATH}:${HOME}/.cargo/bin:${HOME}/.nix-profile/bin:/opt/homebrew/bin:/usr/local/bin:/etc/profiles/per-user/${USER}/bin:/run/current-system/sw/bin:/nix/var/nix/profiles/default/bin"
if ! [[ -x "$(command -v cargo)" ]]; then
echo 'error: Unable to find cargo'
@ -63,13 +63,13 @@ else
fi
if [[ -x "$(command -v rustup)" ]]; then
CARGO_PATH="$(dirname $(rustup which cargo)):/usr/bin"
CARGO_PATH="$(dirname "$(rustup which cargo)"):/usr/bin"
else
CARGO_PATH="$(dirname $(readlink -f $(which cargo))):/usr/bin"
CARGO_PATH="$(dirname "$(readlink -f "$(command -v cargo)")"):/usr/bin"
fi
PROTOC=$(readlink -f $(which protoc))
CARGO_PATH="$(dirname $PROTOC):$CARGO_PATH"
PROTOC="$(readlink -f "$(command -v protoc)")"
CARGO_PATH="$(dirname "$PROTOC"):$CARGO_PATH"
# Run cargo without the various environment variables set by Xcode.
# Those variables can confuse cargo and the build scripts it runs.