From 351695aa5205e2c517e2ff76fe47591e9fee821b Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Wed, 20 May 2026 23:24:49 +0800 Subject: [PATCH] =?UTF-8?q?Tun=20Network=E8=AE=BE=E7=BD=AE=E6=8A=BD?= =?UTF-8?q?=E8=B1=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Tun/Punchnet/Context/SDLContextActor.swift | 70 +------------- .../TunNetwork/SDLTunNetworkManager.swift | 96 +++++++++++++++++++ 2 files changed, 101 insertions(+), 65 deletions(-) create mode 100644 Tun/Punchnet/TunNetwork/SDLTunNetworkManager.swift diff --git a/Tun/Punchnet/Context/SDLContextActor.swift b/Tun/Punchnet/Context/SDLContextActor.swift index 86a762f..54a106a 100644 --- a/Tun/Punchnet/Context/SDLContextActor.swift +++ b/Tun/Punchnet/Context/SDLContextActor.swift @@ -68,6 +68,7 @@ actor SDLContextActor { private let udpHoleServiceProxy: SDLUDPHoleServiceProxy private let packetOutboundActor: PacketOutboundActor private let packetInboundActor: PacketInboundActor + private let tunNetworkManager: SDLTunNetworkManager private let publicDnsServers = ["223.5.5.5", "119.29.29.29"] @@ -105,6 +106,7 @@ actor SDLContextActor { let policyService = PolicyService(identityId: config.identityId) let superServiceProxy = SDLSuperServiceProxy() let udpHoleServiceProxy = SDLUDPHoleServiceProxy() + let tunNetworkManager = SDLTunNetworkManager(provider: provider) let packetOutboundActor = PacketOutboundActor( provider: provider, config: config, @@ -145,6 +147,7 @@ actor SDLContextActor { self.udpHoleServiceProxy = udpHoleServiceProxy self.packetOutboundActor = packetOutboundActor self.packetInboundActor = packetInboundActor + self.tunNetworkManager = tunNetworkManager } public func start() async { @@ -336,7 +339,7 @@ extension SDLContextActor { SDLLogger.log("[SDLContext] registerSuperAck, use algorithm \(algorithm), key len: \(key.count)") // 服务器分配的tun网卡信息 do { - try await self.setNetworkSettings(config: self.config, dnsServer: DNSHelper.dnsServer) + try await self.tunNetworkManager.apply(settings: .init(config: self.config), dnsServer: DNSHelper.dnsServer) SDLLogger.log("[SDLContext] setNetworkSettings successed") await self.packetOutboundActor.startPacketReader() // 开启权限的定时更新 @@ -590,71 +593,8 @@ extension SDLContextActor { } await self.packetOutboundActor.updateRuntime(config: self.config, dataCipher: self.dataCipher) await self.packetInboundActor.updateRuntime(config: self.config, dataCipher: self.dataCipher) - try await self.setNetworkSettings(config: self.config, dnsServer: DNSHelper.dnsServer) - } - - // MARK: 网络改变时需要重新配置网络信息 - private func setNetworkSettings(config: SDLConfiguration, dnsServer: String) async throws { - let networkAddress = config.networkAddress - // 配置路由规则 - var routes: [NEIPv4Route] = [ - NEIPv4Route(destinationAddress: networkAddress.netAddress, subnetMask: networkAddress.maskAddress), - NEIPv4Route(destinationAddress: dnsServer, subnetMask: "255.255.255.255"), - ] - - // 如果存在出口节点配置,则接管系统默认留有 - if config.exitNode != nil { - routes.append(.default()) - } - - // Add code here to start the process of connecting the tunnel. - let networkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "8.8.8.8") - networkSettings.mtu = 1250 - - // 设置网卡的DNS解析 - let networkDomain = networkAddress.networkDomain - let dnsSettings = NEDNSSettings(servers: [dnsServer]) - - dnsSettings.searchDomains = [networkDomain] - dnsSettings.matchDomains = [networkDomain, ""] - // 设置为 false 允许系统在补全 Search Domain 时也能匹配到此设置 - dnsSettings.matchDomainsNoSearch = false - - networkSettings.dnsSettings = dnsSettings - - let ipv4Settings = NEIPv4Settings(addresses: [networkAddress.ipAddress], subnetMasks: [networkAddress.maskAddress]) - // 设置路由表 - ipv4Settings.includedRoutes = routes - - // 配置要排除的路由 - ipv4Settings.excludedRoutes = self.getIpv4ExcludeRoutes() - - networkSettings.ipv4Settings = ipv4Settings - // 网卡配置设置必须成功 - try await self.provider.setTunnelNetworkSettings(networkSettings) - } - - private func getIpv4ExcludeRoutes() -> [NEIPv4Route] { - // 要排除的路由表 - let dnsServers = SDLUtil.getMacOSSystemDnsServers() - var ipv4DnsServers = dnsServers.filter {!$0.contains(":")} - - // 增加常见的dns服务 - let commonDnsServers = [ - "8.8.8.8", - "8.8.4.4", - "223.5.5.5", - "223.6.6.6", - "114.114.114.114" - ] - for ip in commonDnsServers { - if !ipv4DnsServers.contains(ip) { - ipv4DnsServers.append(ip) - } - } - - return ipv4DnsServers.map { NEIPv4Route(destinationAddress: $0, subnetMask: "255.255.255.255") } + try await self.tunNetworkManager.apply(settings: .init(config: self.config), dnsServer: DNSHelper.dnsServer) } } diff --git a/Tun/Punchnet/TunNetwork/SDLTunNetworkManager.swift b/Tun/Punchnet/TunNetwork/SDLTunNetworkManager.swift new file mode 100644 index 0000000..0c622fe --- /dev/null +++ b/Tun/Punchnet/TunNetwork/SDLTunNetworkManager.swift @@ -0,0 +1,96 @@ +// +// SDLTunNetworkManager.swift +// Tun +// +// Created by Codex on 2026/5/20. +// + +import Foundation +import NetworkExtension + +final class SDLTunNetworkManager: @unchecked Sendable { + struct Settings: Sendable { + let ipAddress: String + let maskAddress: String + let netAddress: String + let networkDomain: String + let shouldRouteDefault: Bool + + init(config: SDLConfiguration) { + let networkAddress = config.networkAddress + self.ipAddress = networkAddress.ipAddress + self.maskAddress = networkAddress.maskAddress + self.netAddress = networkAddress.netAddress + self.networkDomain = networkAddress.networkDomain + self.shouldRouteDefault = config.exitNode != nil + } + } + + private let provider: NEPacketTunnelProvider + + init(provider: NEPacketTunnelProvider) { + self.provider = provider + } + + func apply(settings: Settings, dnsServer: String) async throws { + let networkSettings = self.makeNetworkSettings(settings: settings, dnsServer: dnsServer) + try await self.provider.setTunnelNetworkSettings(networkSettings) + } + + private func makeNetworkSettings(settings: Settings, dnsServer: String) -> NEPacketTunnelNetworkSettings { + let networkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "8.8.8.8") + networkSettings.mtu = 1250 + networkSettings.dnsSettings = self.makeDNSSettings(settings: settings, dnsServer: dnsServer) + networkSettings.ipv4Settings = self.makeIPv4Settings(settings: settings, dnsServer: dnsServer) + return networkSettings + } + + private func makeDNSSettings(settings: Settings, dnsServer: String) -> NEDNSSettings { + let dnsSettings = NEDNSSettings(servers: [dnsServer]) + dnsSettings.searchDomains = [settings.networkDomain] + dnsSettings.matchDomains = [settings.networkDomain, ""] + // 设置为 false 允许系统在补全 Search Domain 时也能匹配到此设置 + dnsSettings.matchDomainsNoSearch = false + return dnsSettings + } + + private func makeIPv4Settings(settings: Settings, dnsServer: String) -> NEIPv4Settings { + let ipv4Settings = NEIPv4Settings(addresses: [settings.ipAddress], subnetMasks: [settings.maskAddress]) + ipv4Settings.includedRoutes = self.makeIPv4IncludedRoutes(settings: settings, dnsServer: dnsServer) + ipv4Settings.excludedRoutes = self.makeIPv4ExcludedRoutes() + return ipv4Settings + } + + private func makeIPv4IncludedRoutes(settings: Settings, dnsServer: String) -> [NEIPv4Route] { + var routes: [NEIPv4Route] = [ + NEIPv4Route(destinationAddress: settings.netAddress, subnetMask: settings.maskAddress), + NEIPv4Route(destinationAddress: dnsServer, subnetMask: "255.255.255.255"), + ] + + if settings.shouldRouteDefault { + routes.append(.default()) + } + + return routes + } + + private func makeIPv4ExcludedRoutes() -> [NEIPv4Route] { + let dnsServers = SDLUtil.getMacOSSystemDnsServers() + var ipv4DnsServers = dnsServers.filter { !$0.contains(":") } + let commonDnsServers = [ + "8.8.8.8", + "8.8.4.4", + "223.5.5.5", + "223.6.6.6", + "114.114.114.114" + ] + + for ip in commonDnsServers where !ipv4DnsServers.contains(ip) { + ipv4DnsServers.append(ip) + } + + return ipv4DnsServers.map { + NEIPv4Route(destinationAddress: $0, subnetMask: "255.255.255.255") + } + } +}