Networking

RSS for tag

Explore the networking protocols and technologies used by the device to connect to Wi-Fi networks, Bluetooth devices, and cellular data services.

Networking Documentation

Posts under Networking subtopic

Post

Replies

Boosts

Views

Activity

Networking Resources
General: Forums subtopic: App & System Services > Networking TN3151 Choosing the right networking API Networking Overview document — Despite the fact that this is in the archive, this is still really useful. TLS for App Developers forums post Choosing a Network Debugging Tool documentation WWDC 2019 Session 712 Advances in Networking, Part 1 — This explains the concept of constrained networking, which is Apple’s preferred solution to questions like How do I check whether I’m on Wi-Fi? TN3135 Low-level networking on watchOS TN3179 Understanding local network privacy Adapt to changing network conditions tech talk TCP and UDP ports used by Apple software products support article Understanding Also-Ran Connections forums post Extra-ordinary Networking forums post Foundation networking: Forums tags: Foundation, CFNetwork URL Loading System documentation — NSURLSession, or URLSession in Swift, is the recommended API for HTTP[S] on Apple platforms. Moving to Fewer, Larger Transfers forums post Testing Background Session Code forums post Network framework: Forums tag: Network Network framework documentation — Network framework is the recommended API for TCP, UDP, and QUIC on Apple platforms. Building a custom peer-to-peer protocol sample code (aka TicTacToe) Implementing netcat with Network Framework sample code (aka nwcat) Configuring a Wi-Fi accessory to join a network sample code Moving from Multipeer Connectivity to Network Framework forums post NWEndpoint History and Advice forums post Wi-Fi (general): How to modernize your captive network developer news post Wi-Fi Fundamentals forums post Filing a Wi-Fi Bug Report forums post Working with a Wi-Fi Accessory forums post — This is part of the Extra-ordinary Networking series. Wi-Fi (iOS): TN3111 iOS Wi-Fi API overview technote Wi-Fi Aware framework documentation WirelessInsights framework documentation iOS Network Signal Strength forums post Network Extension Resources Wi-Fi on macOS: Forums tag: Core WLAN Core WLAN framework documentation Secure networking: Forums tags: Security Apple Platform Security support document Preventing Insecure Network Connections documentation — This is all about App Transport Security (ATS). WWDC 2017 Session 701 Your Apps and Evolving Network Security Standards [1] — This is generally interesting, but the section starting at 17:40 is, AFAIK, the best information from Apple about how certificate revocation works on modern systems. WWDC 2025 Session 314 Get ahead with quantum-secure cryptography Available trusted root certificates for Apple operating systems support article Requirements for trusted certificates in iOS 13 and macOS 10.15 support article About upcoming limits on trusted certificates support article Apple’s Certificate Transparency policy support article What’s new for enterprise in iOS 18 support article — This discusses new key usage requirements. Prepare your network environment for stricter security requirements support article — This is primarily of interest to folks developing management software, for example, an MDM server. Technote 2232 HTTPS Server Trust Evaluation Technote 2326 Creating Certificates for TLS Testing QA1948 HTTPS and Test Servers Miscellaneous: More network-related forums tags: 5G, QUIC, Bonjour On FTP forums post Using the Multicast Networking Additional Capability forums post Investigating Network Latency Problems forums post Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" [1] This video is no longer available from Apple, but the URL should help you locate other sources of this info.
0
0
4.5k
2d
Understanding NEHotspotConfigurationErrorInternal
Error 8 in the NEHotspotConfigurationError domain is .internal, aka NEHotspotConfigurationErrorInternal. This error typically indicates that something went wrong in some sort of expected way, but we decided not to surface the exact cause [1]. This has come up a bunch of times before on the forums, and I have various titbits to share. To start, I want to address some specific cases: You’ll see this error if your app isn’t signed with the com.apple.developer.networking.HotspotConfiguration entitlement. To fix this, use Xcode’s Signing & Capabilities editor to add the Hotspot capability to your app. Historically developers reported a situation where once they encountered the error it would show up consistently, but then it would go away on restarting the device. If you see behaviour like that, that’s definitely a bug and I encourage you to file it as such. I have more about filing such bugs in Filing a Wi-Fi Bug Report. Of course, you have to wait to reproduce the error again before you’ll be able to file that bug, because the act of restarting cleared the issue. I’ve seen reports where such problems only occur on a specific type of device, for example, on iPhone 16 but not on earlier or later iPhones. That’s definitely something that Apple should investigate, and I recommend that you file a bug about it. If the problem is being reported by your users but you can’t reproduce it yourself, consider the various suggestions in Using a Sysdiagnose Log to Debug a Hard-to-Reproduce Problem. Assuming you’re still here (-: the next step is to determine whether the problem is specific to NEHotspotConfigurationManager or not. Try joining the accessory’s network from Settings > Wi-Fi. Does that also have problems? If so, that’s not something we can help you with here on the forums. The focus of the Apple Developer Forums is primarily to help developers with the APIs in Apple’s various platform SDKs [2]. We’re not set up to help accessory developers with Wi-Fi issues. However, there are still things you can do, as I explain in Filing a Wi-Fi Bug Report. At this point you have an error that: Persists across restarts Happens with all Apple devices You can reproduce Only affects NEHotspotConfigurationManager If that’s correct then there are a couple of things you might look at: Coerce the error to an NSError and print that. Does it reveal anything interesting? Also check the underlying error property (NSUnderlyingErrorKey) for hints. When reproducing the error, monitor the system log for log entries in the com.apple.networkextension subsystem. Do those offer any clues? Note For lots of hints and tips about the system log, see Your Friend the System Log. And finally, if you have questions about this case, feel free to start a thread here on the forums and we’ll try to help you out. Put it in the App & System Services > Networking subtopic and tag it with Network Extension. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" [1] There’s also the .unknown error. See this post for a brief summary of the difference. [2] And with Apple tools and some developer-oriented services. Revision History 2026-03-18 Added a missing entitlement bullet to the specific case list. 2026-03-17 First posted.
0
0
99
Mar ’26
Network Extension Framework Entitlements
At WWDC 2015 Apple announced two major enhancements to the Network Extension framework: Network Extension providers — These are app extensions that let you insert your code at various points within the networking stack, including: Packet tunnels via NEPacketTunnelProvider App proxies via NEAppProxyProvider Content filters via NEFilterDataProvider and NEFilterControlProvider Hotspot Helper (NEHotspotHelper) — This allows you to create an app that assists the user in navigating a hotspot (a Wi-Fi network where the user must interact with the network in order to get access to the wider Internet). Originally, using any of these facilities required authorisation from Apple. Specifically, you had to apply for, and be granted access to, a managed capability. In Nov 2016 this policy changed for Network Extension providers. Any developer can now use the Network Extension provider capability like they would any other capability. There is one exception to this rule: Network Extension app push providers, introduced by iOS 14 in 2020, still requires that Apple authorise the use of a managed capability. To apply for that, follow the link in Local push connectivity. Also, the situation with Hotspot Helpers remains the same: Using a Hotspot Helper, requires that Apple authorise that use via a managed capability. To apply for that, follow the link in Hotspot helper. IMPORTANT Pay attention to this quote from the documentation: NEHotspotHelper is only useful for hotspot integration. There are both technical and business restrictions that prevent it from being used for other tasks, such as accessory integration or Wi-Fi based location. The rest of this document answers some frequently asked questions about the Nov 2016 change. #1 — Has there been any change to the OS itself? No, this change only affects the process by which you get the capabilities you need in order to use existing Network Extension framework facilities. Previously these were managed capabilities, meaning their use was authorised by Apple. Now, except for app push providers and Hotspot Helper, you can enable the necessary capabilities using Xcode’s Signing & Capabilities editor or the Developer website. IMPORTANT Some Network Extension providers have other restrictions on their use. For example, a content filter can only be used on a supervised device. These restrictions are unchanged. See TN3134 Network Extension provider deployment for the details. #2 — How exactly do I enable the Network Extension provider capability? In the Signing & Capabilities editor, add the Network Extensions capability and then check the box that matches the provider you’re creating. In the Certificates, Identifiers & Profiles section of the Developer website, when you add or edit an App ID, you’ll see a new capability listed, Network Extensions. Enable that capability in your App ID and then regenerate the provisioning profiles based on that App ID. A newly generated profile will include the com.apple.developer.networking.networkextension entitlement in its allowlist; this is an array with an entry for each of the supported Network Extension providers. To confirm that this is present, dump the profile as shown below. $ security cms -D -i NETest.mobileprovision … <plist version="1.0"> <dict> … <key>Entitlements</key> <dict> <key>com.apple.developer.networking.networkextension</key> <array> <string>packet-tunnel-provider</string> <string>content-filter-provider</string> <string>app-proxy-provider</string> … and so on … </array> … </dict> … </dict> </plist> #3 — I normally use Xcode’s Signing & Capabilities editor to manage my entitlements. Do I have to use the Developer website for this? No. Xcode 11 and later support this capability in the Signing & Capabilities tab of the target editor (r. 28568128 ). #4 — Can I still use Xcode’s “Automatically manage signing” option? Yes. Once you modify your App ID to add the Network Extension provider capability, Xcode’s automatic code signing support will include the entitlement in the allowlist of any profiles that it generates based on that App ID. #5 — What should I do if I previously applied for the Network Extension provider managed capability and I’m still waiting for a reply? Consider your current application cancelled, and use the new process described above. #6 — What should I do if I previously applied for the Hotspot Helper managed capability and I’m still waiting for a reply? Apple will continue to process Hotspot Helper managed capability requests and respond to you in due course. #7 — What if I previously applied for both Network Extension provider and Hotspot Helper managed capabilities? Apple will ignore your request for the Network Extension provider managed capability and process it as if you’d only asked for the Hotspot Helper managed capability. #8 — On the Mac, can Developer ID apps host Network Extension providers? Yes, but there are some caveats: This only works on macOS 10.15 or later. Your Network Extension provider must be packaged as a system extension, not an app extension. You must use the *-systemextension values for the Network Extension entitlement (com.apple.developer.networking.networkextension). For more on this, see Exporting a Developer ID Network Extension. #9 — After moving to the new process, my app no longer has access to the com.apple.managed.vpn.shared keychain access group. How can I regain that access? Access to this keychain access group requires another managed capability. If you need that, please open a DTS code-level support request and we’ll take things from there. IMPORTANT This capability is only necessary if your VPN supports configuration via a configuration profile and needs to access credentials from that profile (as discussed in the Profile Configuration section of the NETunnelProviderManager Reference). Many VPN apps don’t need this facility. If you were previously granted the Network Extension managed capability (via the process in place before Nov 2016), make sure you mention that; restoring your access to the com.apple.managed.vpn.shared keychain access group should be straightforward in that case. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Revision History 2025-11-11 Removed the discussion of TSI assets because those are no longer a thing. 2025-09-12 Adopted the code-level support request terminology. Made other minor editorial changes. 2023-01-11 Added a discussion of Network Extension app push providers. Added a link to Exporting a Developer ID Network Extension. Added a link to TN3134. Made significant editorial changes. 2020-02-27 Fixed the formatting. Updated FAQ#3. Made minor editorial changes. 2020-02-16 Updated FAQ#8 to account for recent changes. Updated FAQ#3 to account for recent Xcode changes. Made other editorial changes. 2016-01-25 Added FAQ#9. 2016-01-6 Added FAQ#8. 2016-11-11 Added FAQ#5, FAQ#6 and FAQ#7. 2016-11-11 First posted.
0
0
23k
Nov ’25
Unable to detect Network Extension configuration change while pushing MDM profile
My team is developing an enterprise VPN application that needs to respond to Mobile Device Management (MDM) profile installations and removals in real-time. Our app uses the NetworkExtension framework and needs to update the UI immediately when VPN configurations are added or removed via MDM. We are currently observing NEVPNConfigurationChangeNotification to detect VPN configuration changes: While NEVPNConfigurationChangeNotification fires reliably when users manually remove VPN profiles through Settings > General > VPN & Device Management, it appears to have inconsistent behavior when MDM profiles containing VPN configurations are installed programmatically via MDM systems. STEPS TO REPRODUCE From MDM Admin Console: Deploy a new VPN profile to the test device On Device: Wait for MDM profile installation (usually silent, no user interaction required) Check Device Settings: Go to Settings > General > VPN & Device Management to confirm profile is installed Return to App: Check if the UI shows the new VPN profile
1
0
224
Feb ’26
App occassionally crashing while connecting to public wifi
We are using the [NEHotspotHelper supportedNetworkInterfaces] to get the Wi-Fi interface in our app, but it occasionally crashes on some devices with the following stack trace: 0 CaptiveNetwork 0x0000000221d87a4c ServerConnectionGetHandlerQueue + 0 (ServerConnection.c:509) 1 CaptiveNetwork 0x0000000221d8577c CNPluginCopySupportedInterfaces + 180 (CNPlugin.c:457) 2 NetworkExtension 0x00000001b0446618 +[NEHotspotHelper supportedNetworkInterfaces] + 32 (NEHotspotHelper.m:563) It seems like the crash is happening on apple's api of supportedNetworkInterfaces. We would like to understand the cause of the crash.
2
0
104
May ’25
Working with a Wi-Fi Accessory
For important background information, read Extra-ordinary Networking before reading this. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Working with a Wi-Fi Accessory Building an app that works with a Wi-Fi accessory presents specific challenges. This post discusses those challenges and some recommendations for how to address them. Note While my focus here is iOS, much of the info in this post applies to all Apple platforms. IMPORTANT iOS 18 introduced AccessorySetupKit, a framework to simplify the discovery and configuration of an accessory. I’m not fully up to speed on that framework myself, but I encourage you to watch WWDC 2024 Session 10203 Meet AccessorySetupKit and read the framework documentation. IMPORTANT iOS 26 introduced WiFiAware, a framework for setting up communication with Wi-Fi Aware accessories. Wi-Fi Aware is an industry standard to securely discover, pair, and communicate with nearby devices. This is especially useful for stand-alone accessories (defined below). For more on this framework, watch WWDC 2025 Session 228 Supercharge device connectivity with Wi-Fi Aware and read the framework documentation. For information on how to create a Wi-Fi Aware accessory that works with iPhone, go to Developer > Accessories, download Accessory Design Guidelines for Apple Devices, and review the Wi-Fi Aware chapter. Accessory Categories I classify Wi-Fi accessories into three different categories. A bound accessory is ultimately intended to join the user’s Wi-Fi network. It may publish its own Wi-Fi network during the setup process, but the goal of that process is to get the accessory on to the existing network. Once that’s done, your app interacts with the accessory using ordinary networking APIs. An example of a bound accessory is a Wi-Fi capable printer. A stand-alone accessory publishes a Wi-Fi network at all times. An iOS device joins that network so that your app can interact with it. The accessory never provides access to the wider Internet. An example of a stand-alone accessory is a video camera that users take with them into the field. You might want to write an app that joins the camera’s network and downloads footage from it. A gateway accessory is one that publishes a Wi-Fi network that provides access to the wider Internet. Your app might need to interact with the accessory during the setup process, but after that it’s useful as is. An example of this is a Wi-Fi to WWAN gateway. Not all accessories fall neatly into these categories. Indeed, some accessories might fit into multiple categories, or transition between categories. Still, I’ve found these categories to be helpful when discussing various accessory integration challenges. Do You Control the Firmware? The key question here is Do you control the accessory’s firmware? If so, you have a bunch of extra options that will make your life easier. If not, you have to adapt to whatever the accessory’s current firmware does. Simple Improvements If you do control the firmware, I strongly encourage you to: Support IPv6 Implement Bonjour [1] These two things are quite easy to do — most embedded platforms support them directly, so it’s just a question of turning them on — and they will make your life significantly easier: Link-local addresses are intrinsic to IPv6, and IPv6 is intrinsic to Apple platforms. If your accessory supports IPv6, you’ll always be able to communicate with it, regardless of how messed up the IPv4 configuration gets. Similarly, if you support Bonjour, you’ll always be able to find your accessory on the network. [1] Bonjour is an Apple term for three Internet standards: RFC 3927 Dynamic Configuration of IPv4 Link-Local Addresses RFC 6762 Multicast DNS RFC 6763 DNS-Based Service Discovery WAC For a bound accessory, support Wireless Accessory Configuration (WAC). This is a relatively big ask — supporting WAC requires you to join the MFi Program — but it has some huge benefits: You don’t need to write an app to configure your accessory. The user will be able to do it directly from Settings. If you do write an app, you can use the EAWiFiUnconfiguredAccessoryBrowser class to simplify your configuration process. HomeKit For a bound accessory that works in the user’s home, consider supporting HomeKit. This yields the same onboarding benefits as WAC, and many other benefits as well. Also, you can get started with the HomeKit Open Source Accessory Development Kit (ADK). Bluetooth LE If your accessory supports Bluetooth LE, think about how you can use that to improve your app’s user experience. For an example of that, see SSID Scanning, below. Claiming the Default Route, Or Not? If your accessory publishes a Wi-Fi network, a key design decision is whether to stand up enough infrastructure for an iOS device to make it the default route. IMPORTANT To learn more about how iOS makes the decision to switch the default route, see The iOS Wi-Fi Lifecycle and Network Interface Concepts. This decision has significant implications. If the accessory’s network becomes the default route, most network connections from iOS will be routed to your accessory. If it doesn’t provide a path to the wider Internet, those connections will fail. That includes connections made by your own app. Note It’s possible to get around this by forcing your network connections to run over WWAN. See Binding to an Interface in Network Interface Techniques and Running an HTTP Request over WWAN. Of course, this only works if the user has WWAN. It won’t help most iPad users, for example. OTOH, if your accessory’s network doesn’t become the default route, you’ll see other issues. iOS will not auto-join such a network so, if the user locks their device, they’ll have to manually join the network again. In my experience a lot of accessories choose to become the default route in situations where they shouldn’t. For example, a bound accessory is never going to be able to provide a path to the wider Internet so it probably shouldn’t become the default route. However, there are cases where it absolutely makes sense, the most obvious being that of a gateway accessory. Acting as a Captive Network, or Not? If your accessory becomes the default route you must then decide whether to act like a captive network or not. IMPORTANT To learn more about how iOS determines whether a network is captive, see The iOS Wi-Fi Lifecycle. For bound and stand-alone accessories, becoming a captive network is generally a bad idea. When the user joins your network, the captive network UI comes up and they have to successfully complete it to stay on the network. If they cancel out, iOS will leave the network. That makes it hard for the user to run your app while their iOS device is on your accessory’s network. In contrast, it’s more reasonable for a gateway accessory to act as a captive network. SSID Scanning Many developers think that TN3111 iOS Wi-Fi API overview is lying when it says: iOS does not have a general-purpose API for Wi-Fi scanning It is not. Many developers think that the Hotspot Helper API is a panacea that will fix all their Wi-Fi accessory integration issues, if only they could get the entitlement to use it. It will not. Note this comment in the official docs: NEHotspotHelper is only useful for hotspot integration. There are both technical and business restrictions that prevent it from being used for other tasks, such as accessory integration or Wi-Fi based location. Even if you had the entitlement you would run into these technical restrictions. The API was specifically designed to support hotspot navigation — in this context hotspots are “Wi-Fi networks where the user must interact with the network to gain access to the wider Internet” — and it does not give you access to on-demand real-time Wi-Fi scan results. Many developers look at another developer’s app, see that it’s displaying real-time Wi-Fi scan results, and think there’s some special deal with Apple that’ll make that work. There is not. In reality, Wi-Fi accessory developers have come up with a variety of creative approaches for this, including: If you have a bound accessory, you might add WAC support, which makes this whole issue go away. In many cases, you can avoid the need for Wi-Fi scan results by adopting AccessorySetupKit. You might build your accessory with a barcode containing the info required to join its network, and scan that from your app. This is the premise behind the Configuring a Wi-Fi Accessory to Join the User’s Network sample code. You might configure all your accessories to have a common SSID prefix, and then take advantage of the prefix support in NEHotspotConfigurationManager. See Programmatically Joining a Network, below. You might have your app talk to your accessory via some other means, like Bluetooth LE, and have the accessory scan for Wi-Fi networks and return the results. Programmatically Joining a Network Network Extension framework has an API, NEHotspotConfigurationManager, to programmatically join a network, either temporarily or as a known network that supports auto-join. For the details, see Wi-Fi Configuration. One feature that’s particularly useful is it’s prefix support, allowing you to create a configuration that’ll join any network with a specific prefix. See the init(ssidPrefix:) initialiser for the details. For examples of how to use this API, see: Configuring a Wi-Fi Accessory to Join the User’s Network — It shows all the steps for one approach for getting a non-WAC bound accessory on to the user’s network. NEHotspotConfiguration Sample — Use this to explore the API in general. Secure Communication Users expect all network communication to be done securely. For some ideas on how to set up a secure connection to an accessory, see TLS For Accessory Developers. Revision History 2025-11-05 Added a link to the Accessory Design Guidelines for Apple Devices. 2025-06-19 Added a preliminary discussion of Wi-Fi Aware. 2024-09-12 Improved the discussion of AccessorySetupKit. 2024-07-16 Added a preliminary discussion of AccessorySetupKit. 2023-10-11 Added the HomeKit section. Fixed the link in Secure Communication to point to TLS For Accessory Developers. 2023-07-23 First posted.
0
0
1.9k
Nov ’25
test NEAppProxyProvider without MDM?
This discussion is for iOS/iPadOS. I've written an NEAppProxyProvider network extension. I'd like to test it. I thought that using the "NETestAppMapping" dictionary was a way to get there, but when I try to instantiate an NEAppProxyProviderManager to try to install stuff, the console tells me "must be MDM managed" and I get nowhere. So can someone tell me, can I at least test the idea without needing to first get MDM going? I'd like to know if how I'm approaching the core problem even makes sense. My custom application needs to stream video, via the SRT protocol, to some place like youtube or castr. The problem is that in the environment we are in (big convention centers), our devices are on a LAN, but the connection from the LAN out to the rest of the world just sucks. Surprisingly, cellular has better performance. So I am trying to do the perverse thing of forcing traffix that is NOT local to go out over cellular. And traffic that is completely local (i.e. talking to a purely local server/other devices on the LAN) happens over ethernet. [To simplify things, wifi is not connected.] Is an app proxy the right tool for this? Is there any other tool? Unfortunately, I cannot rewrite the code to force everything through Apple's Network framework, which is the one place I know we can say "use cellular." [E.g. URLSession() has absolutely no way of forcing cellular, and even so, the low level streaming library I use is written with raw sockets, and its not feasible for me to rewrite it.] Any other suggestions of how to accomplish this "send non-local traffic to cellular, all local traffic out over ethernet" gratefully welcomed!
9
0
171
Mar ’26
A Peek Behind the NECP Curtain
From time to time the subject of NECP grows up, both here on DevForums and in DTS cases. I’ve posted about this before but I wanted to collect those tidbits into single coherent post. If you have questions or comments, start a new thread in the App & System Services > Networking subtopic and tag it with Network Extension. That way I’ll be sure to see it go by. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" A Peek Behind the NECP Curtain NECP stands for Network Extension Control Protocol. It’s a subsystem within the Apple networking stack that controls which programs have access to which network interfaces. It’s vitally important to the Network Extension subsystem, hence the name, but it’s used in many different places. Indeed, a very familiar example of its use is the Settings > Mobile Data [1] user interface on iOS. NECP has no explicit API, although there are APIs that are offer some insight into its state. Continuing the Settings > Mobile Data example above, there is a little-known API, CTCellularData in the Core Telephony framework, that returns whether your app has access to WWAN. Despite having no API, NECP is still relevant to developers. The Settings > Mobile Data example is one place where it affects app developers but it’s most important for Network Extension (NE) developers. A key use case for NECP is to prevent VPN loops. When starting an NE provider, the system configures the NECP policy for the NE provider’s process to prevent it from using a VPN interface. This means that you can safely open a network connection inside your VPN provider without having to worry about its traffic being accidentally routed back to you. This is why, for example, an NE packet tunnel provider can use any networking API it wants, including BSD Sockets, to run its connection without fear of creating a VPN loop [1]. One place that NECP shows up regularly is the system log. Next time you see a system log entry like this: type: debug time: 15:02:54.817903+0000 process: Mail subsystem: com.apple.network category: connection message: nw_protocol_socket_set_necp_attributes [C723.1.1:1] setsockopt 39 SO_NECP_ATTRIBUTES … you’ll at least know what the necp means (-: Finally, a lot of NECP infrastructure is in the Darwin open source. As with all things in Darwin, it’s fine to poke around and see how your favourite feature works, but do not incorporate any information you find into your product. Stuff you uncover by looking in Darwin is not considered API. [1] Settings > Cellular Data if you speak American (-: [2] Network Extension providers can call the createTCPConnection(to:enableTLS:tlsParameters:delegate:) method to create an NWTCPConnection [3] that doesn’t run through the tunnel. You can use that if it’s convenient but you don’t need to use it. [3] NWTCPConnection is now deprecated, but there are non-deprecated equivalents. For the full story, see NWEndpoint History and Advice. Revision History 2025-12-12 Replaced “macOS networking stack” with “Apple networking stack” to avoid giving the impression that this is all about macOS. Added a link to NWEndpoint History and Advice. Made other minor editorial changes. 2023-02-27 First posted.
0
0
2.7k
Dec ’25
Thread topology data: no API path for parent-child relationships
I'm building a HomeKit app that discovers Thread devices and visualizes the mesh topology. I can detect device roles (Router vs End Device via characteristic 0x0703) and identify Border Routers (via _meshcop._udp), but I cannot determine which Router is the parent of a given End Device. Any Thread device can act as a Router (a Nanoleaf bulb, an Eve plug, not just HomePods), and End Devices attach to these Routers as children. That parent-child relationship is what I'm trying to map, but there's no RLOC16, neighbor table, or parent identifier exposed through any available API. I've tested every path I can find. Here's what I've tried on a network with 44 Thread devices and 6 Border Routers: What works (partially) HAP Thread Management Service (0x0701) gives me the device role from characteristic 0x0703, the OpenThread version from 0x0706, and node capabilities from 0x0702. That's the complete set of characteristics on that service. None of them contain RLOC16, parent Router, or neighbor data. This service also only exists on HAP-native Thread devices. My 20 Matter-over-Thread devices (Aqara, Eve Door, SmartWings, Onvis S4) don't have it at all. MeshCoP Bonjour (_meshcop._udp) identifies Border Routers and the network name/Extended PAN ID. No topology data about other mesh nodes. What doesn't work ThreadNetwork framework (THClient) - retrieveAllCredentials() returns error Code 3 because the app can't access credentials stored by Apple Home. Even if it worked, THCredentials only contains network config (name, PAN ID, channel), not topology. Direct CoAP queries - Border Routers don't route traffic from WiFi to Thread management ports. Mesh-local addresses aren't reachable. No Thread NWInterface in Network.framework. Network.framework - No visibility into the Thread mesh from the WiFi side. The only remaining path I can see (but it's not practical) Matter cluster 0x0035 (Thread Network Diagnostics) appears to have exactly what I need: RLOC16, NeighborTable with isChild boolean, RouteTable. I haven't implemented this because it requires commissioning each device individually onto my app's own Matter fabric via Multi-Admin. That's 21 separate user-initiated pairing actions on my network. I can't ask end users to do that. The core issue Every Thread Router (whether it's a HomePod acting as a Border Router or a Nanoleaf bulb acting as a mesh Router) knows its own children and neighbors. The Border Routers also maintain route tables covering the mesh backbone. This data exists on the user's own devices but none of it is exposed to third-party apps. Even something minimal would help. HMAccessory already exposes matterNodeID as a cross-protocol identifier. Exposing RLOC16 the same way would be enough, since parent-child relationships are encoded in the address itself (ParentRLOC = ChildRLOC & 0xFC00). Has anyone found another approach I'm missing? Thanks in advance for any pointers.
1
0
258
Feb ’26
Extra-ordinary Networking
Most apps perform ordinary network operations, like fetching an HTTP resource with URLSession and opening a TCP connection to a mail server with Network framework. These operations are not without their challenges, but they’re the well-trodden path. If your app performs ordinary networking, see TN3151 Choosing the right networking API for recommendations as to where to start. Some apps have extra-ordinary networking requirements. For example, apps that: Help the user configure a Wi-Fi accessory Require a connection to run over a specific interface Listen for incoming connections Building such an app is tricky because: Networking is hard in general. Apple devices support very dynamic networking, and your app has to work well in whatever environment it’s running in. Documentation for the APIs you need is tucked away in man pages and doc comments. In many cases you have to assemble these APIs in creative ways. If you’re developing an app with extra-ordinary networking requirements, this post is for you. Note If you have questions or comments about any of the topics discussed here, put them in a new thread here on DevForums. Make sure I see it by putting it in the App & System Services > Networking area. And feel free to add tags appropriate to the specific technology you’re using, like Foundation, CFNetwork, Network, or Network Extension. Links, Links, and More Links Each topic is covered in a separate post: The iOS Wi-Fi Lifecycle describes how iOS joins and leaves Wi-Fi networks. Understanding this is especially important if you’re building an app that works with a Wi-Fi accessory. Network Interface Concepts explains how Apple platforms manage network interfaces. If you’ve got this far, you definitely want to read this. Network Interface Techniques offers a high-level overview of some of the more common techniques you need when working with network interfaces. Network Interface APIs describes APIs and core techniques for working with network interfaces. It’s referenced by many other posts. Running an HTTP Request over WWAN explains why most apps should not force an HTTP request to run over WWAN, what they should do instead, and what to do if you really need that behaviour. If you’re building an iOS app with an embedded network server, see Showing Connection Information in an iOS Server for details on how to get the information to show to your user so they can connect to your server. Many folks run into trouble when they try to find the device’s IP address, or other seemingly simple things, like the name of the Wi-Fi interface. Don’t Try to Get the Device’s IP Address explains why these problems are hard, and offers alternative approaches that function correctly in all network environments. Similarly, folks also run into trouble when trying to get the host name. On Host Names explains why that’s more complex than you might think. If you’re working with broadcasts or multicasts, see Broadcasts and Multicasts, Hints and Tips. If you’re building an app that works with a Wi-Fi accessory, see Working with a Wi-Fi Accessory. If you’re trying to gather network interface statistics, see Network Interface Statistics. There are also some posts that are not part of this series but likely to be of interest if you’re working in this space: TN3179 Understanding local network privacy discusses the local network privacy feature. Calling BSD Sockets from Swift does what it says on the tin, that is, explains how to call BSD Sockets from Swift. When doing weird things with the network, you often find yourself having to use BSD Sockets, and that API is not easy to call from Swift. The code therein is primarily for the benefit of test projects, oh, and DevForums posts like these. TN3111 iOS Wi-Fi API overview is a critical resource if you’re doing Wi-Fi specific stuff on iOS. TLS For Accessory Developers tackles the tricky topic of how to communicate securely with a network-based accessory. A Peek Behind the NECP Curtain discusses NECP, a subsystem that control which programs have access to which network interfaces. Networking Resources has links to many other useful resources. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Revision History 2025-07-31 Added a link to A Peek Behind the NECP Curtain. 2025-03-28 Added a link to On Host Names. 2025-01-16 Added a link to Broadcasts and Multicasts, Hints and Tips. Updated the local network privacy link to point to TN3179. Made other minor editorial changes. 2024-04-30 Added a link to Network Interface Statistics. 2023-09-14 Added a link to TLS For Accessory Developers. 2023-07-23 First posted.
0
0
5.8k
Jul ’25
TCP socket disconnection with EBROKENPIPE during file copy of signed app bundle
We are developing a client server application using TCP bsd sockets. When our client is connected to the server, copying another client .app bundle from a file server on the same machine (using Finder or terminal using cp), occasionally causes the first client to disconnect. The client receives an EBROKENPIPE error when attempting to write to its socket. In the Console, the following message appears just before the disconnection: necp_socket_find_policy_match: Marking socket in state 258 as defunct This issue seems to occur only when copying an .app bundle signed with the same TeamIdentifier as the running client. Copying arbitrary files or bundles with a different TeamIdentifier does not trigger the problem. We are running on macOS 15.5. The issue appears specific to macOS 15 and was not observed on earlier versions. Any help or pointers would be greatly appreciated!
2
0
225
Jul ’25
Unable to update app with PacketTunnelProvider running
Hi there, I am working on an app that configures a PacketTunnelProvider to establish a VPN connection. Unfortunately, while a VPN connection is established, I am unable to update the app via testflight. Downloading other app updates works fine. I noticed that after I receive the alert that updating failed, the vpn badge appears at the top of my screen (the same ux that occurs when the connection is first established). So it's almost like it tried to close the tunnel, and seeing that the app update failed it restablishes the tunnel. I am unsure of why I would not be able to update my app. Maybe stopTunnel is not being called with NEProviderStopReason.appUpdate?
1
0
83
Jun ’25
Recommended alternatives to leaf cert pinning to prevent MITM
Hey there Are there any recommendations or guidance for apps on alternatives to certificate pinning to secure their device network traffic? I want to move away from the overhead and risk associated with rotating certificates when using leaf pinning. However, I also don't want people to be able to perform a MITM attack easily using something like Charles Proxy with a self‑signed certificate added to the trust store. My understanding is that an app cannot distinguish between user‑trusted certificates and system‑trusted certificates in the trust store, so it cannot block traffic that uses user‑trusted certificates.
0
0
59
Jan ’26
IOS app on MacOS 15 local network access
Our app is developed for iOS, but some users also run it on macOS (as an iOS app via Apple Silicon). The app requires local network permission, which works perfectly on iOS. Previously, the connection also worked fine on macOS, but since the recent macOS update, the app can no longer connect to our device. Additionally, our app on macOS doesn't prompt for local network permission at all, whereas it does on iOS. Is this a known issue with iOS apps running on macOS? Has anyone else experienced this problem, or is there a workaround? Any help would be appreciated!
9
0
971
Oct ’25
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. Put it in the App & System Services > Networking and tag it with Network Extension. 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. On the other hand, the build / run / debug cycle is simpler on iOS than it is on macOS, especially when you’re building a system extension on macOS. Even if your ultimate goal is to build a macOS-only system extension, if your provider type supports app extension packaging then you should consider whether it makes sense to adopt that packaging just for to speed up your development. If you do decide to try this, be aware that a packaging change can affect your code. See Network Extension Provider Packaging for more on that. [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 2026-04-01 Added a suggestion about provider packaging to the General Hints and Tips section. 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
4.4k
Apr ’26
NSURLSession’s Resume Rate Limiter
IMPORTANT The resume rate limiter is now covered by the official documentation. See Use background sessions efficiently within Downloading files in the background. So, the following is here purely for historical perspective. NSURLSession’s background session support on iOS includes a resume rate limiter. This limiter exists to prevent apps from abusing the background session support in order to run continuously in the background. It works as follows: nsurlsessiond (the daemon that does all the background session work) maintains a delay value for your app. It doubles that delay every time it resumes (or relaunches) your app. It resets that delay to 0 when the user brings your app to the front. It also resets the delay to 0 if the delay period elapses without it having resumed your app. When your app creates a new task while it is in the background, the task does not start until that delay has expired. To understand the impact of this, consider what happens when you download 10 resources. If you pass them to the background session all at once, you see something like this: Your app creates tasks 1 through 10 in the background session. nsurlsessiond starts working on the first few tasks. As tasks complete, nsurlsessiond starts working on subsequent ones. Eventually all the tasks complete and nsurlsessiond resumes your app. Now consider what happens if you only schedule one task at a time: Your app creates task 1. nsurlsessiond starts working on it. When it completes, nsurlsessiond resumes your app. Your app creates task 2. nsurlsessiond delays the start of task 2 a little bit. nsurlsessiond starts working on task 2. When it completes, nsurlsessiond resumes your app. Your app creates task 3. nsurlsessiond delays the start of task 3 by double the previous amount. nsurlsessiond starts working on task 3. When it completes, nsurlsessiond resumes your app. Steps 8 through 11 repeat, and each time the delay doubles. Eventually the delay gets so large that it looks like your app has stopped making progress. If you have a lot of tasks to run then you can mitigate this problem by starting tasks in batches. That is, rather than start just one task in step 1, you would start 100. This only helps up to a point. If you have thousands of tasks to run, you will eventually start seeing serious delays. In that case it’s much better to change your design to use fewer, larger transfers. Note All of the above applies to iOS 8 and later. Things worked differently in iOS 7. There’s a post on DevForums that explains the older approach. Finally, keep in mind that there may be other reasons for your task not starting. Specifically, if the task is flagged as discretionary (because you set the discretionary flag when creating the task’s session or because the task was started while your app was in the background), the task may be delayed for other reasons (low power, lack of Wi-Fi, and so on). Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" (r. 22323366)
0
0
14k
Jul ’25
OSSystemExtension activation fails with code=4 and sysextd "no policy, cannot allow apps outside /Applications" even when host app is in /Applications
Summary We are activating a Network Extension system extension (filter-data) from a signed and notarized macOS app. Activation consistently fails with: OSSystemExtensionErrorDomain code=4 Extension not found in App bundle. Unable to find any matched extension with identifier: com.seaskylight.yksmacos.ExamNetFilter.data At the same time, sysextd logs: no policy, cannot allow apps outside /Applications However, our host app and executable real paths are already under /Applications, and the extension bundle physically exists in the expected app bundle location. Environment macOS: Darwin 25.4.0 Host app: /Applications/xxx.app Host bundle id: com.seaskylight.yksmacos System extension bundle id: com.seaskylight.yksmacos.ExamNetFilter.data Team ID: BVU65MZFLK Device management: Enrolled via DEP: No MDM enrollment: No Reproduction Steps Install host app to /Applications. Launch host app via Finder or: open -a "/Applications/xxx.app" Trigger OSSystemExtensionRequest activationRequestForExtension for: com.seaskylight.yksmacos.ExamNetFilter.data Observe failure callback (code=4). Collect logs: log show --last 2m --style compact --info --debug --predicate 'process == "sysextd"' systemextensionsctl list (shows 0 extension(s)) Observed Results sysextd client activation request for com.seaskylight.yksmacos.ExamNetFilter.data attempting to realize extension with identifier com.seaskylight.yksmacos.ExamNetFilter.data no policy, cannot allow apps outside /Applications App-side diagnostics (captured at failure) pid=3249 bundlePath=/Applications/xxx.app bundlePathReal=/Applications/xxx.app execPath=/Applications/xxx.app/Contents/MacOS/xxx execPathReal=/Applications/xxx.app/Contents/MacOS/xxx extPath=/Applications/xxx.app/Contents/Library/SystemExtensions/ExamNetFilterData.systemextension extExists=true runningFromHelper=false Error callback NSError{domain=OSSystemExtensionErrorDomain code=4 desc=Extension not found in App bundle...} Additional Validation We reproduced the same failure using a minimal native host app (SysExtProbe) in /Applications that only submits the activation request for the same extension identifier. It also fails with OSSystemExtensionErrorDomain code=4, indicating this is not specific to Electron app logic. Signing / Packaging Notes Host app and system extension are signed with the same Team ID (BVU65MZFLK). System extension bundle exists under: /Applications/xxx.app/Contents/Library/SystemExtensions/ExamNetFilterData.systemextension Extension Info.plist contains bundle id: com.seaskylight.yksmacos.ExamNetFilter.data Host app includes NSSystemExtensionUsageDescription. Questions for DTS In non-MDM personal-device scenarios, what exact conditions trigger sysextd to emit: no policy, cannot allow apps outside /Applications even when both bundlePath and realpath are in /Applications? Can code=4 (“Extension not found in App bundle”) be returned for policy/state reasons even when extension bundle is present and identifier matches? Are there known sysextd policy/cache states that cause this behavior, and what is the recommended recovery procedure?
2
0
129
6d
DeviceDiscoveryUI notification for iPad says iPhone?
I have been polishing an app that connects and communicates between a tvOS app I created and a iPadOS app that I also created. Connection works fantastic! However, for some reason when the user selects the button to open the DevicePicker provided by this API and then selects a iPad device the notification that comes across the the iPad reads, "Connect your Apple TV to "AppName" on this iPhone. Is this a bug or am I missing some configuration in maybe Info.plist or a modifier I need to add the DevicePicker for it to communicate the proper device identification? I have everything setup in both app Info.plist files to connect and work fine, but the notification saying iPhone on an iPad is sadly a small detail I would love to change. So...not sure if I found a bug or if I am missing something.
2
0
450
May ’25
iOS Resumable Uploads Troubles
I am referencing: https://developer.apple.com/documentation/foundation/pausing-and-resuming-uploads Specifically: You can’t resume all uploads. The server must support the latest resumable upload protocol draft from the HTTP Working Group at the IETF. Also, uploads that use a background configuration handle resumption automatically, so manual resuming is only needed for non-background uploads. I have control over both the app and the server, and can't seem to get it to work automatically with a background url session. In other words, making multiple requests to get the offset then upload, easy but I am trying to leverage this background configuration resume OS magic. So anyone know what spec version does the server/client need to implement? The docs reference version 3, however the standard is now at like 11. Of course, I am trying out 3. Does anyone know how exactly this resume is implemented in iOS, and what exactly it takes care of? I assumed that I can just POST to a generic end point, say /files, then the OS receives a 104 Location, and saves that. If the upload is interrupted, when the OS resumes the upload, it has enough information to figure out how to resume from the exact offset, either by making a HEAD request to get the offset, or handle a 409. I am assuming it does this, as if it doesn't, the 'uploads that use a background configuration handle resumption automatically' is useless, if it just restarts from 0. Note, of course making individual POST/HEAD/PATCH requests manually works, but at that point I'm not really leveraging any OS auto-magic, and am just consuming an API that could really implement any spec. This won't work in the background, as the OS seems to disallow random HTTP requests when it wakes the app for URLSession background resumes. As of right now, I have it 'partially' working, insofar as the app does receive the 104 didReceiveInformationalResponse url delegate call, however it seems to then hang; it stops sending bytes, seemingly when the 104 is received. However, the request does not complete. In other words, it doesn't seem to receive a client timeout or otherwise indicate the request has finished. Right now, I am starting a single request, POSTing to a /files end point, i.e. I am not getting the location first, then PATCHing to that, as if I do that, the OS 'automatic' resuming fails with a 409, i.e. it doesn't seem to make a HEAD request and/or use the 409 offset correction then continue with the PATCH. Any idea what could be going on?
1
0
223
Mar ’26
FYI: Network System extension, macOS update issue, loss of networking
This is just an FYI in case someone else runs into this problem. This afternoon (12 Dec 2025), I updated to macOS 26.2 and lost my network. The System Settings' Wi-Fi light was green and said it was connected, but traceroute showed "No route to host". I turned Wi-Fi on & off. I rebooted the Mac. I rebooted the eero network. I switched to tethering to my iPhone. I switched to physical ethernet cable. Nothing worked. Then I remembered I had a beta of an app with a network system extension that was distributed through TestFlight. I deleted the app, and networking came right back. I had this same problem ~2 years ago. Same story: app with network system extension + TestFlight + macOS update = lost network. (My TestFlight build might have expired, but I'm not certain) I don't know if anyone else has had this problem, but I thought I'd share this in case it helps.
2
0
291
Jan ’26
Networking Resources
General: Forums subtopic: App & System Services > Networking TN3151 Choosing the right networking API Networking Overview document — Despite the fact that this is in the archive, this is still really useful. TLS for App Developers forums post Choosing a Network Debugging Tool documentation WWDC 2019 Session 712 Advances in Networking, Part 1 — This explains the concept of constrained networking, which is Apple’s preferred solution to questions like How do I check whether I’m on Wi-Fi? TN3135 Low-level networking on watchOS TN3179 Understanding local network privacy Adapt to changing network conditions tech talk TCP and UDP ports used by Apple software products support article Understanding Also-Ran Connections forums post Extra-ordinary Networking forums post Foundation networking: Forums tags: Foundation, CFNetwork URL Loading System documentation — NSURLSession, or URLSession in Swift, is the recommended API for HTTP[S] on Apple platforms. Moving to Fewer, Larger Transfers forums post Testing Background Session Code forums post Network framework: Forums tag: Network Network framework documentation — Network framework is the recommended API for TCP, UDP, and QUIC on Apple platforms. Building a custom peer-to-peer protocol sample code (aka TicTacToe) Implementing netcat with Network Framework sample code (aka nwcat) Configuring a Wi-Fi accessory to join a network sample code Moving from Multipeer Connectivity to Network Framework forums post NWEndpoint History and Advice forums post Wi-Fi (general): How to modernize your captive network developer news post Wi-Fi Fundamentals forums post Filing a Wi-Fi Bug Report forums post Working with a Wi-Fi Accessory forums post — This is part of the Extra-ordinary Networking series. Wi-Fi (iOS): TN3111 iOS Wi-Fi API overview technote Wi-Fi Aware framework documentation WirelessInsights framework documentation iOS Network Signal Strength forums post Network Extension Resources Wi-Fi on macOS: Forums tag: Core WLAN Core WLAN framework documentation Secure networking: Forums tags: Security Apple Platform Security support document Preventing Insecure Network Connections documentation — This is all about App Transport Security (ATS). WWDC 2017 Session 701 Your Apps and Evolving Network Security Standards [1] — This is generally interesting, but the section starting at 17:40 is, AFAIK, the best information from Apple about how certificate revocation works on modern systems. WWDC 2025 Session 314 Get ahead with quantum-secure cryptography Available trusted root certificates for Apple operating systems support article Requirements for trusted certificates in iOS 13 and macOS 10.15 support article About upcoming limits on trusted certificates support article Apple’s Certificate Transparency policy support article What’s new for enterprise in iOS 18 support article — This discusses new key usage requirements. Prepare your network environment for stricter security requirements support article — This is primarily of interest to folks developing management software, for example, an MDM server. Technote 2232 HTTPS Server Trust Evaluation Technote 2326 Creating Certificates for TLS Testing QA1948 HTTPS and Test Servers Miscellaneous: More network-related forums tags: 5G, QUIC, Bonjour On FTP forums post Using the Multicast Networking Additional Capability forums post Investigating Network Latency Problems forums post Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" [1] This video is no longer available from Apple, but the URL should help you locate other sources of this info.
Replies
0
Boosts
0
Views
4.5k
Activity
2d
Understanding NEHotspotConfigurationErrorInternal
Error 8 in the NEHotspotConfigurationError domain is .internal, aka NEHotspotConfigurationErrorInternal. This error typically indicates that something went wrong in some sort of expected way, but we decided not to surface the exact cause [1]. This has come up a bunch of times before on the forums, and I have various titbits to share. To start, I want to address some specific cases: You’ll see this error if your app isn’t signed with the com.apple.developer.networking.HotspotConfiguration entitlement. To fix this, use Xcode’s Signing & Capabilities editor to add the Hotspot capability to your app. Historically developers reported a situation where once they encountered the error it would show up consistently, but then it would go away on restarting the device. If you see behaviour like that, that’s definitely a bug and I encourage you to file it as such. I have more about filing such bugs in Filing a Wi-Fi Bug Report. Of course, you have to wait to reproduce the error again before you’ll be able to file that bug, because the act of restarting cleared the issue. I’ve seen reports where such problems only occur on a specific type of device, for example, on iPhone 16 but not on earlier or later iPhones. That’s definitely something that Apple should investigate, and I recommend that you file a bug about it. If the problem is being reported by your users but you can’t reproduce it yourself, consider the various suggestions in Using a Sysdiagnose Log to Debug a Hard-to-Reproduce Problem. Assuming you’re still here (-: the next step is to determine whether the problem is specific to NEHotspotConfigurationManager or not. Try joining the accessory’s network from Settings > Wi-Fi. Does that also have problems? If so, that’s not something we can help you with here on the forums. The focus of the Apple Developer Forums is primarily to help developers with the APIs in Apple’s various platform SDKs [2]. We’re not set up to help accessory developers with Wi-Fi issues. However, there are still things you can do, as I explain in Filing a Wi-Fi Bug Report. At this point you have an error that: Persists across restarts Happens with all Apple devices You can reproduce Only affects NEHotspotConfigurationManager If that’s correct then there are a couple of things you might look at: Coerce the error to an NSError and print that. Does it reveal anything interesting? Also check the underlying error property (NSUnderlyingErrorKey) for hints. When reproducing the error, monitor the system log for log entries in the com.apple.networkextension subsystem. Do those offer any clues? Note For lots of hints and tips about the system log, see Your Friend the System Log. And finally, if you have questions about this case, feel free to start a thread here on the forums and we’ll try to help you out. Put it in the App & System Services > Networking subtopic and tag it with Network Extension. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" [1] There’s also the .unknown error. See this post for a brief summary of the difference. [2] And with Apple tools and some developer-oriented services. Revision History 2026-03-18 Added a missing entitlement bullet to the specific case list. 2026-03-17 First posted.
Replies
0
Boosts
0
Views
99
Activity
Mar ’26
Network Extension Framework Entitlements
At WWDC 2015 Apple announced two major enhancements to the Network Extension framework: Network Extension providers — These are app extensions that let you insert your code at various points within the networking stack, including: Packet tunnels via NEPacketTunnelProvider App proxies via NEAppProxyProvider Content filters via NEFilterDataProvider and NEFilterControlProvider Hotspot Helper (NEHotspotHelper) — This allows you to create an app that assists the user in navigating a hotspot (a Wi-Fi network where the user must interact with the network in order to get access to the wider Internet). Originally, using any of these facilities required authorisation from Apple. Specifically, you had to apply for, and be granted access to, a managed capability. In Nov 2016 this policy changed for Network Extension providers. Any developer can now use the Network Extension provider capability like they would any other capability. There is one exception to this rule: Network Extension app push providers, introduced by iOS 14 in 2020, still requires that Apple authorise the use of a managed capability. To apply for that, follow the link in Local push connectivity. Also, the situation with Hotspot Helpers remains the same: Using a Hotspot Helper, requires that Apple authorise that use via a managed capability. To apply for that, follow the link in Hotspot helper. IMPORTANT Pay attention to this quote from the documentation: NEHotspotHelper is only useful for hotspot integration. There are both technical and business restrictions that prevent it from being used for other tasks, such as accessory integration or Wi-Fi based location. The rest of this document answers some frequently asked questions about the Nov 2016 change. #1 — Has there been any change to the OS itself? No, this change only affects the process by which you get the capabilities you need in order to use existing Network Extension framework facilities. Previously these were managed capabilities, meaning their use was authorised by Apple. Now, except for app push providers and Hotspot Helper, you can enable the necessary capabilities using Xcode’s Signing & Capabilities editor or the Developer website. IMPORTANT Some Network Extension providers have other restrictions on their use. For example, a content filter can only be used on a supervised device. These restrictions are unchanged. See TN3134 Network Extension provider deployment for the details. #2 — How exactly do I enable the Network Extension provider capability? In the Signing & Capabilities editor, add the Network Extensions capability and then check the box that matches the provider you’re creating. In the Certificates, Identifiers & Profiles section of the Developer website, when you add or edit an App ID, you’ll see a new capability listed, Network Extensions. Enable that capability in your App ID and then regenerate the provisioning profiles based on that App ID. A newly generated profile will include the com.apple.developer.networking.networkextension entitlement in its allowlist; this is an array with an entry for each of the supported Network Extension providers. To confirm that this is present, dump the profile as shown below. $ security cms -D -i NETest.mobileprovision … <plist version="1.0"> <dict> … <key>Entitlements</key> <dict> <key>com.apple.developer.networking.networkextension</key> <array> <string>packet-tunnel-provider</string> <string>content-filter-provider</string> <string>app-proxy-provider</string> … and so on … </array> … </dict> … </dict> </plist> #3 — I normally use Xcode’s Signing & Capabilities editor to manage my entitlements. Do I have to use the Developer website for this? No. Xcode 11 and later support this capability in the Signing & Capabilities tab of the target editor (r. 28568128 ). #4 — Can I still use Xcode’s “Automatically manage signing” option? Yes. Once you modify your App ID to add the Network Extension provider capability, Xcode’s automatic code signing support will include the entitlement in the allowlist of any profiles that it generates based on that App ID. #5 — What should I do if I previously applied for the Network Extension provider managed capability and I’m still waiting for a reply? Consider your current application cancelled, and use the new process described above. #6 — What should I do if I previously applied for the Hotspot Helper managed capability and I’m still waiting for a reply? Apple will continue to process Hotspot Helper managed capability requests and respond to you in due course. #7 — What if I previously applied for both Network Extension provider and Hotspot Helper managed capabilities? Apple will ignore your request for the Network Extension provider managed capability and process it as if you’d only asked for the Hotspot Helper managed capability. #8 — On the Mac, can Developer ID apps host Network Extension providers? Yes, but there are some caveats: This only works on macOS 10.15 or later. Your Network Extension provider must be packaged as a system extension, not an app extension. You must use the *-systemextension values for the Network Extension entitlement (com.apple.developer.networking.networkextension). For more on this, see Exporting a Developer ID Network Extension. #9 — After moving to the new process, my app no longer has access to the com.apple.managed.vpn.shared keychain access group. How can I regain that access? Access to this keychain access group requires another managed capability. If you need that, please open a DTS code-level support request and we’ll take things from there. IMPORTANT This capability is only necessary if your VPN supports configuration via a configuration profile and needs to access credentials from that profile (as discussed in the Profile Configuration section of the NETunnelProviderManager Reference). Many VPN apps don’t need this facility. If you were previously granted the Network Extension managed capability (via the process in place before Nov 2016), make sure you mention that; restoring your access to the com.apple.managed.vpn.shared keychain access group should be straightforward in that case. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Revision History 2025-11-11 Removed the discussion of TSI assets because those are no longer a thing. 2025-09-12 Adopted the code-level support request terminology. Made other minor editorial changes. 2023-01-11 Added a discussion of Network Extension app push providers. Added a link to Exporting a Developer ID Network Extension. Added a link to TN3134. Made significant editorial changes. 2020-02-27 Fixed the formatting. Updated FAQ#3. Made minor editorial changes. 2020-02-16 Updated FAQ#8 to account for recent changes. Updated FAQ#3 to account for recent Xcode changes. Made other editorial changes. 2016-01-25 Added FAQ#9. 2016-01-6 Added FAQ#8. 2016-11-11 Added FAQ#5, FAQ#6 and FAQ#7. 2016-11-11 First posted.
Replies
0
Boosts
0
Views
23k
Activity
Nov ’25
Unable to detect Network Extension configuration change while pushing MDM profile
My team is developing an enterprise VPN application that needs to respond to Mobile Device Management (MDM) profile installations and removals in real-time. Our app uses the NetworkExtension framework and needs to update the UI immediately when VPN configurations are added or removed via MDM. We are currently observing NEVPNConfigurationChangeNotification to detect VPN configuration changes: While NEVPNConfigurationChangeNotification fires reliably when users manually remove VPN profiles through Settings > General > VPN & Device Management, it appears to have inconsistent behavior when MDM profiles containing VPN configurations are installed programmatically via MDM systems. STEPS TO REPRODUCE From MDM Admin Console: Deploy a new VPN profile to the test device On Device: Wait for MDM profile installation (usually silent, no user interaction required) Check Device Settings: Go to Settings > General > VPN & Device Management to confirm profile is installed Return to App: Check if the UI shows the new VPN profile
Replies
1
Boosts
0
Views
224
Activity
Feb ’26
App occassionally crashing while connecting to public wifi
We are using the [NEHotspotHelper supportedNetworkInterfaces] to get the Wi-Fi interface in our app, but it occasionally crashes on some devices with the following stack trace: 0 CaptiveNetwork 0x0000000221d87a4c ServerConnectionGetHandlerQueue + 0 (ServerConnection.c:509) 1 CaptiveNetwork 0x0000000221d8577c CNPluginCopySupportedInterfaces + 180 (CNPlugin.c:457) 2 NetworkExtension 0x00000001b0446618 +[NEHotspotHelper supportedNetworkInterfaces] + 32 (NEHotspotHelper.m:563) It seems like the crash is happening on apple's api of supportedNetworkInterfaces. We would like to understand the cause of the crash.
Replies
2
Boosts
0
Views
104
Activity
May ’25
Working with a Wi-Fi Accessory
For important background information, read Extra-ordinary Networking before reading this. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Working with a Wi-Fi Accessory Building an app that works with a Wi-Fi accessory presents specific challenges. This post discusses those challenges and some recommendations for how to address them. Note While my focus here is iOS, much of the info in this post applies to all Apple platforms. IMPORTANT iOS 18 introduced AccessorySetupKit, a framework to simplify the discovery and configuration of an accessory. I’m not fully up to speed on that framework myself, but I encourage you to watch WWDC 2024 Session 10203 Meet AccessorySetupKit and read the framework documentation. IMPORTANT iOS 26 introduced WiFiAware, a framework for setting up communication with Wi-Fi Aware accessories. Wi-Fi Aware is an industry standard to securely discover, pair, and communicate with nearby devices. This is especially useful for stand-alone accessories (defined below). For more on this framework, watch WWDC 2025 Session 228 Supercharge device connectivity with Wi-Fi Aware and read the framework documentation. For information on how to create a Wi-Fi Aware accessory that works with iPhone, go to Developer > Accessories, download Accessory Design Guidelines for Apple Devices, and review the Wi-Fi Aware chapter. Accessory Categories I classify Wi-Fi accessories into three different categories. A bound accessory is ultimately intended to join the user’s Wi-Fi network. It may publish its own Wi-Fi network during the setup process, but the goal of that process is to get the accessory on to the existing network. Once that’s done, your app interacts with the accessory using ordinary networking APIs. An example of a bound accessory is a Wi-Fi capable printer. A stand-alone accessory publishes a Wi-Fi network at all times. An iOS device joins that network so that your app can interact with it. The accessory never provides access to the wider Internet. An example of a stand-alone accessory is a video camera that users take with them into the field. You might want to write an app that joins the camera’s network and downloads footage from it. A gateway accessory is one that publishes a Wi-Fi network that provides access to the wider Internet. Your app might need to interact with the accessory during the setup process, but after that it’s useful as is. An example of this is a Wi-Fi to WWAN gateway. Not all accessories fall neatly into these categories. Indeed, some accessories might fit into multiple categories, or transition between categories. Still, I’ve found these categories to be helpful when discussing various accessory integration challenges. Do You Control the Firmware? The key question here is Do you control the accessory’s firmware? If so, you have a bunch of extra options that will make your life easier. If not, you have to adapt to whatever the accessory’s current firmware does. Simple Improvements If you do control the firmware, I strongly encourage you to: Support IPv6 Implement Bonjour [1] These two things are quite easy to do — most embedded platforms support them directly, so it’s just a question of turning them on — and they will make your life significantly easier: Link-local addresses are intrinsic to IPv6, and IPv6 is intrinsic to Apple platforms. If your accessory supports IPv6, you’ll always be able to communicate with it, regardless of how messed up the IPv4 configuration gets. Similarly, if you support Bonjour, you’ll always be able to find your accessory on the network. [1] Bonjour is an Apple term for three Internet standards: RFC 3927 Dynamic Configuration of IPv4 Link-Local Addresses RFC 6762 Multicast DNS RFC 6763 DNS-Based Service Discovery WAC For a bound accessory, support Wireless Accessory Configuration (WAC). This is a relatively big ask — supporting WAC requires you to join the MFi Program — but it has some huge benefits: You don’t need to write an app to configure your accessory. The user will be able to do it directly from Settings. If you do write an app, you can use the EAWiFiUnconfiguredAccessoryBrowser class to simplify your configuration process. HomeKit For a bound accessory that works in the user’s home, consider supporting HomeKit. This yields the same onboarding benefits as WAC, and many other benefits as well. Also, you can get started with the HomeKit Open Source Accessory Development Kit (ADK). Bluetooth LE If your accessory supports Bluetooth LE, think about how you can use that to improve your app’s user experience. For an example of that, see SSID Scanning, below. Claiming the Default Route, Or Not? If your accessory publishes a Wi-Fi network, a key design decision is whether to stand up enough infrastructure for an iOS device to make it the default route. IMPORTANT To learn more about how iOS makes the decision to switch the default route, see The iOS Wi-Fi Lifecycle and Network Interface Concepts. This decision has significant implications. If the accessory’s network becomes the default route, most network connections from iOS will be routed to your accessory. If it doesn’t provide a path to the wider Internet, those connections will fail. That includes connections made by your own app. Note It’s possible to get around this by forcing your network connections to run over WWAN. See Binding to an Interface in Network Interface Techniques and Running an HTTP Request over WWAN. Of course, this only works if the user has WWAN. It won’t help most iPad users, for example. OTOH, if your accessory’s network doesn’t become the default route, you’ll see other issues. iOS will not auto-join such a network so, if the user locks their device, they’ll have to manually join the network again. In my experience a lot of accessories choose to become the default route in situations where they shouldn’t. For example, a bound accessory is never going to be able to provide a path to the wider Internet so it probably shouldn’t become the default route. However, there are cases where it absolutely makes sense, the most obvious being that of a gateway accessory. Acting as a Captive Network, or Not? If your accessory becomes the default route you must then decide whether to act like a captive network or not. IMPORTANT To learn more about how iOS determines whether a network is captive, see The iOS Wi-Fi Lifecycle. For bound and stand-alone accessories, becoming a captive network is generally a bad idea. When the user joins your network, the captive network UI comes up and they have to successfully complete it to stay on the network. If they cancel out, iOS will leave the network. That makes it hard for the user to run your app while their iOS device is on your accessory’s network. In contrast, it’s more reasonable for a gateway accessory to act as a captive network. SSID Scanning Many developers think that TN3111 iOS Wi-Fi API overview is lying when it says: iOS does not have a general-purpose API for Wi-Fi scanning It is not. Many developers think that the Hotspot Helper API is a panacea that will fix all their Wi-Fi accessory integration issues, if only they could get the entitlement to use it. It will not. Note this comment in the official docs: NEHotspotHelper is only useful for hotspot integration. There are both technical and business restrictions that prevent it from being used for other tasks, such as accessory integration or Wi-Fi based location. Even if you had the entitlement you would run into these technical restrictions. The API was specifically designed to support hotspot navigation — in this context hotspots are “Wi-Fi networks where the user must interact with the network to gain access to the wider Internet” — and it does not give you access to on-demand real-time Wi-Fi scan results. Many developers look at another developer’s app, see that it’s displaying real-time Wi-Fi scan results, and think there’s some special deal with Apple that’ll make that work. There is not. In reality, Wi-Fi accessory developers have come up with a variety of creative approaches for this, including: If you have a bound accessory, you might add WAC support, which makes this whole issue go away. In many cases, you can avoid the need for Wi-Fi scan results by adopting AccessorySetupKit. You might build your accessory with a barcode containing the info required to join its network, and scan that from your app. This is the premise behind the Configuring a Wi-Fi Accessory to Join the User’s Network sample code. You might configure all your accessories to have a common SSID prefix, and then take advantage of the prefix support in NEHotspotConfigurationManager. See Programmatically Joining a Network, below. You might have your app talk to your accessory via some other means, like Bluetooth LE, and have the accessory scan for Wi-Fi networks and return the results. Programmatically Joining a Network Network Extension framework has an API, NEHotspotConfigurationManager, to programmatically join a network, either temporarily or as a known network that supports auto-join. For the details, see Wi-Fi Configuration. One feature that’s particularly useful is it’s prefix support, allowing you to create a configuration that’ll join any network with a specific prefix. See the init(ssidPrefix:) initialiser for the details. For examples of how to use this API, see: Configuring a Wi-Fi Accessory to Join the User’s Network — It shows all the steps for one approach for getting a non-WAC bound accessory on to the user’s network. NEHotspotConfiguration Sample — Use this to explore the API in general. Secure Communication Users expect all network communication to be done securely. For some ideas on how to set up a secure connection to an accessory, see TLS For Accessory Developers. Revision History 2025-11-05 Added a link to the Accessory Design Guidelines for Apple Devices. 2025-06-19 Added a preliminary discussion of Wi-Fi Aware. 2024-09-12 Improved the discussion of AccessorySetupKit. 2024-07-16 Added a preliminary discussion of AccessorySetupKit. 2023-10-11 Added the HomeKit section. Fixed the link in Secure Communication to point to TLS For Accessory Developers. 2023-07-23 First posted.
Replies
0
Boosts
0
Views
1.9k
Activity
Nov ’25
test NEAppProxyProvider without MDM?
This discussion is for iOS/iPadOS. I've written an NEAppProxyProvider network extension. I'd like to test it. I thought that using the "NETestAppMapping" dictionary was a way to get there, but when I try to instantiate an NEAppProxyProviderManager to try to install stuff, the console tells me "must be MDM managed" and I get nowhere. So can someone tell me, can I at least test the idea without needing to first get MDM going? I'd like to know if how I'm approaching the core problem even makes sense. My custom application needs to stream video, via the SRT protocol, to some place like youtube or castr. The problem is that in the environment we are in (big convention centers), our devices are on a LAN, but the connection from the LAN out to the rest of the world just sucks. Surprisingly, cellular has better performance. So I am trying to do the perverse thing of forcing traffix that is NOT local to go out over cellular. And traffic that is completely local (i.e. talking to a purely local server/other devices on the LAN) happens over ethernet. [To simplify things, wifi is not connected.] Is an app proxy the right tool for this? Is there any other tool? Unfortunately, I cannot rewrite the code to force everything through Apple's Network framework, which is the one place I know we can say "use cellular." [E.g. URLSession() has absolutely no way of forcing cellular, and even so, the low level streaming library I use is written with raw sockets, and its not feasible for me to rewrite it.] Any other suggestions of how to accomplish this "send non-local traffic to cellular, all local traffic out over ethernet" gratefully welcomed!
Replies
9
Boosts
0
Views
171
Activity
Mar ’26
A Peek Behind the NECP Curtain
From time to time the subject of NECP grows up, both here on DevForums and in DTS cases. I’ve posted about this before but I wanted to collect those tidbits into single coherent post. If you have questions or comments, start a new thread in the App & System Services > Networking subtopic and tag it with Network Extension. That way I’ll be sure to see it go by. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" A Peek Behind the NECP Curtain NECP stands for Network Extension Control Protocol. It’s a subsystem within the Apple networking stack that controls which programs have access to which network interfaces. It’s vitally important to the Network Extension subsystem, hence the name, but it’s used in many different places. Indeed, a very familiar example of its use is the Settings > Mobile Data [1] user interface on iOS. NECP has no explicit API, although there are APIs that are offer some insight into its state. Continuing the Settings > Mobile Data example above, there is a little-known API, CTCellularData in the Core Telephony framework, that returns whether your app has access to WWAN. Despite having no API, NECP is still relevant to developers. The Settings > Mobile Data example is one place where it affects app developers but it’s most important for Network Extension (NE) developers. A key use case for NECP is to prevent VPN loops. When starting an NE provider, the system configures the NECP policy for the NE provider’s process to prevent it from using a VPN interface. This means that you can safely open a network connection inside your VPN provider without having to worry about its traffic being accidentally routed back to you. This is why, for example, an NE packet tunnel provider can use any networking API it wants, including BSD Sockets, to run its connection without fear of creating a VPN loop [1]. One place that NECP shows up regularly is the system log. Next time you see a system log entry like this: type: debug time: 15:02:54.817903+0000 process: Mail subsystem: com.apple.network category: connection message: nw_protocol_socket_set_necp_attributes [C723.1.1:1] setsockopt 39 SO_NECP_ATTRIBUTES … you’ll at least know what the necp means (-: Finally, a lot of NECP infrastructure is in the Darwin open source. As with all things in Darwin, it’s fine to poke around and see how your favourite feature works, but do not incorporate any information you find into your product. Stuff you uncover by looking in Darwin is not considered API. [1] Settings > Cellular Data if you speak American (-: [2] Network Extension providers can call the createTCPConnection(to:enableTLS:tlsParameters:delegate:) method to create an NWTCPConnection [3] that doesn’t run through the tunnel. You can use that if it’s convenient but you don’t need to use it. [3] NWTCPConnection is now deprecated, but there are non-deprecated equivalents. For the full story, see NWEndpoint History and Advice. Revision History 2025-12-12 Replaced “macOS networking stack” with “Apple networking stack” to avoid giving the impression that this is all about macOS. Added a link to NWEndpoint History and Advice. Made other minor editorial changes. 2023-02-27 First posted.
Replies
0
Boosts
0
Views
2.7k
Activity
Dec ’25
Thread topology data: no API path for parent-child relationships
I'm building a HomeKit app that discovers Thread devices and visualizes the mesh topology. I can detect device roles (Router vs End Device via characteristic 0x0703) and identify Border Routers (via _meshcop._udp), but I cannot determine which Router is the parent of a given End Device. Any Thread device can act as a Router (a Nanoleaf bulb, an Eve plug, not just HomePods), and End Devices attach to these Routers as children. That parent-child relationship is what I'm trying to map, but there's no RLOC16, neighbor table, or parent identifier exposed through any available API. I've tested every path I can find. Here's what I've tried on a network with 44 Thread devices and 6 Border Routers: What works (partially) HAP Thread Management Service (0x0701) gives me the device role from characteristic 0x0703, the OpenThread version from 0x0706, and node capabilities from 0x0702. That's the complete set of characteristics on that service. None of them contain RLOC16, parent Router, or neighbor data. This service also only exists on HAP-native Thread devices. My 20 Matter-over-Thread devices (Aqara, Eve Door, SmartWings, Onvis S4) don't have it at all. MeshCoP Bonjour (_meshcop._udp) identifies Border Routers and the network name/Extended PAN ID. No topology data about other mesh nodes. What doesn't work ThreadNetwork framework (THClient) - retrieveAllCredentials() returns error Code 3 because the app can't access credentials stored by Apple Home. Even if it worked, THCredentials only contains network config (name, PAN ID, channel), not topology. Direct CoAP queries - Border Routers don't route traffic from WiFi to Thread management ports. Mesh-local addresses aren't reachable. No Thread NWInterface in Network.framework. Network.framework - No visibility into the Thread mesh from the WiFi side. The only remaining path I can see (but it's not practical) Matter cluster 0x0035 (Thread Network Diagnostics) appears to have exactly what I need: RLOC16, NeighborTable with isChild boolean, RouteTable. I haven't implemented this because it requires commissioning each device individually onto my app's own Matter fabric via Multi-Admin. That's 21 separate user-initiated pairing actions on my network. I can't ask end users to do that. The core issue Every Thread Router (whether it's a HomePod acting as a Border Router or a Nanoleaf bulb acting as a mesh Router) knows its own children and neighbors. The Border Routers also maintain route tables covering the mesh backbone. This data exists on the user's own devices but none of it is exposed to third-party apps. Even something minimal would help. HMAccessory already exposes matterNodeID as a cross-protocol identifier. Exposing RLOC16 the same way would be enough, since parent-child relationships are encoded in the address itself (ParentRLOC = ChildRLOC & 0xFC00). Has anyone found another approach I'm missing? Thanks in advance for any pointers.
Replies
1
Boosts
0
Views
258
Activity
Feb ’26
Extra-ordinary Networking
Most apps perform ordinary network operations, like fetching an HTTP resource with URLSession and opening a TCP connection to a mail server with Network framework. These operations are not without their challenges, but they’re the well-trodden path. If your app performs ordinary networking, see TN3151 Choosing the right networking API for recommendations as to where to start. Some apps have extra-ordinary networking requirements. For example, apps that: Help the user configure a Wi-Fi accessory Require a connection to run over a specific interface Listen for incoming connections Building such an app is tricky because: Networking is hard in general. Apple devices support very dynamic networking, and your app has to work well in whatever environment it’s running in. Documentation for the APIs you need is tucked away in man pages and doc comments. In many cases you have to assemble these APIs in creative ways. If you’re developing an app with extra-ordinary networking requirements, this post is for you. Note If you have questions or comments about any of the topics discussed here, put them in a new thread here on DevForums. Make sure I see it by putting it in the App & System Services > Networking area. And feel free to add tags appropriate to the specific technology you’re using, like Foundation, CFNetwork, Network, or Network Extension. Links, Links, and More Links Each topic is covered in a separate post: The iOS Wi-Fi Lifecycle describes how iOS joins and leaves Wi-Fi networks. Understanding this is especially important if you’re building an app that works with a Wi-Fi accessory. Network Interface Concepts explains how Apple platforms manage network interfaces. If you’ve got this far, you definitely want to read this. Network Interface Techniques offers a high-level overview of some of the more common techniques you need when working with network interfaces. Network Interface APIs describes APIs and core techniques for working with network interfaces. It’s referenced by many other posts. Running an HTTP Request over WWAN explains why most apps should not force an HTTP request to run over WWAN, what they should do instead, and what to do if you really need that behaviour. If you’re building an iOS app with an embedded network server, see Showing Connection Information in an iOS Server for details on how to get the information to show to your user so they can connect to your server. Many folks run into trouble when they try to find the device’s IP address, or other seemingly simple things, like the name of the Wi-Fi interface. Don’t Try to Get the Device’s IP Address explains why these problems are hard, and offers alternative approaches that function correctly in all network environments. Similarly, folks also run into trouble when trying to get the host name. On Host Names explains why that’s more complex than you might think. If you’re working with broadcasts or multicasts, see Broadcasts and Multicasts, Hints and Tips. If you’re building an app that works with a Wi-Fi accessory, see Working with a Wi-Fi Accessory. If you’re trying to gather network interface statistics, see Network Interface Statistics. There are also some posts that are not part of this series but likely to be of interest if you’re working in this space: TN3179 Understanding local network privacy discusses the local network privacy feature. Calling BSD Sockets from Swift does what it says on the tin, that is, explains how to call BSD Sockets from Swift. When doing weird things with the network, you often find yourself having to use BSD Sockets, and that API is not easy to call from Swift. The code therein is primarily for the benefit of test projects, oh, and DevForums posts like these. TN3111 iOS Wi-Fi API overview is a critical resource if you’re doing Wi-Fi specific stuff on iOS. TLS For Accessory Developers tackles the tricky topic of how to communicate securely with a network-based accessory. A Peek Behind the NECP Curtain discusses NECP, a subsystem that control which programs have access to which network interfaces. Networking Resources has links to many other useful resources. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Revision History 2025-07-31 Added a link to A Peek Behind the NECP Curtain. 2025-03-28 Added a link to On Host Names. 2025-01-16 Added a link to Broadcasts and Multicasts, Hints and Tips. Updated the local network privacy link to point to TN3179. Made other minor editorial changes. 2024-04-30 Added a link to Network Interface Statistics. 2023-09-14 Added a link to TLS For Accessory Developers. 2023-07-23 First posted.
Replies
0
Boosts
0
Views
5.8k
Activity
Jul ’25
TCP socket disconnection with EBROKENPIPE during file copy of signed app bundle
We are developing a client server application using TCP bsd sockets. When our client is connected to the server, copying another client .app bundle from a file server on the same machine (using Finder or terminal using cp), occasionally causes the first client to disconnect. The client receives an EBROKENPIPE error when attempting to write to its socket. In the Console, the following message appears just before the disconnection: necp_socket_find_policy_match: Marking socket in state 258 as defunct This issue seems to occur only when copying an .app bundle signed with the same TeamIdentifier as the running client. Copying arbitrary files or bundles with a different TeamIdentifier does not trigger the problem. We are running on macOS 15.5. The issue appears specific to macOS 15 and was not observed on earlier versions. Any help or pointers would be greatly appreciated!
Replies
2
Boosts
0
Views
225
Activity
Jul ’25
URL Filter Network Extension
Hello team, I have implemented sample project for URL Filtering as well as setup PIR server at backend but currently I am facing a major issue, If PIR server is re started then the app shows error code 9 every time until. and unless I disconnect and connect it back to internet
Replies
1
Boosts
0
Views
160
Activity
Apr ’26
Unable to update app with PacketTunnelProvider running
Hi there, I am working on an app that configures a PacketTunnelProvider to establish a VPN connection. Unfortunately, while a VPN connection is established, I am unable to update the app via testflight. Downloading other app updates works fine. I noticed that after I receive the alert that updating failed, the vpn badge appears at the top of my screen (the same ux that occurs when the connection is first established). So it's almost like it tried to close the tunnel, and seeing that the app update failed it restablishes the tunnel. I am unsure of why I would not be able to update my app. Maybe stopTunnel is not being called with NEProviderStopReason.appUpdate?
Replies
1
Boosts
0
Views
83
Activity
Jun ’25
Recommended alternatives to leaf cert pinning to prevent MITM
Hey there Are there any recommendations or guidance for apps on alternatives to certificate pinning to secure their device network traffic? I want to move away from the overhead and risk associated with rotating certificates when using leaf pinning. However, I also don't want people to be able to perform a MITM attack easily using something like Charles Proxy with a self‑signed certificate added to the trust store. My understanding is that an app cannot distinguish between user‑trusted certificates and system‑trusted certificates in the trust store, so it cannot block traffic that uses user‑trusted certificates.
Replies
0
Boosts
0
Views
59
Activity
Jan ’26
IOS app on MacOS 15 local network access
Our app is developed for iOS, but some users also run it on macOS (as an iOS app via Apple Silicon). The app requires local network permission, which works perfectly on iOS. Previously, the connection also worked fine on macOS, but since the recent macOS update, the app can no longer connect to our device. Additionally, our app on macOS doesn't prompt for local network permission at all, whereas it does on iOS. Is this a known issue with iOS apps running on macOS? Has anyone else experienced this problem, or is there a workaround? Any help would be appreciated!
Replies
9
Boosts
0
Views
971
Activity
Oct ’25
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. Put it in the App & System Services > Networking and tag it with Network Extension. 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. On the other hand, the build / run / debug cycle is simpler on iOS than it is on macOS, especially when you’re building a system extension on macOS. Even if your ultimate goal is to build a macOS-only system extension, if your provider type supports app extension packaging then you should consider whether it makes sense to adopt that packaging just for to speed up your development. If you do decide to try this, be aware that a packaging change can affect your code. See Network Extension Provider Packaging for more on that. [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 2026-04-01 Added a suggestion about provider packaging to the General Hints and Tips section. 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.
Replies
0
Boosts
0
Views
4.4k
Activity
Apr ’26
NSURLSession’s Resume Rate Limiter
IMPORTANT The resume rate limiter is now covered by the official documentation. See Use background sessions efficiently within Downloading files in the background. So, the following is here purely for historical perspective. NSURLSession’s background session support on iOS includes a resume rate limiter. This limiter exists to prevent apps from abusing the background session support in order to run continuously in the background. It works as follows: nsurlsessiond (the daemon that does all the background session work) maintains a delay value for your app. It doubles that delay every time it resumes (or relaunches) your app. It resets that delay to 0 when the user brings your app to the front. It also resets the delay to 0 if the delay period elapses without it having resumed your app. When your app creates a new task while it is in the background, the task does not start until that delay has expired. To understand the impact of this, consider what happens when you download 10 resources. If you pass them to the background session all at once, you see something like this: Your app creates tasks 1 through 10 in the background session. nsurlsessiond starts working on the first few tasks. As tasks complete, nsurlsessiond starts working on subsequent ones. Eventually all the tasks complete and nsurlsessiond resumes your app. Now consider what happens if you only schedule one task at a time: Your app creates task 1. nsurlsessiond starts working on it. When it completes, nsurlsessiond resumes your app. Your app creates task 2. nsurlsessiond delays the start of task 2 a little bit. nsurlsessiond starts working on task 2. When it completes, nsurlsessiond resumes your app. Your app creates task 3. nsurlsessiond delays the start of task 3 by double the previous amount. nsurlsessiond starts working on task 3. When it completes, nsurlsessiond resumes your app. Steps 8 through 11 repeat, and each time the delay doubles. Eventually the delay gets so large that it looks like your app has stopped making progress. If you have a lot of tasks to run then you can mitigate this problem by starting tasks in batches. That is, rather than start just one task in step 1, you would start 100. This only helps up to a point. If you have thousands of tasks to run, you will eventually start seeing serious delays. In that case it’s much better to change your design to use fewer, larger transfers. Note All of the above applies to iOS 8 and later. Things worked differently in iOS 7. There’s a post on DevForums that explains the older approach. Finally, keep in mind that there may be other reasons for your task not starting. Specifically, if the task is flagged as discretionary (because you set the discretionary flag when creating the task’s session or because the task was started while your app was in the background), the task may be delayed for other reasons (low power, lack of Wi-Fi, and so on). Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" (r. 22323366)
Replies
0
Boosts
0
Views
14k
Activity
Jul ’25
OSSystemExtension activation fails with code=4 and sysextd "no policy, cannot allow apps outside /Applications" even when host app is in /Applications
Summary We are activating a Network Extension system extension (filter-data) from a signed and notarized macOS app. Activation consistently fails with: OSSystemExtensionErrorDomain code=4 Extension not found in App bundle. Unable to find any matched extension with identifier: com.seaskylight.yksmacos.ExamNetFilter.data At the same time, sysextd logs: no policy, cannot allow apps outside /Applications However, our host app and executable real paths are already under /Applications, and the extension bundle physically exists in the expected app bundle location. Environment macOS: Darwin 25.4.0 Host app: /Applications/xxx.app Host bundle id: com.seaskylight.yksmacos System extension bundle id: com.seaskylight.yksmacos.ExamNetFilter.data Team ID: BVU65MZFLK Device management: Enrolled via DEP: No MDM enrollment: No Reproduction Steps Install host app to /Applications. Launch host app via Finder or: open -a "/Applications/xxx.app" Trigger OSSystemExtensionRequest activationRequestForExtension for: com.seaskylight.yksmacos.ExamNetFilter.data Observe failure callback (code=4). Collect logs: log show --last 2m --style compact --info --debug --predicate 'process == "sysextd"' systemextensionsctl list (shows 0 extension(s)) Observed Results sysextd client activation request for com.seaskylight.yksmacos.ExamNetFilter.data attempting to realize extension with identifier com.seaskylight.yksmacos.ExamNetFilter.data no policy, cannot allow apps outside /Applications App-side diagnostics (captured at failure) pid=3249 bundlePath=/Applications/xxx.app bundlePathReal=/Applications/xxx.app execPath=/Applications/xxx.app/Contents/MacOS/xxx execPathReal=/Applications/xxx.app/Contents/MacOS/xxx extPath=/Applications/xxx.app/Contents/Library/SystemExtensions/ExamNetFilterData.systemextension extExists=true runningFromHelper=false Error callback NSError{domain=OSSystemExtensionErrorDomain code=4 desc=Extension not found in App bundle...} Additional Validation We reproduced the same failure using a minimal native host app (SysExtProbe) in /Applications that only submits the activation request for the same extension identifier. It also fails with OSSystemExtensionErrorDomain code=4, indicating this is not specific to Electron app logic. Signing / Packaging Notes Host app and system extension are signed with the same Team ID (BVU65MZFLK). System extension bundle exists under: /Applications/xxx.app/Contents/Library/SystemExtensions/ExamNetFilterData.systemextension Extension Info.plist contains bundle id: com.seaskylight.yksmacos.ExamNetFilter.data Host app includes NSSystemExtensionUsageDescription. Questions for DTS In non-MDM personal-device scenarios, what exact conditions trigger sysextd to emit: no policy, cannot allow apps outside /Applications even when both bundlePath and realpath are in /Applications? Can code=4 (“Extension not found in App bundle”) be returned for policy/state reasons even when extension bundle is present and identifier matches? Are there known sysextd policy/cache states that cause this behavior, and what is the recommended recovery procedure?
Replies
2
Boosts
0
Views
129
Activity
6d
DeviceDiscoveryUI notification for iPad says iPhone?
I have been polishing an app that connects and communicates between a tvOS app I created and a iPadOS app that I also created. Connection works fantastic! However, for some reason when the user selects the button to open the DevicePicker provided by this API and then selects a iPad device the notification that comes across the the iPad reads, "Connect your Apple TV to "AppName" on this iPhone. Is this a bug or am I missing some configuration in maybe Info.plist or a modifier I need to add the DevicePicker for it to communicate the proper device identification? I have everything setup in both app Info.plist files to connect and work fine, but the notification saying iPhone on an iPad is sadly a small detail I would love to change. So...not sure if I found a bug or if I am missing something.
Replies
2
Boosts
0
Views
450
Activity
May ’25
iOS Resumable Uploads Troubles
I am referencing: https://developer.apple.com/documentation/foundation/pausing-and-resuming-uploads Specifically: You can’t resume all uploads. The server must support the latest resumable upload protocol draft from the HTTP Working Group at the IETF. Also, uploads that use a background configuration handle resumption automatically, so manual resuming is only needed for non-background uploads. I have control over both the app and the server, and can't seem to get it to work automatically with a background url session. In other words, making multiple requests to get the offset then upload, easy but I am trying to leverage this background configuration resume OS magic. So anyone know what spec version does the server/client need to implement? The docs reference version 3, however the standard is now at like 11. Of course, I am trying out 3. Does anyone know how exactly this resume is implemented in iOS, and what exactly it takes care of? I assumed that I can just POST to a generic end point, say /files, then the OS receives a 104 Location, and saves that. If the upload is interrupted, when the OS resumes the upload, it has enough information to figure out how to resume from the exact offset, either by making a HEAD request to get the offset, or handle a 409. I am assuming it does this, as if it doesn't, the 'uploads that use a background configuration handle resumption automatically' is useless, if it just restarts from 0. Note, of course making individual POST/HEAD/PATCH requests manually works, but at that point I'm not really leveraging any OS auto-magic, and am just consuming an API that could really implement any spec. This won't work in the background, as the OS seems to disallow random HTTP requests when it wakes the app for URLSession background resumes. As of right now, I have it 'partially' working, insofar as the app does receive the 104 didReceiveInformationalResponse url delegate call, however it seems to then hang; it stops sending bytes, seemingly when the 104 is received. However, the request does not complete. In other words, it doesn't seem to receive a client timeout or otherwise indicate the request has finished. Right now, I am starting a single request, POSTing to a /files end point, i.e. I am not getting the location first, then PATCHing to that, as if I do that, the OS 'automatic' resuming fails with a 409, i.e. it doesn't seem to make a HEAD request and/or use the 409 offset correction then continue with the PATCH. Any idea what could be going on?
Replies
1
Boosts
0
Views
223
Activity
Mar ’26
FYI: Network System extension, macOS update issue, loss of networking
This is just an FYI in case someone else runs into this problem. This afternoon (12 Dec 2025), I updated to macOS 26.2 and lost my network. The System Settings' Wi-Fi light was green and said it was connected, but traceroute showed "No route to host". I turned Wi-Fi on & off. I rebooted the Mac. I rebooted the eero network. I switched to tethering to my iPhone. I switched to physical ethernet cable. Nothing worked. Then I remembered I had a beta of an app with a network system extension that was distributed through TestFlight. I deleted the app, and networking came right back. I had this same problem ~2 years ago. Same story: app with network system extension + TestFlight + macOS update = lost network. (My TestFlight build might have expired, but I'm not certain) I don't know if anyone else has had this problem, but I thought I'd share this in case it helps.
Replies
2
Boosts
0
Views
291
Activity
Jan ’26