// // VPNManager.swift // sdlan // // Created by 安礼成 on 2024/1/17. // import Foundation import NetworkExtension import SwiftUI // vpn管理类 class VPNManager { static let shared = VPNManager() private var observation: NSKeyValueObservation? var vpnStatus: VPNStatus = .disconnected enum VPNStatus { case connected case disconnected } private init() { } // 开启vpn func enableVpn(options: [String : NSObject]) async throws { NSLog("enable vpn with options: \(options)") let manager = try await loadAndCreateProviderManager() try await manager.loadFromPreferences() self.addVPNStatusObserver(manager) try manager.connection.startVPNTunnel(options: options) } // 关闭vpn func disableVpn() async throws { let managers = try await NETunnelProviderManager.loadAllFromPreferences() managers.first?.connection.stopVPNTunnel() } // MARK: - Private Methods // 监控系统VPN的状态的变化 private func addVPNStatusObserver(_ manager: NETunnelProviderManager) { self.observation = manager.connection.observe(\.status, options: [.initial, .new]) {[weak self] connection, change in guard let status = change.newValue else { return } switch status { case .invalid, .disconnected, .disconnecting: self?.vpnStatus = .disconnected case .connecting, .connected, .reasserting: self?.vpnStatus = .connected @unknown default: self?.vpnStatus = .disconnected } } } // MARK: - Private Methods // 加载或者创建相关的配置 private func loadAndCreateProviderManager() async throws -> NETunnelProviderManager { let managers = try await NETunnelProviderManager.loadAllFromPreferences() let manager = managers.first ?? NETunnelProviderManager() manager.localizedDescription = "punchnetmac" manager.isEnabled = true // 设置相关参数,在PacketTunnel中可以用 let protocolConfiguration = NETunnelProviderProtocol() protocolConfiguration.serverAddress = "punchnetmac" protocolConfiguration.providerConfiguration = [String:AnyObject]() protocolConfiguration.providerBundleIdentifier = "com.jihe.punchnetmac.tun" manager.protocolConfiguration = protocolConfiguration manager.isOnDemandEnabled = false manager.isEnabled = true try await manager.saveToPreferences() return manager } deinit { NotificationCenter.default.removeObserver(self) } }