Posts

Post not yet marked as solved
3 Replies
287 Views
Hi! We are investigating the power consumption of our VPN app on iOS. We noticed that while the VPN tunnel is started, we frequently experience sleep and wake events. Depending on the device it varies somewhere between 60 - 600 times during an overnight test where the device is just laying around and doing absolutely nothing. I looked into the system logs, and the wake reason is always this one: 2024-03-01 03:09:00.836588+0200 0x35e96 Default 0x0 50 7 wifid: (WiFiPolicy) [com.apple.WiFiPolicy:] System wake reason: SMC.OutboxNotEmpty smc.70070000 baseband I googled what OutboxNotEmpty means, but I only found several macOS-related topics. Interestingly, when I leave the same phone without a VPN running, I don't see the above log even once during an overnight test. I also tested a different VPN app and saw the above log in the system logs. This makes me think this is either some iOS feature I don't understand or some bug that causes frequent wakeups. I'd appreciate any feedback if this is a known issue or if we need to do something differently within our tunnel implementation.
Posted
by twardakm.
Last updated
.
Post not yet marked as solved
9 Replies
558 Views
Hi! We are developing VPN software for the iOS platform, and our customers report a rare issue that we cannot reproduce. We seek any advice about the root cause of such a problem. On every update, we notice an increased number of customer reports saying that the tunnel process is in a "connecting" loop, and to break the loop the customer has to remove the VPN profile from the settings. As none of our testers could reproduce the issue, we have minimal knowledge to work on. What we know so far: The OnDemand rules cause the tunnel process to be restarted in the loop The tunnel process does not start at all. We have logs from our customers, and we know that the application tries to start an extension, but the extension does not start at all. Something in the operating system prevents the extension from starting. The issue reappears on every app update. My theory so far is that the profile gets broken during an update process, but we have no means of confirming that. Is this a known issue? Any advice on how could we reproduce the problem? Thank you in advance for any tips!
Posted
by twardakm.
Last updated
.
Post not yet marked as solved
4 Replies
457 Views
Hello, I experienced a strange (and in my opinion unexpected) behavior from DynamicStore/configd. In our application we setup the routes in the system by setting AdditionalRoutes property on a specific interface to route part of the network traffic through it. The routes are set properly, but I noticed that the they are not cleared once removed from AdditionalRoutes. After a while I figured, that the problem lies in the DestinationAddress I set in AdditionalRoutes. I was using the following configuration: var newRoutes: [[String: NSObject]] = [ ["DestinationAddress": "10.0.0.1" as NSObject, "SubnetMask": "255.0.0.0" as NSObject ] ] and it resulted in a new route: 10 link#16 UCS en0 ! which was not cleared when AdditionalRoutes were reset to the original value. When I changed the DestinationAddress to: var newRoutes: [[String: NSObject]] = [ ["DestinationAddress": "10.0.0.0" as NSObject, "SubnetMask": "255.0.0.0" as NSObject ] ] both, setting and clearing routes works as expected. The only difference is changing the DestinationAddress from 10.0.0.1 to 10.0.0.1. In my opinion this incosistent behavior. Although I can understand that the system might reject 10.0.0.1 as a valid DestinationAddress for creating routes, I don't think it's correct behavior to accept such address, but never clear the routes. The full source code which might be used to verify my claims: import Foundation import SystemConfiguration let en0ServiceIPv4 = "State:/Network/Service/***/IPv4" as CFString let store = SCDynamicStoreCreate(nil, "dseditor" as CFString, nil, nil)! let originalValue = SCDynamicStoreCopyValue(store, en0ServiceIPv4) as! [String: NSObject] var newValue = originalValue print("AdditionalRoutes: \(String(describing: originalValue["AdditionalRoutes"]))") var newRoutes: [[String: NSObject]] = [ ["DestinationAddress": "10.0.0.1" as NSObject, "SubnetMask": "255.0.0.0" as NSObject ] ] newValue["AdditionalRoutes"] = newRoutes as NSObject print("newValue: \(newValue)") var result = SCDynamicStoreSetValue(store, en0ServiceIPv4, newValue as CFPropertyList) print("set new value: \(result)") sleep(3) result = SCDynamicStoreSetValue(store, en0ServiceIPv4, originalValue as CFPropertyList) print("restore old value: \(result)") Naturally, the en0ServiceIPv4 needs to be changed and the program needs to be run as root. Can you please share your thoughts, if this is an OS bug or expected behavior? If it is expected, what is the reasoning behind it?
Posted
by twardakm.
Last updated
.
Post not yet marked as solved
5 Replies
632 Views
Hello, I'm struggling to understand how I can use NSXPC API to communicate between two processes on iOS. The problem which I want to solve is how to pass some information from VPN tunnel to the VPN app. I'm looking at the XPC documentation and for iOS I can create NSXPCListener only with the following functions: service() anonymous() Both return NSXPCListener instance. But the question remains, how to connect to such an instance? In NSXPConnection API I see only one option for iOS: init(listenerEndpoint: NSXPCListenerEndpoint) Other constructors accepting serviceName or machServiceName are available only form macOS. I feel like the problem of communicating between two processes should be easy, but surprisingly I did find it quite difficult on iOS. Can you please advice if this is a proper API for my use case? Or maybe is there some better one, which I'm not aware of? If this is a proper API, how should I create a connection between two apps? How to pass a listener from one process to the other?
Posted
by twardakm.
Last updated
.
Post not yet marked as solved
3 Replies
531 Views
I am developing a VPN app that uses Network Extension and Wireguard protocol on Ventura (13.4). I am testing the following scenario: Connect my Mac to WiFi (en0 = index 16) and to an iPad (via USB-C) which works as hotspot (en11 = index 26). Make sure in System Settings that WiFi is before iPad hotspot in Service order Connect to the VPN client (utun3 = index 28 is created) Disable WiFi When I disable WiFi I lose access to the internet. To regain the internet access on a new interface I need to restart the tunnel completely. From a user perspective, on a Mac it seems fine, but on an iOS device it feels like suboptimal solution - the user might frequently move between WiFi/cellular connectivity and we need to reestablish VPN connection every time the default interface changes (I tested that scenario as well and it behaves exactly the same as on macOS). So far I have implemented a workaround to avoid such reconnection, and in our tunnel implementation I use good, old bind to rebind our tunnel socket (UDP) to the primary interface (en0/en11). I checked the NECP logs for more details, and in a scenario, when I don't use the custom bind, I see that some rules are created which seem to be skipped: 2023-06-27 08:53:25.277090+0200 0x43e4a5 Error 0x0 0 0 kernel: necp_socket_find_policy_match_with_info_locked: DATA-TRACE <SOCKET <private>>: MATCHED POLICY - proto 17 port <local 64002/64002 remote 0/0> <drop-all order 9001> <pid=73678 Application 66744 Real Application 66744 BoundInterface 26> (policy id=29157 session_order=2002 policy_order=10802 result=IP_TUNNEL) 2023-06-27 08:53:25.277097+0200 0x43e4a5 Default 0x0 0 0 kernel: necp_socket_find_policy_match: Socket Policy: <private> (BoundInterface 26 Proto 17) Policy 29157 Skip 10494 Result 6 Parameter 26 My application PID is 73678 and iPad hotspot network interface (en11) is 26. To me it looks like the packets which are supposed go to the en11 interface are skipped. Is this expected/desired behavior, that while changing network interfaces, the tunnel should be completely restarted?
Posted
by twardakm.
Last updated
.