iOS_YIJIANLIAN/OneTouchPT/PacketTunnelProvider.swift

213 lines
8.1 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// PacketTunnelProvider.swift
// OneTouchPT
//
// Created by SU on 2025/6/16.
//
import Foundation
import NetworkExtension
import Tun2SocksKit
import OTClient
class PacketTunnelProvider: NEPacketTunnelProvider {
private let cli_shared = YjlNeiHeClient.shared
private let config = YjlNeiHeConfig()
private var isAlive = false
override func startTunnel(options: [String : NSObject]?) async throws {
self.ONETopenLog()
await cli_shared.SetLayout()
self.cli_shared.SheZhiRizhi({ message in
NSLog("SheZhiRizhi log: \(message!)clashLog")
})
await config.tiJiaoNeiHe(cli: cli_shared)
let cjson = await cli_shared.HuoQuPeiZhiPro()
let cs = try JSONSerialization.jsonObject(with: cjson.data(using: .utf8)!, options: []) as! [String: Any]
let mp = cs["mixed-port"] as? Int ?? 0
if (mp != 0) {
NSLog("[SheZhiRizhi]mp: \(mp)")
}
let port = mp != 0 ? mp : cs["port"] as? Int ?? 0
let sp = mp != 0 ? mp : cs["socks-port"] as? Int ?? 0
NSLog("[SheZhiRizhi]startTunnel port: \(port), socksPort: \(sp)")
try await self.setTunnelNetworkSettings(initHttpSettings(port))
if (sp != 0) {
Socks5Tunnel.run(withConfig: .string(content: createTunnelConfig(socksPort: sp))) { code in
NSLog("[SheZhiRizhi]Socks5Tunnel ret: \(code)")
}
}
isAlive = true
self.addObserver(self, forKeyPath:"defaultPath", context: nil)
}
//
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "defaultPath" {
// VPN
let newPath = self.defaultPath
NSLog("[SheZhiRizhi]address: \(String(describing: newPath))")
print("默认网络路径已变动: \(String(describing: newPath))")
}
}
func ONETopenLog(){
let fileONETManager = FileManager.default
let containerURL = fileONETManager.containerURL(forSecurityApplicationGroupIdentifier: "group.com.jsq.yijianlian")
let ONETlogFilePath = containerURL?.appendingPathComponent("tunnel.log").path ?? ""
fileONETManager.createFile(atPath: ONETlogFilePath, contents: nil, attributes: nil)
freopen(ONETlogFilePath.cString(using: .ascii), "w+", stdout)
freopen(ONETlogFilePath.cString(using: .ascii), "w+", stderr)
}
override func stopTunnel(with reason: NEProviderStopReason) async {
isAlive = false
Socks5Tunnel.quit()
}
override func handleAppMessage(_ data: Data) async -> Data? {
let params = try! JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
let method = params["method"] as! String
let args = params["args"] as? [String : Any]
switch(method) {
case "JoinAppLog":
return wrapAppMessageResult(await cli_shared.JoinAppLog())
case "YanChiCeShi":
let nName = args!["proxyName"] as! String
let u = args!["url"] as! String
let to = args!["timeout"] as! Int
return wrapAppMessageResult(await cli_shared.YanChiCeShi(nName: nName, u: u, to: to))
case "SetLayout":
return wrapAppMessageResult(await cli_shared.SetLayout())
case "XiuGaiJieDian":
//
//
let pName = args!["pName"] as! String
//
let sName = args!["sName"] as! String
let name3 = ""
return wrapAppMessageResult(await cli_shared.XiuGaiJieDian(pName: pName, sName: sName, name3: name3))
case "NeiHeChuShi":
let hDir = args!["hDir"] as! String
return wrapAppMessageResult(await cli_shared.HeNeiHeChuShi(hDir: hDir))
case "GuanBiAllCons":
return wrapAppMessageResult(await cli_shared.GuanBiAllCons())
case "GuanBiDangQianCon":
let nameId = args!["nameId"] as! String
return wrapAppMessageResult(await cli_shared.GuanBiDangQianCon(nameId: nameId))
case "GetUserInfo":
return wrapAppMessageResult(await cli_shared.GetUserInfo())
case "HuoQuSuoYouCons":
return wrapAppMessageResult(await cli_shared.HuoQuSuoYouCons())
case "HuoQuPeiZhi":
return wrapAppMessageResult(await cli_shared.HuoQuPeiZhi())
case "HuoQuPeiZhiPro":
return wrapAppMessageResult(await cli_shared.HuoQuPeiZhiPro())
case "HuoQuShuXing":
return wrapAppMessageResult(await cli_shared.HuoQuShuXing())
case "HuoQuDaiLi":
return wrapAppMessageResult(await cli_shared.HuoQuDaiLi())
case "HuoQuTongJi":
return wrapAppMessageResult(await cli_shared.HuoQuTongJi())
case "HuoQuSuiDaoMoShi":
return wrapAppMessageResult(await cli_shared.HuoQuSuiDaoMoShi())
case "PanDuanPeiZhi":
let cp = args!["cp"] as! String
return wrapAppMessageResult(await cli_shared.PanDuanPeiZhi(cp: cp))
case "SetAppInfo":
return wrapAppMessageResult(await cli_shared.SetAppInfo(appinfo: ""))
case "JieXiPeiZhi":
return wrapAppMessageResult(await cli_shared.JieXiPeiZhi())
case "SheZhiPeiZhi":
let cp = args!["cp"] as! String
return wrapAppMessageResult(await cli_shared.SheZhiPeiZhi(cp: cp))
case "SheZhiZhuYeLuJing":
let LuJing = args!["LuJing"] as! String
return wrapAppMessageResult(await cli_shared.SheZhiZhuYeLuJing(LuJing: LuJing))
case "SheZhiSuiDaoMoShi":
let moShi = args!["moShi"] as! String
return wrapAppMessageResult(await cli_shared.SheZhiSuiDaoMoShi(moShi: moShi))
case "ppap":
return wrapAppMessageResult(await cli_shared.ppap())
case "KaiQiRiZhi":
return wrapAppMessageResult(await cli_shared.KaiQiRiZhi())
case "TingZhiRiZhi":
return wrapAppMessageResult(await cli_shared.TingZhiRiZhi())
case "isAlive":
return wrapAppMessageResult(isAlive)
default:
break
}
return nil
}
}
private func initHttpSettings(_ p: Int) -> NEPacketTunnelNetworkSettings {
let netSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "254.1.1.1")
netSettings.mtu = 9000
netSettings.ipv4Settings = {
let netSettings = NEIPv4Settings(addresses: ["198.18.0.1"], subnetMasks: ["255.255.0.0"])
netSettings.includedRoutes = [NEIPv4Route.default()]
return netSettings
}()
netSettings.ipv6Settings = {
let netSettings = NEIPv6Settings(addresses: ["fd6e:a81b:704f:1211::1"], networkPrefixLengths: [64])
netSettings.includedRoutes = [NEIPv6Route.default()]
return netSettings
}()
netSettings.dnsSettings = NEDNSSettings(servers: ["127.0.0.1"])
netSettings.proxySettings = {
let netSettings = NEProxySettings();
netSettings.httpServer = NEProxyServer(address: "::1", port: p)
netSettings.httpsServer = NEProxyServer(address: "::1", port: p)
netSettings.httpEnabled = true
netSettings.httpsEnabled = true
netSettings.matchDomains = [""]
return netSettings
}()
return netSettings
}
private func createTunnelConfig(socksPort: Int) -> String {
return """
tunnel:
mtu: 9000
socks5:
port: \(socksPort)
address: ::1
udp: 'udp'
misc:
task-stack-size: 2048
connect-timeout: 5000
read-write-timeout: 60000
log-file: stderr
log-level: info
limit-nofile: 65535
"""
}
private func wrapAppMessageResult(_ retStrr: Any?) -> Data? {
if (retStrr == nil || retStrr is Void) {
return nil
}
if (retStrr is Int) {
return withUnsafeBytes(of: retStrr as! Int) { Data($0) }
}
if (retStrr is Bool) {
return withUnsafeBytes(of: (retStrr as! Bool) ? 1 : 0) { Data($0) }
}
if (retStrr is String) {
return (retStrr as! String).data(using: .utf8)
}
return nil
}