revert(macos): killswitch 回退 L0(低优先级暂缓)

用户判定 killswitch 优先级低、暂不做:
- includeAllNetworks 实测堵死整机网络;退化方案 enforceRoutes+on-demand
  几乎等于没做(核心 fail-closed 没拿到),on-demand 还对免费版配额造成
  重连 churn —— 性价比低
- VpnChannel.swift 恢复到 L0 stub(setKillSwitch→result(nil));
  PacketTunnelProvider.swift 已是原样
- docs §6.5 改为「尝试与暂缓」记录,状态表 macOS 回 L0
- local_test.sh 的 ks-* 漏测子命令保留(将来重拾 killswitch 时可用)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-07-01 06:38:47 +08:00
parent a32d87c9c0
commit 6bcdbbe752
2 changed files with 8 additions and 81 deletions
+2 -76
View File
@@ -33,10 +33,6 @@ final class VpnChannel: NSObject {
private let statsClient = StatsClient()
private var manager: NETunnelProviderManager?
private var sysextDelegate: SysExtActivationDelegate?
// KillSwitch(), true Dart AppSettings.killSwitch
// NE fail-closed:includeAllNetworks + enforceRoutes(L2 OS )
// + NEOnDemandRule (L3 /线) docs/killswitch-design.html §6.5
private var killSwitchEnabled = true
static func register(with registrar: FlutterPluginRegistrar) {
let instance = VpnChannel()
@@ -91,26 +87,8 @@ final class VpnChannel: NSObject {
case "getActiveOutbound":
result("auto")
case "setKillSwitch":
let on = (call.arguments as? Bool) ?? true
killSwitchEnabled = on
vpnLog("setKillSwitch=\(on)")
// manager NE (includeAllNetworks/enforceRoutes/on-demand);
// manager , loadOrCreateManager
if let mgr = manager {
Task {
do {
try await self.applyKillSwitchConfig(to: mgr)
vpnLog("setKillSwitch: NE 配置已更新并保存 ✓")
result(nil)
} catch {
let ns = error as NSError
vpnLog("setKillSwitch: 保存 NE 配置失败 ✗ code=\(ns.code) desc=\(ns.localizedDescription)")
result(FlutterError(code: "killswitch_failed", message: error.localizedDescription, details: nil))
}
}
} else {
result(nil)
}
// includeAllNetworks / on-demand kill switch()
result(nil)
default:
result(FlutterMethodNotImplemented)
}
@@ -142,19 +120,6 @@ final class VpnChannel: NSObject {
}
private func stop(_ result: @escaping FlutterResult) async {
// on-demand stopVPNTunnel OS on-demand
// start() loadOrCreateManager killSwitchEnabled on-demand
if let mgr = manager, mgr.isOnDemandEnabled {
mgr.isOnDemandEnabled = false
do {
try await mgr.saveToPreferences()
try await mgr.loadFromPreferences()
vpnLog("stop: 已临时关闭 on-demand(避免手动断开被自动拉回)")
} catch {
let ns = error as NSError
vpnLog("stop: 关闭 on-demand 失败(仍继续断开) code=\(ns.code) desc=\(ns.localizedDescription)")
}
}
manager?.connection.stopVPNTunnel()
result(nil)
}
@@ -170,7 +135,6 @@ final class VpnChannel: NSObject {
mgr.protocolConfiguration = proto
mgr.localizedDescription = "Pangolin"
mgr.isEnabled = true
configureKillSwitch(on: mgr) // killSwitchEnabled NE fail-closed
vpnLog(" saveToPreferences(providerBundleId=\(Self.tunnelBundleId)) …")
try await mgr.saveToPreferences()
try await mgr.loadFromPreferences() // , connection
@@ -178,44 +142,6 @@ final class VpnChannel: NSObject {
return mgr
}
// KillSwitch()NE
// killSwitchEnabled manager NE (,):
// enforceRoutes=true: includedRoutes(0.0.0.0/0 ),
//
// NEOnDemandRule :OS 线/,
// excludeLocalNetworks=true: LAN(/AirPlay ),
// includeAllNetworks:( sing-box
// app ) + on-demand
// + ()/
// ,, docs/killswitch-design.html §6.5
// enforceRoutes/excludeLocalNetworks macOS 11+ API,Runner 10.15 #available
private func configureKillSwitch(on mgr: NETunnelProviderManager) {
if let proto = mgr.protocolConfiguration as? NETunnelProviderProtocol {
proto.includeAllNetworks = false
if #available(macOS 11.0, *) {
proto.enforceRoutes = killSwitchEnabled
proto.excludeLocalNetworks = true
}
}
if killSwitchEnabled {
let rule = NEOnDemandRuleConnect()
rule.interfaceTypeMatch = .any
mgr.onDemandRules = [rule]
mgr.isOnDemandEnabled = true
} else {
mgr.onDemandRules = []
mgr.isOnDemandEnabled = false
}
vpnLog(" killSwitch 配置: enforceRoutes=\(killSwitchEnabled) onDemand=\(killSwitchEnabled) includeAllNetworks=false")
}
/// killswitch( + + ) setKillSwitch manager
private func applyKillSwitchConfig(to mgr: NETunnelProviderManager) async throws {
configureKillSwitch(on: mgr)
try await mgr.saveToPreferences()
try await mgr.loadFromPreferences()
}
// / PacketTunnel System Extension
// ; didFinishWithResult
private func activateSystemExtensionIfNeeded() async throws {