Routing packets using Packet Tunnel Provider

Hi!

I am new to Apple app development so please bear with me.

I am trying to design an app that can mimic some of the functionality of iptables routing. The crux of it is I would like to redirect local traffic bound for a specific port to a different port and then redirect any outgoing traffic on that port back to the original port:

outgoing packet bound for IP:1234 -> 127.0.0.1:2345 outgoing packet bound for IP:2345 -> IP:1234

I tried to implement this behavior with a packet tunnel but have not made any substantial progress. Is this the right approach?

Here is my implementation:

private func handleConnection(_ connection: NWConnection) {
    connection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { [weak self] data, context, isComplete, error in
        if let data = data, !data.isEmpty {
            self?.processData(data, from: connection)
        }
        if let error = error {
            print("Connection error: \(error)")
        }
        if isComplete {
            connection.cancel()
        } else {
            self?.handleConnection(connection) // Continue to receive data
        }
    }
    connection.start(queue: .main)
}

private func processData(_ data: Data, from connection: NWConnection) {
    switch connection.endpoint {
    case .hostPort(let host, let port):
        let portNumber = port.rawValue
        let hostDescription = host.debugDescription
        print("Received data from host: \(hostDescription) on port: \(portNumber)")
        
        if portNumber == 1234 {
            // Rule 1: Redirect traffic from port 1234 to 127.0.0.1:2345
            redirectTraffic(data, to: "127.0.0.1", port: 2345)
            print("Redirecting traffic from 1234 to 2345")
        } else if portNumber == 2345 {
            // Rule 2: Redirect traffic from port 2345 to the original IP address but port 1234
            redirectTraffic(data, to: hostDescription, port: 1234)
            print("Redirecting traffic from 2345 back to 1234")
        }
        
    case .service(name: _, type: _, domain: _, interface: _):
        print("Received bonjour service")
    case .unix(path: _):
        print("Received unix domain path")
    case .url(_):
        print("Received url")
    case .opaque(_):
        print("Opaque?")
    @unknown default:
        fatalError("Unknown endpoint type")
    }
}
I tried to implement this behavior with a packet tunnel but have not made any substantial progress. Is this the right approach?

Almost certainly not )-: I often see folks try to use an NE packet tunnel provider to achieve a goal that it was never intended to support. Indeed, one of my former colleagues tackled this problem head on in TN3120 Expected use cases for Network Extension packet tunnel providers.

So what’s your high-level goal here?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Routing packets using Packet Tunnel Provider
 
 
Q