mirror of
https://github.com/jkcoxson/LocalDevVPN.git
synced 2026-03-02 14:36:16 +01:00
Fix Localizable, Update TunnelProv, Add fix for Duplicated VPNs
This commit is contained in:
@@ -12,6 +12,9 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
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
|
||||
@@ -20,11 +23,15 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
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
|
||||
if error == nil {
|
||||
self.readPackets()
|
||||
@@ -34,120 +41,69 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
}
|
||||
|
||||
override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
|
||||
// Add code here to start the process of stopping the tunnel.
|
||||
completionHandler()
|
||||
}
|
||||
|
||||
override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)?) {
|
||||
// Add code here to handle the message.
|
||||
if let handler = completionHandler {
|
||||
handler(messageData)
|
||||
}
|
||||
completionHandler?(messageData)
|
||||
}
|
||||
|
||||
override func sleep(completionHandler: @escaping () -> Void) {
|
||||
completionHandler()
|
||||
}
|
||||
|
||||
override func wake() {
|
||||
// Add code here to wake up.
|
||||
}
|
||||
override func wake() {}
|
||||
|
||||
private func readPackets() {
|
||||
packetFlow.readPackets { packets, protocols in
|
||||
var output: [Data] = []
|
||||
var output = [Data](repeating: Data(), count: packets.count)
|
||||
|
||||
for (i, packet) in packets.enumerated() {
|
||||
var modifiedPacket = packet
|
||||
if protocols[i].int32Value == AF_INET {
|
||||
modifiedPacket = self.packetReplaceIp(packet, self.tunnelDeviceIp, self.tunnelFakeIp, self.tunnelFakeIp, self.tunnelDeviceIp)
|
||||
guard protocols[i].int32Value == AF_INET, packet.count >= 20 else {
|
||||
output[i] = packet
|
||||
continue
|
||||
}
|
||||
|
||||
if modifiedPacket.count >= 20 {
|
||||
var mutableBytes = [UInt8](modifiedPacket)
|
||||
|
||||
// Swap bytes
|
||||
(mutableBytes[12], mutableBytes[16]) = (mutableBytes[16], mutableBytes[12])
|
||||
(mutableBytes[13], mutableBytes[17]) = (mutableBytes[17], mutableBytes[13])
|
||||
(mutableBytes[14], mutableBytes[18]) = (mutableBytes[18], mutableBytes[14])
|
||||
(mutableBytes[15], mutableBytes[19]) = (mutableBytes[19], mutableBytes[15])
|
||||
|
||||
modifiedPacket = Data(mutableBytes)
|
||||
}
|
||||
|
||||
output.append(modifiedPacket)
|
||||
|
||||
output[i] = self.processPacket(packet)
|
||||
}
|
||||
|
||||
self.packetFlow.writePackets(output, withProtocols: protocols)
|
||||
self.readPackets()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func packetReplaceIp(_ data: Data, _ sourceSearch: String, _ sourceReplace: String, _ destSearch: String, _ destReplace: String) -> Data {
|
||||
// Check if packet is too small for IPv4 header
|
||||
if data.count < 20 {
|
||||
return data
|
||||
private func processPacket(_ packet: Data) -> Data {
|
||||
var bytes = [UInt8](packet)
|
||||
|
||||
let srcIP = UInt32(bigEndian: bytes.withUnsafeBytes { $0.load(fromByteOffset: 12, as: UInt32.self) })
|
||||
let dstIP = UInt32(bigEndian: bytes.withUnsafeBytes { $0.load(fromByteOffset: 16, as: UInt32.self) })
|
||||
|
||||
if srcIP == deviceIpValue {
|
||||
let replacement = fakeIpValue.bigEndian
|
||||
withUnsafeBytes(of: replacement) { bytes.replaceSubrange(12..<16, with: $0) }
|
||||
}
|
||||
if dstIP == fakeIpValue {
|
||||
let replacement = deviceIpValue.bigEndian
|
||||
withUnsafeBytes(of: replacement) { bytes.replaceSubrange(16..<20, with: $0) }
|
||||
}
|
||||
|
||||
// Convert IP strings to Data with network byte order (big-endian)
|
||||
func ipToUInt32(_ ipString: String) -> UInt32 {
|
||||
let components = ipString.split(separator: ".")
|
||||
var result: UInt32 = 0
|
||||
|
||||
if components.count == 4,
|
||||
let byte1 = UInt32(components[0]),
|
||||
let byte2 = UInt32(components[1]),
|
||||
let byte3 = UInt32(components[2]),
|
||||
let byte4 = UInt32(components[3]) {
|
||||
result = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
bytes.swapAt(12, 16)
|
||||
bytes.swapAt(13, 17)
|
||||
bytes.swapAt(14, 18)
|
||||
bytes.swapAt(15, 19)
|
||||
|
||||
// Convert IP strings to UInt32
|
||||
let sourceSearchIP = ipToUInt32(sourceSearch)
|
||||
let sourceReplaceIP = ipToUInt32(sourceReplace)
|
||||
let destSearchIP = ipToUInt32(destSearch)
|
||||
let destReplaceIP = ipToUInt32(destReplace)
|
||||
|
||||
// Extract source and destination IPs from packet
|
||||
var sourcePacketIP: UInt32 = 0
|
||||
var destPacketIP: UInt32 = 0
|
||||
|
||||
(data as NSData).getBytes(&sourcePacketIP, range: NSRange(location: 12, length: 4))
|
||||
(data as NSData).getBytes(&destPacketIP, range: NSRange(location: 16, length: 4))
|
||||
|
||||
if sourceSearchIP != sourcePacketIP && destSearchIP != destPacketIP {
|
||||
return data
|
||||
}
|
||||
|
||||
let mutableData = NSMutableData(data: data)
|
||||
|
||||
if sourceSearchIP == sourcePacketIP {
|
||||
var sourceIP = sourceReplaceIP
|
||||
mutableData.replaceBytes(in: NSRange(location: 12, length: 4), withBytes: &sourceIP)
|
||||
}
|
||||
|
||||
if destSearchIP == destPacketIP {
|
||||
var destIP = destReplaceIP
|
||||
mutableData.replaceBytes(in: NSRange(location: 16, length: 4), withBytes: &destIP)
|
||||
}
|
||||
|
||||
return mutableData as Data
|
||||
return Data(bytes)
|
||||
}
|
||||
|
||||
// Helper function to convert IP string to Data
|
||||
private func ipToData(_ ip: String) -> Data {
|
||||
let components = ip.split(separator: ".")
|
||||
var data = Data(capacity: 4)
|
||||
|
||||
for component in components {
|
||||
if let byte = UInt8(component) {
|
||||
data.append(byte)
|
||||
}
|
||||
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 data
|
||||
return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user