diff --git a/Tun/PacketTunnelProvider.swift b/Tun/PacketTunnelProvider.swift index cea144c..8d6246f 100644 --- a/Tun/PacketTunnelProvider.swift +++ b/Tun/PacketTunnelProvider.swift @@ -19,9 +19,10 @@ class PacketTunnelProvider: NEPacketTunnelProvider { var context: SDLContext? private var rootTask: Task? - override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) { + override func startTunnel(options: [String: NSObject]?, completionHandler: @escaping (Error?) -> Void) { // host: "192.168.0.101", port: 1265 - guard let options else { + guard let options, let config = SDLConfiguration.parse(options: options) else { + NSLog("配置错误") return } @@ -30,50 +31,6 @@ class PacketTunnelProvider: NEPacketTunnelProvider { return } - // let token = options["token"] as! String - let installed_channel = options["installed_channel"] as! String - let superIp = options["super_ip"] as! String - let superPort = options["super_port"] as! Int - let stunServersStr = options["stun_servers"] as! String - let noticePort = options["notice_port"] as! Int - let token = options["token"] as! String - let accessToken = options["access_token"] as! String - let clientId = options["client_id"] as! String - let remoteDnsServer = options["remote_dns_server"] as! String - let hostname = options["hostname"] as! String - - let stunServers = stunServersStr.split(separator: ";").compactMap { server -> SDLConfiguration.StunServer? in - let parts = server.split(separator: ":", maxSplits: 2) - guard parts.count == 2 else { - return nil - } - - let ports = parts[1].split(separator: ",", maxSplits: 2) - guard ports.count == 2, let port1 = Int(String(ports[0])), let port2 = Int(String(ports[1])) else { - return nil - } - - return .init(host: String(parts[0]), ports: [port1, port2]) - } - - guard stunServers.count >= 2 else { - NSLog("stunServers配置错误") - return - } - - NSLog("[PacketTunnelProvider] client_id: \(clientId), token: \(token)") - - let config = SDLConfiguration(version: 1, - installedChannel: installed_channel, - superHost: superIp, - superPort: superPort, - stunServers: stunServers, - clientId: clientId, - noticePort: noticePort, - token: token, - accessToken: accessToken, - remoteDnsServer: remoteDnsServer, - hostname: hostname) // 加密算法 let rsaCipher = try! CCRSACipher(keySize: 1024) let aesChiper = CCAESChiper() diff --git a/Tun/Punchnet/SDLConfiguration.swift b/Tun/Punchnet/SDLConfiguration.swift index db9fc15..0a43429 100644 --- a/Tun/Punchnet/SDLConfiguration.swift +++ b/Tun/Punchnet/SDLConfiguration.swift @@ -9,7 +9,6 @@ import NIOCore // 配置项目 public class SDLConfiguration { - public struct StunServer { public let host: String public let ports: [Int] @@ -40,12 +39,8 @@ public class SDLConfiguration { let stunServers: [StunServer] let remoteDnsServer: String - let hostname: String - let noticePort: Int - let networkAddress: NetworkAddress = .init(networkId: 8, ip: 0, maskLen: 24, mac: "xyz".data(using: .utf8)!, networkDomain: "punchnet") - lazy var stunSocketAddress: SocketAddress = { let stunServer = stunServers[0] return try! SocketAddress.makeAddressResolvingHost(stunServer.host, port: stunServer.ports[0]) @@ -62,18 +57,30 @@ public class SDLConfiguration { }() let clientId: String - let token: String + let networkAddress: NetworkAddress + let hostname: String let accessToken: String - - public init(version: UInt8, installedChannel: String, superHost: String, superPort: Int, stunServers: [StunServer], clientId: String, noticePort: Int, token: String, accessToken: String, remoteDnsServer: String, hostname: String) { + + public init(version: UInt8, + installedChannel: String, + superHost: String, + superPort: Int, + stunServers: [StunServer], + clientId: String, + networkAddress: NetworkAddress, + hostname: String, + noticePort: Int, + accessToken: String, + remoteDnsServer: String) { + self.version = version self.installedChannel = installedChannel self.superHost = superHost self.superPort = superPort self.stunServers = stunServers self.clientId = clientId + self.networkAddress = networkAddress self.noticePort = noticePort - self.token = token self.accessToken = accessToken self.remoteDnsServer = remoteDnsServer self.hostname = hostname @@ -106,3 +113,79 @@ public class SDLConfiguration { } } + +// 解析配置文件 +extension SDLConfiguration { + + static func parse(options: [String: NSObject]) -> SDLConfiguration? { + guard let installed_channel = options["installed_channel"] as? String, + let superIp = options["super_ip"] as? String, + let superPort = options["super_port"] as? Int, + let stunServersStr = options["stun_servers"] as? String, + let noticePort = options["notice_port"] as? Int, + let token = options["token"] as? String, + let accessToken = options["access_token"] as? String, + let clientId = options["client_id"] as? String, + let remoteDnsServer = options["remote_dns_server"] as? String, + let hostname = options["hostname"] as? String, + let networkAddressDict = options["networkAddress"] as? [String: NSObject] else { + return nil + } + + guard let stunServers = parseStunServers(stunServersStr: stunServersStr), stunServers.count >= 2 else { + NSLog("stunServers配置错误") + return nil + } + + guard let networkAddress = parseNetworkAddress(networkAddressDict) else { + return nil + } + + NSLog("[PacketTunnelProvider] client_id: \(clientId), token: \(token)") + + return SDLConfiguration(version: 1, + installedChannel: installed_channel, + superHost: superIp, + superPort: superPort, + stunServers: stunServers, + clientId: clientId, + networkAddress: networkAddress, + hostname: hostname, + noticePort: noticePort, + accessToken: accessToken, + remoteDnsServer: remoteDnsServer) + } + + + private static func parseStunServers(stunServersStr: String) -> [SDLConfiguration.StunServer]? { + let stunServers = stunServersStr.split(separator: ";").compactMap { server -> SDLConfiguration.StunServer? in + let parts = server.split(separator: ":", maxSplits: 2) + guard parts.count == 2 else { + return nil + } + + let ports = parts[1].split(separator: ",", maxSplits: 2) + guard ports.count == 2, let port1 = Int(String(ports[0])), let port2 = Int(String(ports[1])) else { + return nil + } + + return .init(host: String(parts[0]), ports: [port1, port2]) + } + + return stunServers.count >= 2 ? stunServers : nil + } + + private static func parseNetworkAddress(_ config: [String: NSObject]) -> SDLConfiguration.NetworkAddress? { + guard let networkId = config["network_id"] as? UInt32, + let ipStr = config["ip"] as? String, + let ip = SDLUtil.ipv4StrToInt32(ipStr), + let maskLen = config["mask_len"] as? UInt8, + let mac = config["mac"] as? Data, + let networkDomain = config["network_domain"] as? String else { + return nil + } + + return .init(networkId: networkId, ip: ip, maskLen: maskLen, mac: mac, networkDomain: networkDomain) + } + +} diff --git a/Tun/Punchnet/SDLUtil.swift b/Tun/Punchnet/SDLUtil.swift index 69f46b9..5836b0a 100644 --- a/Tun/Punchnet/SDLUtil.swift +++ b/Tun/Punchnet/SDLUtil.swift @@ -30,6 +30,21 @@ struct SDLUtil { return "\(ip0).\(ip1).\(ip2).\(ip3)" } + public static func ipv4StrToInt32(_ ip: String) -> UInt32? { + let parts = ip.split(separator: ".") + guard parts.count == 4 else { + return nil + } + + var result: UInt32 = 0 + for part in parts { + guard let byte = UInt8(part) else { return nil } + result = (result << 8) | UInt32(byte) + } + + return result + } + // 判断ip地址是否在同一个网络 public static func inSameNetwork(ip: UInt32, compareIp: UInt32, maskLen: UInt8) -> Bool { if ip == compareIp {