Intercept IP address or Domain Name from safari using VPN

392 Views Asked by At

Hello I am working on an application which can intercept the visited network traffic ip address list from iPhone (similar to Charles Proxy).

Currently I have written code to create a VPN profile using NETunnelProviderManager class.

        NETunnelProviderManager.loadAllFromPreferences { [weak self] managers, error in
            guard let self = self else { return }
            if self.manager != managers?.first {
                self.manager = managers?.first
            } else {
                self.manager = self.makeManager()
            }
            self.manager?.saveToPreferences(completionHandler: { (error) in
                if let error = error {
                    print("Error in saving VPN Config: \(error.localizedDescription)")
                }
                self.manager?.loadFromPreferences(completionHandler: { (error) in
                    if error == nil {
                        do {
                            try self.manager?.connection.startVPNTunnel()
                        } catch let vpnTunnelError {
                            print("Unable to start VPN Tunnel by error: \(vpnTunnelError.localizedDescription)")
                        }
                    } else {
                        print("Load From Preference Error")
                    }
                })
            })
        }
    }
    private func makeManager() -> NETunnelProviderManager {
        let manager = NETunnelProviderManager()
        manager.localizedDescription = "NetworkTrafficVPN"

        let proto = NETunnelProviderProtocol()
        proto.providerBundleIdentifier = "com.NetworkTraffic.vpn-tunnel"
        proto.serverAddress = "Network Traffic"
        manager.protocolConfiguration = proto

        let onDemandRule = NEOnDemandRuleConnect()
        onDemandRule.interfaceTypeMatch = .any
        manager.isOnDemandEnabled = true
        manager.onDemandRules = [onDemandRule]
        manager.isEnabled = true
        return manager
    }

Once I start the vpn tunnel (self.manager?.connection.startVPNTunnel()) from the created NETunnelProviderManager object

I get a callback in NEPacketTunnelProvider network extension method (startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void)).

I have created the NEPacketTunnelNetworkSettings inside startTunnel() method using the assigned IP address of the iPhone.

After calling the method self.setTunnelNetworkSettings(settings) { error in } I am getting network data callback inside self.packetFlow.readPackets { (data, numbers) } method

class PacketTunnelProvider: NEPacketTunnelProvider {

    // MARK: - Constants

    let logger: Logger = Logger(subsystem: "NetworkTrafficSubsystem", category: "NetworkTrafficCategory")
    let proxyServerPort: Int = 8888
    let proxyServerAddress = "192.168.43.185" // Device assigned ip address

    // MARK: - NEPacketTunnelProvider

    override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) {
        let settings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: proxyServerAddress)
        settings.tunnelOverheadBytes = 80
        settings.mtu = 1400

        settings.ipv4Settings = NEIPv4Settings(addresses: [proxyServerAddress], subnetMasks: ["255.255.255.255"])
        settings.ipv4Settings?.includedRoutes = [NEIPv4Route.default()]
        settings.ipv4Settings?.excludedRoutes = []
        settings.dnsSettings = NEDNSSettings(servers: ["8.8.8.8", "8.8.4.4"])
        settings.dnsSettings?.matchDomains = []
        self.setTunnelNetworkSettings(settings) { error in
            if let e = error {
                self.logger.info("Settings error")
                completionHandler(e)
            } else {
                self.logger.info("Settings set without error")
                self.readPacketObjects()
                completionHandler(nil)
            }
        }
    }

    private func readPacketObjects() {

        self.packetFlow.readPackets { (data, numbers) in
            self.logger.info("Inside readPackets completionHandler")
            // Way to print the ip address from the received data array
            self.packetFlow.writePackets(data, withProtocols: numbers)
            self.readPacketObjects()
        }
    }
}

But I am unable to decode the data object from self.packetFlow.readPackets { (data, numbers) in } method.

So my question is that in order to read the IP address of all the visited network traffic is this the correct approach or I need to do something else.

If this is correct approach then let me know how to decode the received Data object. If not then please suggest the correct way to achieve this functionality.

Any help would be appreciated thanks.

1

There are 1 best solutions below

0
On

So my question is that in order to read the IP address of all the visited network traffic is this the correct approach or I need to do something else

You need to implement Per App VPN.

Per App VPN can be implemented for Supervised Devices only. if you want to implement it in test mode apple provides Testing Per App VPN (last paragraph of this page) which works without MDM.