Files
LocalDevVPN/TunnelProv/PacketTunnelProvider.swift
2025-10-03 09:09:18 +10:00

73 lines
2.7 KiB
Swift

//
// PacketTunnelProvider.swift
// TunnelProv
//
// Created by Stossy11 on 28/03/2025.
//
import NetworkExtension
class PacketTunnelProvider: NEPacketTunnelProvider {
var tunnelDeviceIp: String = "10.7.0.0"
var tunnelFakeIp: String = "10.7.0.1"
var tunnelSubnetMask: String = "255.255.255.0"
private var deviceIpValue: UInt32 = 0
private var fakeIpValue: UInt32 = 0
override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) {
if let deviceIp = options?["TunnelDeviceIP"] as? String {
tunnelDeviceIp = deviceIp
}
if let fakeIp = options?["TunnelFakeIP"] as? String {
tunnelFakeIp = fakeIp
}
deviceIpValue = ipToUInt32(tunnelDeviceIp)
fakeIpValue = ipToUInt32(tunnelFakeIp)
let settings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: tunnelDeviceIp)
let ipv4 = NEIPv4Settings(addresses: [tunnelDeviceIp], subnetMasks: [tunnelSubnetMask])
ipv4.includedRoutes = [NEIPv4Route(destinationAddress: tunnelDeviceIp, subnetMask: tunnelSubnetMask)]
ipv4.excludedRoutes = [.default()]
settings.ipv4Settings = ipv4
setTunnelNetworkSettings(settings) { error in
guard error == nil else { return completionHandler(error) }
self.setPackets()
completionHandler(nil)
}
}
func setPackets() {
packetFlow.readPackets { [self] packets, protocols in
let fakeip = self.fakeIpValue
let deviceip = self.deviceIpValue
var modified = packets
for i in modified.indices where protocols[i].int32Value == AF_INET && modified[i].count >= 20 {
modified[i].withUnsafeMutableBytes { bytes in
guard let ptr = bytes.baseAddress?.assumingMemoryBound(to: UInt32.self) else { return }
let src = UInt32(bigEndian: ptr[3])
let dst = UInt32(bigEndian: ptr[4])
if src == deviceip { ptr[3] = fakeip.bigEndian }
if dst == fakeip { ptr[4] = deviceip.bigEndian }
}
}
self.packetFlow.writePackets(modified, withProtocols: protocols)
setPackets()
}
}
private func ipToUInt32(_ ipString: String) -> UInt32 {
let components = ipString.split(separator: ".")
guard components.count == 4,
let b1 = UInt32(components[0]),
let b2 = UInt32(components[1]),
let b3 = UInt32(components[2]),
let b4 = UInt32(components[3]) else {
return 0
}
return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4
}
}