97 lines
3.5 KiB
Swift
97 lines
3.5 KiB
Swift
//
|
|
// 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")
|
|
}
|
|
}
|
|
}
|