Network Extension

RSS for tag

Customize and extend the core networking features of iOS, iPad OS, and macOS using Network Extension.

Posts under Network Extension tag

200 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

Two or more System Extension activation on Ventura
Hello! After submitting two OSSystemExtensionRequest (let's say Endpoint and Network extensions), when the user allows only one (endpoint) extension, we receive request: didFinishWithResult callback for both manager delegates. This leads us to falsely believe that both our extensions are allowed. We tried to prevent this by using propertiesRequestForExtension where our (network) delegate will ask for properties, check if the given extension is enabled and then finish if it's ok. If it's not enabled, however, we receive no second callback when the user allows the other extension. We thought that we would need to submit another OSSystemExtensionRequest for the extension that wasn't allowed to receive a callback when it finally is. However, the second and all other consecutive requests immediately finish and we receive request: didFinishWithResult even when the user does not allow the second extension. Example: Endpoint and Network managers submit OSSystemExtensionRequest User only allows Endpoint extension Endpoint manager checks the properties, finds out it's enabled and finishes Network manager checks the properties, finds out it's disabled Network manager sends another OSSystemExtensionRequest Network manager immediately receives request: didFinishWithResult Network manager checks the properties, finds out it's disabled .... This loop ends when the user finally allows the network extension, when the manager finds out that it's enabled. Is there something we are missing? Shouldn't another OSSystemExtensionRequest finish with requestNeedsUserApproval. How should we go about this issue? Many thanks, Denis
6
0
1.6k
Aug ’23
Debugging a Network Extension Provider
I regularly see folks struggle to debug their Network Extension providers. For an app, and indeed various app extensions, debugging is as simple as choosing Product > Run in Xcode. That’s not the case with a Network Extension provider, so I thought I’d collect together some hints and tips to help you get started. If you have any comments or questions, create a new thread here on DevForums and tag it with Network Extension so that I see it. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Debugging a Network Extension Provider Debugging a Network Extension provider presents some challenges; its not as simple as choosing Product > Run in Xcode. Rather, you have to run the extension first and then choose Debug > Attach to Process. Attaching is simple, it’s the running part that causes all the problems. When you first start out it can be a challenge to get your extension to run at all. Add a First Light Log Point The first step is to check whether the system is actually starting your extension. My advice is to add a first light log point, a log point on the first line of code that you control. The exact mechanics of this depend on your development, your deployment target, and your NE provider’s packaging. In all cases, however, I recommend that you log to the system log. The system log has a bunch of cool features. If you’re curious, see Your Friend the System Log. The key advantage is that your log entries are mixed in with system log entries, which makes it easier to see what else is going on when your extension loads, or fails to load. IMPORTANT Use a unique subsystem and category for your log entries. This makes it easier to find them in the system log. For more information about Network Extension packaging options, see TN3134 Network Extension provider deployment. Logging in Swift If you’re using Swift, the best logging API depends on your deployment target. On modern systems — macOS 11 and later, iOS 14 and later, and aligned OS releases — it’s best to use the Logger API, which is shiny and new and super Swift friendly. For example: let log = Logger(subsystem: "com.example.galactic-mega-builds", category: "earth") let client = "The Mice" let answer = 42 log.log(level: .debug, "run complete, client: \(client), answer: \(answer, privacy: .private)") If you support older systems, use the older, more C-like API: let log = OSLog(subsystem: "com.example.galactic-mega-builds", category: "earth") let client = "The Mice" let answer = 42 os_log(.debug, log: log, "run complete, client: %@, answer: %{private}d", client as NSString, answer) Logging in C If you prefer a C-based language, life is simpler because you only have one choice: #import <os/log.h> os_log_t log = os_log_create("com.example.galactic-mega-builds", "earth"); const char * client = "The Mice"; int answer = 42; os_log_debug(log, "run complete, client: %s, answer: %{private}d", client, answer); Add a First Light Log Point to Your App Extension If your Network Extension provider is packaged as an app extension, the best place for your first light log point is an override of the provider’s initialiser. There are a variety of ways you could structure this but here’s one possibility: import NetworkExtension import os.log class PacketTunnelProvider: NEPacketTunnelProvider { static let log = Logger(subsystem: "com.example.myvpnapp", category: "packet-tunnel") override init() { self.log = Self.log log.log(level: .debug, "first light") super.init() } let log: Logger … rest of your code here … } This uses a Swift static property to ensure that the log is constructed in a race-free manner, something that’s handy for all sorts of reasons. It’s possible for your code to run before this initialiser — for example, if you have a C++ static constructor — but that’s something that’s best to avoid. Add a First Light Log Point to Your System Extension If your Network Extension provider is packaged as a system extension, add your first light log point to main.swift. Here’s one way you might structure that: import NetworkExtension func main() -> Never { autoreleasepool { let log = PacketTunnelProvider.log log.log(level: .debug, "first light") NEProvider.startSystemExtensionMode() } dispatchMain() } main() See how the main function gets the log object from the static property on PacketTunnelProvider. I told you that’d come in handy (-: Again, it’s possible for your code to run before this but, again, that’s something that’s best to avoid. App Extension Hints Both iOS and macOS allow you to package your Network Extension provider as an app extension. On iOS this is super reliable. I’ve never seen any weirdness there. That’s not true on macOS. macOS lets the user put apps anywhere; they don’t have to be placed in the Applications directory. macOS maintains a database, the Launch Services database, of all the apps it knows about and their capabilities. The app extension infrastructure uses that database to find and load app extensions. It’s not uncommon for this database to get confused, which prevents Network Extension from loading your provider’s app extension. This is particularly common on developer machines, where you are building and rebuilding your app over and over again. The best way to avoid problems is to have a single copy of your app extension’s container app on the system. So, while you’re developing your app extension, delete any other copies of your app that might be lying around. If you run into problems you may be able to fix them using: lsregister, to interrogate and manipulate the Launch Services database pluginkit, to interrogate and manipulate the app extension state [1] IMPORTANT Both of these tools are for debugging only; they are not considered API. Also, lsregister is not on the default path; find it at /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister. For more details about pluginkit, see the pluginkit man page. When debugging a Network Extension provider, add buttons to make it easy to save and remove your provider’s configuration. For example, if you’re working on a packet tunnel provider you might add: A Save Config button that calls the saveToPreferences(completionHandler:) method to save the tunnel configuration you want to test with A Remove Config button that calls the removeFromPreferences(completionHandler:) method to remove your tunnel configuration These come in handy when you want to start again from scratch. Just click Remove Config and then Save Config and you’ve wiped the slate clean. You don’t have to leave these buttons in your final product, but it’s good to have them during bring up. [1] This tool is named after the PluginKit framework, a private framework used to load this type of app extension. It’s distinct from the ExtensionKit framework which is a new, public API for managing extensions. System Extension Hints macOS allows you to package your Network Extension provider as a system extension. For this to work the container app must be in the Applications directory [1]. Copying it across each time you rebuild your app is a chore. To avoid that, add a Build post-action script: Select your app’s scheme and choose Product > Scheme > Edit Scheme. On the left, select Build. Click the chevron to disclose all the options. Select Post-actions. In the main area, click the add (+) button and select New Run Script Action. In the “Provide build settings from” popup, select your app target. In the script field, enter this script: ditto "${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}" "/Applications/${FULL_PRODUCT_NAME}" Now, each time you build your app, this script will copy it to the Applications directory. Build your app now, both to confirm that this works and to enable the next step. The next issue you’ll find is that choosing Product > Run runs the app from the build products directory rather than the Applications directory. To fix that: Edit your app’s scheme again. On the left, select Run. In the main area, select the Info tab. From the Executable popup, choose Other. Select the copy of your app in the Applications directory. Now, when you choose Product > Run, Xcode will run that copy rather than the one in the build products directory. Neat-o! For your system extension to run your container app must activate it. As with the Save Config and Remote Config buttons described earlier, it’s good to add easy-to-access buttons to activate and deactivate your system extension. With an app extension the system automatically terminates your extension process when you rebuild it. This is not the case with a system extension; you’ll have to deactivate and then reactivate it each time. Each activation must be approved in System Settings > Privacy & Security. To make that easier, leave System Settings running all the time. This debug cycle leaves deactivated but not removed system extensions installed on your system. These go away when you restart, so do that from time to time. Once a day is just fine. macOS includes a tool, systemextensionctl, to interrogate and manipulate system extension state. The workflow described above does not require that you use it, but it’s good to keep in mind. Its man page is largely content free so run the tool with no arguments to get help. [1] Unless you disable System Integrity Protection, but who wants to do that? You Can Attach with the Debugger Once your extension is running, attach with the debugger using one of two commands: To attach to an app extension, choose Debug > Attach to Process > YourAppExName. To attach to a system extension, choose Debug > Attach to Process by PID or Name. Make sure to select Debug Process As root. System extensions run as root so the attach will fail if you select Debug Process As Me. But Should You? Debugging networking code with a debugger is less than ideal because it’s common for in-progress network requests to time out while you’re stopped in the debugger. Debugging Network Extension providers this way is especially tricky because of the extra steps you have to take to get your provider running. So, while you can attach with the debugger, and that’s a great option in some cases, it’s often better not to do that. Rather, consider the following approach: Write the core logic of your provider so that you can unit test each subsystem outside of the provider. This may require some scaffolding but the time you take to set that up will pay off once you encounter your first gnarly problem. Add good logging to your provider to help debug problems that show up during integration testing. I recommend that you treat your logging as a feature of your product. Carefully consider where to add log points and at what level to log. Check this logging code into your source code repository and ship it — or at least the bulk of it — as part of your final product. This logging will be super helpful when it comes to debugging problems that only show up in the field. Remember that, when using the system log, log points that are present but don’t actually log anything are very cheap. In most cases it’s fine to leave these in your final product. Now go back and read Your Friend the System Log because it’s full of useful hints and tips on how to use the system log to debug the really hard problems. General Hints and Tips Install the Network Diagnostics and VPN (Network Extension) profiles [1] on your test device. These enable more logging and, most critically, the recording of private data. For more info about that last point, see… you guessed it… Your Friend the System Log. Get these profiles from our Bug Reporting > Profiles and Logs page. When you’re bringing up a Network Extension provider, do your initial testing with a tiny test app. I regularly see folks start out by running Safari and that’s less than ideal. Safari is a huge app with lots of complexity, so if things go wrong it’s hard to tell where to look. I usually create a small test app to use during bring up. The exact function of this test app varies by provider type. For example: If I’m building a packet tunnel provider, I might have a test function that makes an outgoing TCP connection to an IP address. Once I get that working I add another function that makes an outgoing TCP connection to a DNS name. Then I start testing UDP. And so on. Similarly for a content filter, but then it makes sense to add a test that runs a request using URLSession and another one to bring up a WKWebView. If I’m building a DNS proxy provider, my test app might use CFHost to run a simple name-to-address query. Also, consider doing your bring up on the Mac even if your final target is iOS. macOS has a bunch of handy tools for debugging networking issues, including: dig for DNS queries nc for TCP and UDP connections netstat to display the state of the networking stack tcpdump for recording a packet trace [2] Read their respective man pages for all the details. [1] The latter is not a profile on macOS, but just a set of instructions. [2] You can use an RVI packet trace on iOS but it’s an extra setup step. Revision History 2023-12-15 Fixed a particularly egregious typo (and spelling error in a section title, no less!). 2023-04-02 Fixed one of the steps in Sytem Extension Hints.
0
0
2k
Dec ’23
How to identify this crash causes.
Hi, I am experiencing following crashes intermittently in macOS network extension. Sometime in an hour or two or three. I don't see anywhere references to my project code hence i am unable to understand this crashes. Anyone please point me into right direction from here: Crash Dumps Samples: Process: com.skyhighsecurity.epclient.networkextension [39224] Path: /Library/SystemExtensions/*/com.skyhighsecurity.epclient.networkextension Identifier: com.skyhighsecurity.epclient.networkextension Version: 1.0 (1) Code Type: ARM-64 (Native) Parent Process: launchd [1] User ID: 0 Date/Time: 2023-03-20 13:46:51.6991 +0530 OS Version: macOS 12.6.3 (21G419) Report Version: 12 Anonymous UUID: 72617D4C-9E91-7141-D71D-9CB5BDADAA25 Sleep/Wake UUID: B462FD28-68B4-4B46-84EB-D16E29760748 Time Awake Since Boot: 32000 seconds Time Since Wake: 5 seconds System Integrity Protection: disabled Crashed Thread: 3 Dispatch queue: NEFilterExtensionProviderContext queue Exception Type: EXC_BREAKPOINT (SIGTRAP) Exception Codes: 0x0000000000000001, 0x0000000182e26104 Exception Note: EXC_CORPSE_NOTIFY Termination Reason: Namespace SIGNAL, Code 5 Trace/BPT trap: 5 Terminating Process: exc handler [39224] Application Specific Information: BUG IN CLIENT OF LIBPLATFORM: os_unfair_lock is corrupt Abort Cause 1949042982 Thread 0: 0 libsystem_kernel.dylib 0x182dd5d70 __sigsuspend_nocancel + 8 1 libdispatch.dylib 0x182c5b5e0 _dispatch_sigsuspend + 48 2 libdispatch.dylib 0x182c5b5b0 _dispatch_sig_thread + 60 Thread 1: 0 libsystem_pthread.dylib 0x182e07078 start_wqthread + 0 Thread 2: 0 libsystem_pthread.dylib 0x182e07078 start_wqthread + 0 Thread 3 Crashed:: Dispatch queue: NEFilterExtensionProviderContext queue 0 libsystem_platform.dylib 0x182e26104 _os_unfair_lock_corruption_abort + 88 1 libsystem_platform.dylib 0x182e21184 _os_unfair_lock_lock_slow + 328 2 libsystem_pthread.dylib 0x182e07640 pthread_mutex_destroy + 64 3 Foundation 0x183d7ac18 -[_NSXPCConnectionClassCache dealloc] + 48 4 libobjc.A.dylib 0x182cb7c58 objc_object::sidetable_release(bool, bool) + 260 5 NetworkExtension 0x19148b798 -[NEFilterSocketFlow .cxx_destruct] + 40 6 libobjc.A.dylib 0x182c9d8e4 object_cxxDestructFromClass(objc_object*, objc_class*) + 116 7 libobjc.A.dylib 0x182c94b0c objc_destructInstance + 80 8 libobjc.A.dylib 0x182c94ab8 _objc_rootDealloc + 80 9 NetworkExtension 0x19148246c -[NEFilterDataExtensionProviderContext handleSocketSourceEventWithSocket:] + 132 10 libdispatch.dylib 0x182c481b4 _dispatch_client_callout + 20 11 libdispatch.dylib 0x182c4b670 _dispatch_continuation_pop + 500 12 libdispatch.dylib 0x182c5e8e0 _dispatch_source_invoke + 1596 13 libdispatch.dylib 0x182c4f784 _dispatch_lane_serial_drain + 376 14 libdispatch.dylib 0x182c50404 _dispatch_lane_invoke + 392 15 libdispatch.dylib 0x182c5ac98 _dispatch_workloop_worker_thread + 648 16 libsystem_pthread.dylib 0x182e08360 _pthread_wqthread + 288 17 libsystem_pthread.dylib 0x182e07080 start_wqthread + 8
2
0
1.4k
Aug ’23
ipa build with xcode 14.2 crashing in ios 16 and 16.x but working absolutely fine with lower versions.
In code: thread Queue: shared_tcpConnWorkQueue   libsp.dylib`spd_checkin_socket.cold.1:      0x242276464 &lt;+0&gt;:  adrp   x8, 137736      0x242276468 &lt;+4&gt;:  adrp   x9, 0      0x24227646c &lt;+8&gt;:  add    x9, x9, #0xa3f            ; "Linked against modern SDK, VOIP socket will not wake. Use Local Push Connectivity instead"      0x242276470 &lt;+12&gt;: str    x9, [x8, #0x390] 0x242276474 &lt;+16&gt;: brk    #0x1 -&gt; EXC_BREAKPOINT (code=1, subcode=0x242276474) DeviceLogs: Application Specific Information: Linked against modern SDK, VOIP socket will not wake. Use Local Push Connectivity instead   Thread 3 name:   Dispatch queue: shared_tcpConnWorkQueue Thread 3 Crashed: 0   libsp.dylib                          0x216566474 spd_checkin_socket.cold.1 + 16 1   libsp.dylib                          0x2165654c0 spd_checkin_socket + 896 2   CFNetwork                            0x1b4230ef0 0x1b40f2000 + 1306352 3   CFNetwork                            0x1b4232bcc 0x1b40f2000 + 1313740 4   CFNetwork                            0x1b42351e0 0x1b40f2000 + 1323488 5   CFNetwork                            0x1b42343a0 0x1b40f2000 + 1319840 6   libdispatch.dylib                    0x1b9e61850 _dispatch_call_block_and_release + 24 7   libdispatch.dylib                    0x1b9e627c8 _dispatch_client_callout + 16 8   libdispatch.dylib                    0x1b9e3d854 _dispatch_lane_serial_drain$VARIANT$armv81 + 604 9   libdispatch.dylib                    0x1b9e3e2e4 _dispatch_lane_invoke$VARIANT$armv81 + 380 10  libdispatch.dylib                    0x1b9e48000 _dispatch_workloop_worker_thread + 612 11  libsystem_pthread.dylib              0x1fa8e2b50 _pthread_wqthread + 284 12  libsystem_pthread.dylib              0x1fa8e267c start_wqthread + 8 I think it is due to voip socket issue. But not getting the point exactly. As am new to ios Development so do not have much idea. Looking forward for guidance. Thanks in advance!
4
1
1.2k
Nov ’23
enforceRoutes causes excludedRoutes to be ignored
In our PacketTunnelProvider we are seeing behavior for enforceRoutes which appears to contradict the documentation. According to the developer documentation (my emphasis): If this property is YES when the includeAllNetworks property is NO, the system scopes the included routes to the VPN and the excluded routes to the current primary network interface. If we set these IPv4 settings: IPv4Settings = { configMethod = manual addresses = ( 172.16.1.1, ) subnetMasks = ( 255.255.255.255, ) includedRoutes = ( { destinationAddress = 0.0.0.0 destinationSubnetMask = 0.0.0.0 }, ) excludedRoutes = ( { destinationAddress = 10.10.0.0 destinationSubnetMask = 255.255.255.0 }, ) overridePrimary = YES } Then if enforceRoutes is set to YES, then we do not see traffic for the excluded network, which is the expected behavior. If enforceRoutes is set to NO, then we do see traffic for the excluded network. In both cases includeAllNetworks and excludeLocalNetworks are both NO. The excluded network is not one of the local LANs. Is this a known issue? Is there some documented interaction that I missed here? Is there a workaround we can use to make this function as intended, with enforceRoutes set to YES?
6
0
843
May ’24
Network Extension: broken behavior on iOS 16.4+ when setting NEVPNProtocol's `includeAllNetworks` flag.
I am seeing an interesting behavior on iOS 16.4+ when I set NEVPNProtocol includeAllNetworks flag to TRUE as part of my tunnels's saved preferences. After my packet tunnel provider starts up and goes through the usual setup of adding routes, where let's say we just just add NEIPv4Route.default() to route everything and eventually setting via: setTunnelNetworkSettings. Any subsequent calls to cancelTunnelWithError will cause the phone to get into a state where the tunnel provider goes away but it appears that my routes did not properly clean up, essentially causing a device to get into a state where all network traffic is now dead. The only way to recover is to go into OS Settings -> VPN and change selected profile to some other one, or just remove ours and go through installation again. It appears to only be happening on iOS 16.4+ devices, any previous versions clean up just fine. Curious if anyone has seen such behavior? Thanks in advance.
4
0
489
May ’24
async/await back deployment crash in system extension
The problem I have a MacOS app that hosts a content filtering system extension, like SimpleFirewall. The app has been in production for a couple years. I'm working on a new version, and in testing the release candidate, I'm getting a consistent crash that I believe is related to swift concurrency back deployment. Here are the key details: building using Xcode 14.2, from a machine running Monterrey, Swift 5.7.2 crash does not happen when building and testing from Xcode, locally crash does not happen on test machine running Ventura crash DOES happen always on a test machine running Big Sur only the root-user system extension crashes, not the host application the new version introduced async/await into the system extension crash report shows identical stack trace to well-known issue that had to do with concurrency back deployment Is there a known issue/limitation with concurrency back deployment in the context of a system extension? Is there any reason why async/await shouldn't work in that context when deployed to Big Sur? More details, context The key lines of the crash stack trace are: 0 libswiftCore.dylib 0x00007fff2cdacdc7 swift::ResolveAsSymbolicReference::operator()(swift::Demangle::__runtime::SymbolicReferenceKind, swift::Demangle::__runtime::Directness, int, void const*) + 55 1 libswiftCore.dylib 0x00007fff2cdcf2dd swift::Demangle::__runtime::Demangler::demangleSymbolicReference(unsigned char) + 141 2 libswiftCore.dylib 0x00007fff2cdcc2a8 swift::Demangle::__runtime::Demangler::demangleType(__swift::__runtime::llvm::StringRef, std::__1::function<swift::Demangle::__runtime::Node* (swift::Demangle::__runtime::SymbolicReferenceKind, swift::Demangle::__runtime::Directness, int, void const*)>) + 168 3 libswiftCore.dylib 0x00007fff2cdb25a4 swift_getTypeByMangledNameImpl(swift::MetadataRequest, __swift::__runtime::llvm::StringRef, void const* const*, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 516 4 libswiftCore.dylib 0x00007fff2cdafd6d swift::swift_getTypeByMangledName(swift::MetadataRequest, __swift::__runtime::llvm::StringRef, void const* const*, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 477 5 libswiftCore.dylib 0x00007fff2cdaff9b swift_getTypeByMangledNameInContext + 171 6 com.myorg.app.filter-extension 0x000000010db2b8b7 0x10db02000 + 170167 7 libdispatch.dylib 0x00007fff20516806 _dispatch_client_callout + 8 8 libdispatch.dylib 0x00007fff2051798c _dispatch_once_callout + 20 9 libswiftCore.dylib 0x00007fff2cdbe16a swift_once + 26 10 com.myorg.app.filter-extension 0x000000010db2c5e3 0x10db02000 + 173539 11 com.myorg.app.filter-extension 0x000000010dbbd708 0x10db02000 + 767752 12 com.myorg.app.filter-extension 0x000000010db073cc 0x10db02000 + 21452 13 com.apple.NetworkExtension 0x00007fff2dfdd4d8 -[NEExtensionProviderContext createWithCompletionHandler:] + 377 14 com.apple.Foundation 0x00007fff215a7c96 __NSXPCCONNECTION_IS_CALLING_OUT_TO_EXPORTED_OBJECT_S1__ + 10 15 com.apple.Foundation 0x00007fff21552b98 -[NSXPCConnection _decodeAndInvokeMessageWithEvent:flags:] + 2271 16 com.apple.Foundation 0x00007fff2150a049 message_handler + 206 17 libxpc.dylib 0x00007fff20406c24 _xpc_connection_call_event_handler + 56 18 libxpc.dylib 0x00007fff20405a9b _xpc_connection_mach_event + 938 The first five lines are identical to an issue from Xcode 13.2.1, discussed in depth on the swift forums: https://forums.swift.org/t/async-await-crash-on-ios14-with-xcode-13-2-1/54541 ...except I'm using Xcode 14.2. Which makes me think that it's not exactly the same bug, but another manifestation of a failure to link against the back-deployed currency lib, possibly having to do with the fact that the system extension isn't able to access the back-deployed lib. The archived app does have libswift_Concurrency.dylib at MyApp.app/Contents/Frameworks/libswift_Concurrency.dylib. What I've Tried I tested the workaround in the above mentioned thread, using lipo to remove arm64 arch, but it didn't work. I also tested adding -Xllvm -sil-disable-pass=alloc-stack-hoisting to Other Swift settings, as suggested in https://developer.apple.com/forums/thread/697070. I would greatly appreciate any assistance.
9
0
2k
Aug ’23
Xcode 15.0 Beta: NEPacketTunnelProvider is only available in tvOS 17.0 or newer
I'm researching to develop a VPN application on tvOS 17.0, but even if I set the dev target version to 17.0, it still prompts me that the API is not available. 'NEPacketTunnelProvider' is only available in tvOS 17. 0 or newer I have 2 xcodes installed on my computer, I tried switching to sudo xcode-select -s /Applications/Xcode-beta.app/Contents/Developer, but it still doesn't work. Is there anything else I need to set?
5
0
1.4k
Oct ’23
New 60s timer when instantiating PacketTunnelProvider
Somewhere between iOS 16 and iOS 16.5, we've been noticing a new timer when starting up our PacketTunnelProvider. When we start the VPN session and if we take longer than 60 seconds to call the completion handler in (void)startTunnelWithOptions:(NSDictionary *)options completionHandler:(void (^)(NSError *))completionHandler We see that our VPN gets shutdown by the OS. 11:19:15.371532-0700 nesessionmanager NESMVPNSession[Primary Tunnel:test:7A492A00-109B-4DC9-970F-563A7BBC65A6:(null)]: Plugin NEVPNTunnelPlugin(com.netmotionwireless.Mobility[inactive]) initialized with Mach-O UUIDs ( "69923795-443E-3B0D-9D51-1DC84EB26A08" ) 11:19:15.372733-0700 nesessionmanager NESMVPNSession[Primary Tunnel:test:7A492A00-109B-4DC9-970F-563A7BBC65A6:(null)] in state NESMVPNSessionStateStarting: plugin NEVPNTunnelPlugin(com.netmotionwireless.Mobility[inactive]) started with PID 27315 error (null) 11:19:15.389348-0700 nesessionmanager NESMVPNSession[Primary Tunnel:test:7A492A00-109B-4DC9-970F-563A7BBC65A6:(null)] in state NESMVPNSessionStateStarting: plugin NEVPNTunnelPlugin(com.netmotionwireless.Mobility[inactive]) attached IPC with endpoint 0xd5a820210 . . . 11:20:15.290251-0700 nesessionmanager NESMVPNSession[Primary Tunnel:test:7A492A00-109B-4DC9-970F-563A7BBC65A6:(null)]: State timer (60 seconds) fired in state NESMVPNSessionStateStarting 11:20:15.290375-0700 nesessionmanager NESMVPNSession[Primary Tunnel:test:7A492A00-109B-4DC9-970F-563A7BBC65A6:(null)] in state NESMVPNSessionStateStarting: timed out 11:20:15.293574-0700 nesessionmanager NESMVPNSession[Primary Tunnel:test:7A492A00-109B-4DC9-970F-563A7BBC65A6:(null)]: Leaving state NESMVPNSessionStateStarting 11:20:15.293813-0700 nesessionmanager NESMVPNSession[Primary Tunnel:test:7A492A00-109B-4DC9-970F-563A7BBC65A6:(null)]: Entering state NESMVPNSessionStateStopping, timeout 20 seconds 11:20:15.294034-0700 nesessionmanager NESMVPNSession[Primary Tunnel:test:7A492A00-109B-4DC9-970F-563A7BBC65A6:(null)]: config request: pushing handler [(null)] (null) 11:20:15.294286-0700 nesessionmanager <NESMServer: 0xd5a904120>: Request to uninstall session: NESMVPNSession[Primary Tunnel:test:7A492A00-109B-4DC9-970F-563A7BBC65A6:(null)] 11:20:15.294426-0700 nesessionmanager NESMVPNSession[Primary Tunnel:test:7A492A00-109B-4DC9-970F-563A7BBC65A6:(null)]: status changed to disconnecting We can see this with the log message State timer (60 seconds) fired in state NESMVPNSessionStateStarting Is there anything we can do to influence the length of this timer or change the state the VPN is in, other than calling the completion handler? Thanks
6
0
1.1k
Aug ’23
TCC configuration (endpoint security extension) failing via MDM on Ventura
Hello there. We have an endpoint security service that consists of a command-line tool and a client app that bundles a network extension (the command-line tool runs as a daemon via Launch Services and communicates with the extension via XPC). It works when installed manually under all OS versions, and under MacOS 12.x (Monterey) and earlier when provisioned via MDM. However, beginning with some version of 13.x (Ventura), MDM provisioning is insufficient. The daemon is unable to connect to the extension via XPC. Under "Full Disk Access" in System Pref^H^H^H^HSettings, an entry for our component appears but the switch is off. Turning the switch on manually at this point does not change the situation; the daemon apparently remains unable to talk to the extension. It seems as though some additional entitlement or declaration is now needed in the MDM mobileconfig to make things work under 13.x and above, but after trying a multitude of combinations, I'm at a loss. Any hints?
6
0
1.6k
Jul ’23
write() not working in OS betas for files in App Group, from app and extension
We have an App Group defined in our entitlements file so that two pieces of our software, a management GUI and a VPN extension, can write files to the same location. This is not just for regular log files. There's data we want to record which isn't appropriate for the system logs. What we're seeing on the iOS and macOS betas is that the write() file always fails, and we end up with \0s written to the file instead of the data. This is true both with the shipping versions of our applications on the App Store and with builds made with Xcode 15 and run on the devices in the debugger. Happens from both the Network Extension and the management application. Both macOS and iOS. Shipping apps and freshly built with latest tools. There's nothing we see in the Console logs that would appear to explain this. I didn't see anything in the release notes that would address this, but I could easily have missed something. Anyone else seen this?
17
0
1.6k
Aug ’23
Xcode 15b3 Swift 5.9 C++ Interop with Network Extension
Just a quick observation. I find that the NSNotification.Name NEVPNStatusDidChange is not visible when the Swift Compiler setting: C++ and Objective-C Interoperability is set to C++/Objective-C++. Simply switching between C/Objective-C and C++/Objective-C++, a successfully building app is no longer able to build with error: Type 'NSNotification.Name?' has no member 'NEVPNStatusDidChange'. The Swift code being used is: NotificationCenter.default.addObserver(self, selector: #selector(self.updateNetworkStatus(_:)), name: .NEVPNStatusDidChange, object: nil)
4
0
839
Sep ’23
Best API to intercept and modify network packets?
In some countries, the government deploys DPI (deep packet inspection) systems for censorship. These systems usually don't implement TCP completely and thus can be tricked pretty easily into allowing a connection to a blocked resource to go through, e.g. by fragmenting a ClientHello and optionally shuffling the fragments around. There exists this app for Windows: https://github.com/ValdikSS/GoodbyeDPI It uses WinDivert to intercept the network traffic and modify it as needed. I'd like to build a similar tool for macOS but I struggle to understand which of the many APIs I should use. I need two main features from the API in question: The ability to drop a packet sent by an application and send something else, e.g. several TCP fragments with the same data, instead. The ability to drop incoming packets because some DPI equipment works by sending RST before the origin server has time to respond. Ideally, I'd filter the connections by destination IP address and only work on those that deal with blocked resources, leaving the other ones to be dealt with completely by to system so that there's no needless performance regression caused by all traffic passing through my code. So which API do I use for this? NetworkExtension — which kind? BPF? Some other unix API? Or I'll have to resort to making it a kernel extension?
1
1
572
Jul ’23
How to make SimpleFirewall work as expected?
I am trying to use the example of the network extension. Now I have completed the necessary profile configuration and other content. After I try to run, a corresponding small window will pop up, but no matter how long after I click start, no matter what connection I send, it does not respond and display. I would like to know how to open a connection on the port being filtered? And then to make the SimpleFirewall work as expected?
1
0
438
Jul ’23
NWConnection not connecting with QUIC
In an iOS network extension setup as a Packet Tunnel. I am accepting packets in using NEPacketTunnelFlow and open a NWConnection up to the destination like so let parameters = .quic(alpn: []) let connection = NWConnection(to: .hostPort(host: host, port: port!), using: parameters) but my state handler is never receiving the .ready state. My NWConnection code works fine for TCP and DNS using let parameters = .tcp // OR let parameters = .udp On my NWConnection state handler I am receiving .waiting with an error of dns. I am testing quic by navigating onto the Facebook app and with wireshark intercepting the traffic I can see the DNS queries resolving I have NEDNSSettings applied to my NEPacketTunnelNetworkSettings Is my issue to do with not passing in the alpn value or is there an extra permission/setting I am missing? I have not found a value which changes the outcome at all. I have tried following [https://developer.apple.com/videos/play/wwdc2021/10094/) but no success.
4
0
1.1k
Aug ’23
How to utilize NSXPCListener/Connection for IPC on iOS
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?
5
0
753
Aug ’23
MacOS 14 beta: DNS issue when enable VPN
Our application (VPN solution) works well on macOS 13 and this issue only occurred on macOS 14 beta. This issue is: If we connect the cable to a Mac mini’s ethernet port, and enable the VPN in our application, then the Tunnel is enabled under System Settings-&gt;Network-&gt;VPN &amp; Filter, after that, the DNS stops resolving. If we use a “USB-C LAN” adapter to connect the cable to Mac mini’s USB-C port, this issue disappears. Only enable Wi-Fi can also avoid this issue. The confusion is what’s the difference between connect to Ethernet directly and use an adapter?
6
0
909
Aug ’23
Per App VPN sending traffic despite no include routes
We use Packet Tunnel under network extension framework on iOS for traffic forwarding. Deployment is per app vpn through MDM. When there is captive portal network, we clear all include routes(virtual ip is still there) so that end user can authenticate with captive portal network. But to our surprise, traffic is still coming to virtual ip. Is this expected? Shouldn't traffic go direct when there is no include routes there?
16
0
1.2k
Sep ’23
[macOS] Wanted to capture inbound DNS traffic using NETransparentProxyProvider
Hi Team, I'm trying to capture inbound traffic for DNS responses and have experimented with the following rules, but they did not work. NENetworkRule *dnsInboundTraffic = [[NENetworkRule alloc] initWithRemoteNetwork:nil remotePrefix:0 localNetwork:[NWHostEndpoint endpointWithHostname:@"0.0.0.0" port:@"53"] localPrefix:0 protocol:NENetworkRuleProtocolUDP direction:NETrafficDirectionInbound]; settings.includedNetworkRules = @[dnsInboundTraffic]; Could you please correct me if I'm making any mistakes while setting the rules?
11
0
805
Feb ’24