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

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
56
Jan ’26
Flow Divert behavior
Hello, Our app uses Network Extension / Packet Tunnel Provider to establish VPN connections on macOS and iOS. We have observed that after creating a utun device and adding any IPv4 routes (NEPacketTunnelNetworkSettings.IPv4Settings), the OS automatically adds several host routes via utun to services such as Akamai, Apple Push, etc. These routes appear to correspond to TCP flows that were active at the moment the VPN connection was established. When a particular TCP flow ends, the corresponding host route is deleted. We understand this is likely intended to avoid breaking existing TCP connections. However, we find the behavior of migrating existing TCP flows to the new utun interface simply because any IPv4 route is added somewhat questionable. This approach would make sense in a "full-tunnel" scenario — for example, when all IPv4 traffic (e.g., 0.0.0.0/0) is routed through the tunnel — but not necessarily in a "split-tunnel" configuration where only specific IPv4 routes are added. Is there any way to control or influence this behavior? Would it be possible for FlowDivert to differentiate between full-tunnel and split-tunnel cases, and only preserve existing TCP flows via utun in the full-tunnel scenario? Thank you.
0
0
119
Apr ’25
On FTP
Questions about FTP crop up from time-to-time here on DevForums. In most cases I write a general “don’t use FTP” response, but I don’t have time to go into all the details. I’ve created this post as a place to collect all of those details, so I can reference them in other threads. IMPORTANT Apple’s official position on FTP is: All our FTP APIs have been deprecated, and you should avoid using deprecated APIs. Apple has been slowly removing FTP support from the user-facing parts of our system. The most recent example of this is that we removed the ftp command-line tool in macOS 10.13. You should avoid the FTP protocol and look to adopt more modern alternatives. The rest of this post is an informational explanation of the overall FTP picture. This post is locked so I can keep it focused. If you have questions or comments, please do create a new thread in the App & System Services > Networking subtopic and I’ll respond there. Don’t Use FTP FTP is a very old and very crufty protocol. Certain things that seem obvious to us now — like being able to create a GUI client that reliably shows a directory listing in a platform-independent manner — aren’t possible to do in FTP. However, by far the biggest problem with FTP is that it provides no security [1]. Specifically, the FTP protocol: Provides no on-the-wire privacy, so anyone can see the data you transfer Provides no client-authenticates-server authentication, so you have no idea whether you’re talking to the right server Provides no data integrity, allowing an attacker to munge your data in transit Transfers user names and passwords in the clear Using FTP for anonymous downloads may be acceptable (see the explanation below) but most other uses of FTP are completely inappropriate for the modern Internet. IMPORTANT You should only use FTP for anonymous downloads if you have an independent way to check the integrity of the data you’ve downloaded. For example, if you’re downloading a software update, you could use code signing to check its integrity. If you don’t check the integrity of the data you’ve downloaded, an attacker could substitute a malicious download instead. This would be especially bad in, say, the software update case. These fundamental problems with the FTP protocol mean that it’s not a priority for Apple. This is reflected in the available APIs, which is the subject of the next section. FTP APIs Apple provides two FTP APIs: All Apple platforms provide FTP downloads via URLSession. Most Apple platforms (everything except watchOS) support CFFTPStream, which allows for directory listings, downloads, uploads, and directory creation. All of these FTP APIs are now deprecated: URLSession was deprecated for the purposes of FTP in the 2022 SDKs (macOS 13, iOS 16, iPadOS 16, tvOS 16, watchOS 9) [2]. CFFTPStream was deprecated in the 2016 SDKs (macOS 10.11, iOS 9, iPadOS 9, tvOS 9). CFFTPStream still works about as well as it ever did, which is not particularly well. Specifically: There is at least one known crashing bug (r. 35745763), albeit one that occurs quite infrequently. There are clear implementation limitations — like the fact that CFFTPCreateParsedResourceListing assumes a MacRoman text encoding (r. 7420589) — that won’t be fixed. If you’re looking for an example of how to use these APIs, check out SimpleFTPSample. Note This sample hasn’t been updated since 2013 and is unlikely to ever be updated given Apple’s position on FTP. The FTP support in URLSession has significant limitations: It only supports FTP downloads; there’s no support for uploads or any other FTP operations. It doesn’t support resumable FTP downloads [3]. It doesn’t work in background sessions. That prevents it from running FTP downloads in the background on iOS. It’s only supported in classic loading mode. See the usesClassicLoadingMode property and the doc comments in <Foundation/NSURLSession.h>. If Apple’s FTP APIs are insufficient for your needs, you’ll need to write or acquire your own FTP library. Before you do that, however, consider switching to an alternative protocol. After all, if you’re going to go to the trouble of importing a large FTP library into your code base, you might as well import a library for a better protocol. The next section discusses some options in this space. Alternative Protocols There are numerous better alternatives to FTP: HTTPS is by far the best alternative to FTP, offering good security, good APIs on Apple platforms, good server support, and good network compatibility. Implementing traditional FTP operations over HTTPS can be a bit tricky. One possible way forward is to enable DAV extensions on the server. FTPS is FTP over TLS (aka SSL). While FTPS adds security to the protocol, which is very important, it still inherits many of FTP’s other problems. Personally I try to avoid this protocol. SFTP is a file transfer protocol that’s completely unrelated to FTP. It runs over SSH, making it a great alternative in many of the ad hoc setups that traditionally use FTP. Apple doesn’t have an API for either FTPS or SFTP, although on macOS you may be able to make some headway by invoking the sftp command-line tool. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" [1] In another thread someone asked me about FTP’s other problems, those not related to security, so let’s talk about that. One of FTP’s implicit design goals was to provide cross-platform support that exposes the target platform. You can think of FTP as being kinda like telnet. When you telnet from Unix to VMS, it doesn’t aim to abstract away VMS commands, so that you can type Unix commands at the VMS prompt. Rather, you’re expected to run VMS commands. FTP is (a bit) like that. This choice made sense back when the FTP protocol was invented. Folks were expecting to use FTP via a command-line client, so there was a human in the loop. If they ran a command and it produced VMS-like output, that was fine because they knew that they were FTPing into a VMS machine. However, most users today are using GUI clients, and this design choice makes it very hard to create a general GUI client for FTP. Let’s consider the simple problem of getting the contents of a directory. When you send an FTP LIST command, the server would historically run the platform native directory list command and pipe the results back to you. To create a GUI client you have to parse that data to extract the file names. Doing that is a serious challenge. Indeed, just the first step, working out the text encoding, is a challenge. Many FTP servers use UTF-8, but some use ISO-Latin-1, some use other standard encodings, some use Windows code pages, and so on. I say “historically” above because there have been various efforts to standardise this stuff, both in the RFCs and in individual server implementations. However, if you’re building a general client you can’t rely on these efforts. After all, the reason why folks continue to use FTP is because of it widespread support. [2] To quote the macOS 13 Ventura Release Notes: FTP is deprecated for URLSession and related APIs. Please adopt modern secure networking protocols such as HTTPS. (92623659) [3] Although you can implement resumable downloads using the lower-level CFFTPStream API, courtesy of the kCFStreamPropertyFTPFileTransferOffset property. Revision History 2025-10-06 Explained that URLSession only supports FTP in classic loading mode. Made other minor editorial changes. 2024-04-15 Added a footnote about FTP’s other problems. Made other minor editorial changes. 2022-08-09 Noted that the FTP support in URLSession is now deprecated. Made other minor editorial changes. 2021-04-06 Fixed the formatting. Fixed some links. 2018-02-23 First posted.
0
0
5.8k
Oct ’25
iPhone App 进行网络请求的时候出错,报错信息为:未能完成该操作。设备上无剩余空间
1、已经检查过手机的存储空间,还有一百多G的空间。app端进行网络接口情况的时候报错了,报错信息如下: Error : Error Domain=NSPOSIXErrorDomain Code=28 "No space left on device" UserInfo={_NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <7DB1CBFD-B9BE-422D-9C9A-78D8FC04DC1B>.<76>, _kCFStreamErrorDomainKey=1, _kCFStreamErrorCodeKey=28, _NSURLErrorRelatedURLSessionTaskErrorKey=( "LocalDataTask <7DB1CBFD-B9BE-422D-9C9A-78D8FC04DC1B>.<76>" ), _NSURLErrorNWPathKey=satisfied (Path is satisfied), interface: pdp_ip0[lte], ipv4, ipv6, dns, expensive, estimated upload: 65536Bps, uses cell} 2、手机型号是iPhone 15 Plus,iOS 17.6.1
2
0
418
Jun ’25
What does iOS do wrt Shared Web Credentials when it makes a call to a server to perform a message filter request
In order to create a Message Filter Extension it is necessary to set up Shared Web Credentials. I'd like to form an understanding of what role SWC plays when the OS is making request to the associated network service (when the extension has called deferQueryRequestToNetwork()) and how this differs from when an app directly uses Shared Web Credentials itself. When an app is making direct use of SWC, it makes a request to obtain the user's credentials from the web site. However in the case of a Message Filter Extension, there aren't any individual user credentials, so what is happening behind the scenes when the OS makes a server request on behalf of a Message Filtering Extension? A more general question - the documentation for Shared Web Credentials says "Associated domains establish a secure association between domains and your app.". Thank you
2
0
477
Apr ’25
Content filtering
Hello team, Would this mean that content filters intended for all browsing can only be implemented for managed devices using MDM? My goal would be to create a content filtering app for all users, regardless of if their device is managed/supervised. thanks.
1
0
109
Jan ’26
Pair iOS Central with MacOS Peripheral for encrypted characteristic
Is this even possible? Instead of any pairing dialog appearing, my central code get the "Authentication is insufficient" error when reading the characteristic. My peripheral (in the macOS app) code uses the .notifyEncryptionRequired property and uses .readEncryptionRequired and .writeEncryptionRequired permissions. No descriptors are set, but I think they get added automatically since this characteristic notifies. 2900 and 2902 descriptors are set by the peripheral/CoreBluetooth. If the Mac and iPhone are using the same Apple ID does that affect pairing?
0
0
94
Feb ’26
Does app launch recency affect NEPacketTunnelProvider, HotspotHelper, or NEHotspotManager functionality?
We are assisting a client with their app integration. The client believes that NEPacketTunnelProvider, NEHotspotHelper, and NEHotspotManager extensions stop functioning if the containing app hasn't been launched by the user within some recent window (e.g. 30, 60, or 90 days). We haven't been able to find any documentation supporting this claim. Specifically, we'd like to know: Is there any app launch recency requirement that would cause iOS to stop invoking a registered NEHotspotHelper or NEHotspotManager configuration? Is there any app launch recency requirement that would cause iOS to tear down or prevent activation of a NEPacketTunnelProvider? More generally, does iOS enforce any kind of "staleness" check on apps that provide Network Extension or Hotspot-related functionality, where not being foregrounded for some period causes the system to stop honoring their registrations? If such a mechanism exists, we'd appreciate any pointers to documentation or technical notes describing the behavior and timeframes involved. If it doesn't exist, confirmation would help us guide our client's debugging in the right direction. Thank you.
1
0
75
Mar ’26
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
70
3w
URL Filter Prefetch Interval guarantee
Hello, I have implemented a URL Filter using the sample provided here: Filtering Traffic by URL. I am also using an App Group to dynamically manage the Bloom filter and block list data. However, when I update my block list URLs and create a new Bloom filter plist in the App Group, the extension does not seem to use the updated Bloom filter even after the prefetch interval expires. Also for testing purpose can I keep this interval to 10 mins or below ?
3
0
261
2w
About the Relay payload in iOS configuration profiles
Are the network relays introduced in 2023 and https://developer.apple.com/videos/play/wwdc2023/10002/ the same thing as the Private Relay introduced in 2021? https://developer.apple.com/videos/play/wwdc2021/10096/ We are considering verifying the relay function, but we are not sure whether they are the same function or different functions. https://developer.apple.com/documentation/devicemanagement/relay?language=objc
0
0
61
Apr ’25
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
425
May ’25
Triggering “realtime” mode for peer-to-peer WiFi via awdl to fix jitter problems
This is a bit complicated to explain so bare with me. I am working on building an app that allows you to send real time video/camera captures from one Apple device to another. I am using a custom UDP protocol built on top of NWListener, NWBrowser, and NWConnection APIs. It works fine, but there are a few issues that seems to all be related to awdl: When transmitting via WiFi over the router (not using peer-to-peer), there are periodic interruptions when the wireless card on the device changes channels for awdl polling. This is resolved by changing the 5GHz WiFi channel on the router to channel 149 (or disabling AWDL altogether which is not really feasible). In order to work around number 1, I decided to build in an option to toggle/prefer peer-to-peer transmission in the app thinking that if everything goes over a peer-to-peer connection the jitter caused from the channel switching should go away. This also works, but with an important caveat. The default transmission is extremely choppy until you take an OS action that “elevates” the AWDL connection into “realtime” mode. I am using includePeerToPeer on the listener, browser, and connection as well as serviceClass interactiveVideo. For number 1, you can understand that asking users to change the channel on their router is not a great user experience, but the problem is the peer-to-peer connection workaround is also not great by default. For number 2, as an example of the behavior, I can send a stream from my Mac to my iPad over a peer-to-peer connection and it works but the video is very choppy until I move my cursor from my Mac to my iPad to trigger Universal Control. I captured the OS logs while doing this and can confirm that something happens to trigger “realtime” mode on the AWDL connection. After that, the streaming is totally smooth with zero latency. Some log samples: 2026-03-19 12:42:01.277968-0400 0x1ae294c Default 0x0 495 3 rapportd: (CoreUtils) [com.apple.rapport:CLinkD] Update client from UniversalControl:697 2026-03-19 12:42:01.278031-0400 0x1ae294c Default 0x0 495 0 rapportd: (CoreUtils) [com.apple.CoreUtils:AsyncCnx] CLinkCnx-6089: Connect start: 'CLink-ed3b9618b4e0._companion-link._tcp.local.%13' 2026-03-19 12:42:01.278149-0400 0x1ae294c Default 0x0 495 0 rapportd: (CoreUtils) [com.apple.CoreUtils:AsyncCnx] CLinkCnx-6089: Querying SRV CLink-ed3b9618b4e0._companion-link._tcp.local.%13 2026-03-19 12:42:01.279454-0400 0x1ae253a Info 0x0 382 0 wifip2pd: [com.apple.awdl:datapathInitiator] Created AWDLDatapathInitiator clink-ed3b9618b4e0._companion-link._tcp.local <To: 2e:f2:5a:15:76:52> 2026-03-19 12:42:01.279498-0400 0x1ae294c Default 0x0 495 0 rapportd: (CoreUtils) [com.apple.CoreUtils:AsyncCnx] CLinkCnx-6089: Resolving DNS f970afcc-1f1c-47af-a3f3-0236c9f9bbb0.local.%13 2026-03-19 12:42:01.279588-0400 0x1ae253a Default 0x0 382 0 wifip2pd: [com.apple.awdl:datapathInitiator] AWDLDatapathInitiator clink-ed3b9618b4e0._companion-link._tcp.local <To: 2e:f2:5a:15:76:52> was started 2026-03-19 12:42:01.282537-0400 0x1ae294c Default 0x0 495 0 rapportd: (Network) [com.apple.network:path] nw_path_evaluator_start [5C54D967-624D-4269-B080-6C7AE63218C7 IPv6#1e905043%awdl0.49154 generic, attribution: developer] path: satisfied (Path is satisfied), interface: awdl0[802.11], dns, uses wifi 2026-03-19 12:42:01.596450-0400 0x1ae253a Debug 0x0 382 0 wifip2pd: [com.apple.awdl:driver] Received event realtimeMode 2026-03-19 12:42:01.596589-0400 0x1ae253a Default 0x0 382 0 wifip2pd: [com.apple.awdl:interface] Realtime mode updated true I noticed that on iOS 26 and iPadOS 26 a realtime mode was added specifically to the Wi-Fi Aware API which I assume does what I want: https://developer.apple.com/documentation/wifiaware/waperformancemode/realtime, but I am looking for a solution that works with the existing network API and also on previous OS versions. I have already tried a lot of things, but is there any way to programmatically trigger “realtime” mode? For additional context, the goal here is to have extremely low latency that also works for gaming. The actual latency introduced in 1 is approximately 30-50ms around once a second… adding a buffer to the stream makes the video completely smooth, but the extra delay on the receiver end is not acceptable for this use case. Any help or ideas would be appreciated. I can’t easily share a reproduce case right now, and even if I could, getting multiple devices into the exact state along with the router configuration in order to reproduce is going to be pretty difficult anyway.
3
0
147
2w
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.3k
1w
Sporadic "no route to host" over ssh
When connecting to my M1 mac mini over ssh, certain programs are often unable to reach network destinations in the corporate LAN, although they can usually reach external addresses like www.apple.com. For example, a java program attempting to download from teamcity.dev.corp.com:8111 often fails like: java.net.NoRouteToHostException: No route to host Running the exact same command from the Apple Terminal program works like normal, simply connecting over ethernet on en0 to a TeamCity server inside the same building. Basic diagnostics from the ssh session do not show anything unusual: > traceroute teamcity.dev.corp.com traceroute to teamcity.dev.corp.com (10.21.4.1), 64 hops max, 40 byte packets 1 teamcity.dev.corp.com (10.21.4.1) 1.702 ms 0.409 ms 0.336 ms > route -n get teamcity.dev.corp.com route to: 10.21.4.1 destination: 10.21.4.1 interface: en0 flags: <UP,HOST,DONE,LLINFO,WASCLONED,IFSCOPE,IFREF> recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire 0 0 0 0 0 0 1500 1194 > uname -a Darwin mac 25.1.0 Darwin Kernel Version 25.1.0: Mon Oct 20 19:32:47 PDT 2025; root:xnu-12377.41.6~2/RELEASE_ARM64_T8103 arm64 Similar problems occur in docker commands to a remote daemon ("no route to host" or "connection refused"): docker -H tcp://<ip>:<port> ... Most other programs are never affected by this problem. Are there other diagnostic steps that might reveal the cause?
3
0
138
Jan ’26
CallKit and PushToTalk related changes in iOS 26
Starting in iOS 26, two notable changes have been made to CallKit, LiveCommunicationKit, and the PushToTalk framework: As a diagnostic aid, we're introducing new dialogs to warn apps of voip push related issue, for example when they fail to report a call or when when voip push delivery stops. The specific details of that behavior are still being determined and are likely to change over time, however, the critical point here is that these alerts are only intended to help developers debug and improve their app. Because of that, they're specifically tied to development and TestFlight signed builds, so the alert dialogs will not appear for customers running app store builds. The existing termination/crashes will still occur, but the new warning alerts will not appear. As PushToTalk developers have previously been warned, the last unrestricted PushKit entitlement ("com.apple.developer.pushkit.unrestricted-voip.ptt") has been disabled in the iOS 26 SDK. ALL apps that link against the iOS 26 SDK which receive a voip push through PushKit and which fail to report a call to CallKit will be now be terminated by the system, as the API contract has long specified. __ Kevin Elliott DTS Engineer, CoreOS/Hardware
0
0
1k
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
56
Activity
Jan ’26
Flow Divert behavior
Hello, Our app uses Network Extension / Packet Tunnel Provider to establish VPN connections on macOS and iOS. We have observed that after creating a utun device and adding any IPv4 routes (NEPacketTunnelNetworkSettings.IPv4Settings), the OS automatically adds several host routes via utun to services such as Akamai, Apple Push, etc. These routes appear to correspond to TCP flows that were active at the moment the VPN connection was established. When a particular TCP flow ends, the corresponding host route is deleted. We understand this is likely intended to avoid breaking existing TCP connections. However, we find the behavior of migrating existing TCP flows to the new utun interface simply because any IPv4 route is added somewhat questionable. This approach would make sense in a "full-tunnel" scenario — for example, when all IPv4 traffic (e.g., 0.0.0.0/0) is routed through the tunnel — but not necessarily in a "split-tunnel" configuration where only specific IPv4 routes are added. Is there any way to control or influence this behavior? Would it be possible for FlowDivert to differentiate between full-tunnel and split-tunnel cases, and only preserve existing TCP flows via utun in the full-tunnel scenario? Thank you.
Replies
0
Boosts
0
Views
119
Activity
Apr ’25
On FTP
Questions about FTP crop up from time-to-time here on DevForums. In most cases I write a general “don’t use FTP” response, but I don’t have time to go into all the details. I’ve created this post as a place to collect all of those details, so I can reference them in other threads. IMPORTANT Apple’s official position on FTP is: All our FTP APIs have been deprecated, and you should avoid using deprecated APIs. Apple has been slowly removing FTP support from the user-facing parts of our system. The most recent example of this is that we removed the ftp command-line tool in macOS 10.13. You should avoid the FTP protocol and look to adopt more modern alternatives. The rest of this post is an informational explanation of the overall FTP picture. This post is locked so I can keep it focused. If you have questions or comments, please do create a new thread in the App & System Services > Networking subtopic and I’ll respond there. Don’t Use FTP FTP is a very old and very crufty protocol. Certain things that seem obvious to us now — like being able to create a GUI client that reliably shows a directory listing in a platform-independent manner — aren’t possible to do in FTP. However, by far the biggest problem with FTP is that it provides no security [1]. Specifically, the FTP protocol: Provides no on-the-wire privacy, so anyone can see the data you transfer Provides no client-authenticates-server authentication, so you have no idea whether you’re talking to the right server Provides no data integrity, allowing an attacker to munge your data in transit Transfers user names and passwords in the clear Using FTP for anonymous downloads may be acceptable (see the explanation below) but most other uses of FTP are completely inappropriate for the modern Internet. IMPORTANT You should only use FTP for anonymous downloads if you have an independent way to check the integrity of the data you’ve downloaded. For example, if you’re downloading a software update, you could use code signing to check its integrity. If you don’t check the integrity of the data you’ve downloaded, an attacker could substitute a malicious download instead. This would be especially bad in, say, the software update case. These fundamental problems with the FTP protocol mean that it’s not a priority for Apple. This is reflected in the available APIs, which is the subject of the next section. FTP APIs Apple provides two FTP APIs: All Apple platforms provide FTP downloads via URLSession. Most Apple platforms (everything except watchOS) support CFFTPStream, which allows for directory listings, downloads, uploads, and directory creation. All of these FTP APIs are now deprecated: URLSession was deprecated for the purposes of FTP in the 2022 SDKs (macOS 13, iOS 16, iPadOS 16, tvOS 16, watchOS 9) [2]. CFFTPStream was deprecated in the 2016 SDKs (macOS 10.11, iOS 9, iPadOS 9, tvOS 9). CFFTPStream still works about as well as it ever did, which is not particularly well. Specifically: There is at least one known crashing bug (r. 35745763), albeit one that occurs quite infrequently. There are clear implementation limitations — like the fact that CFFTPCreateParsedResourceListing assumes a MacRoman text encoding (r. 7420589) — that won’t be fixed. If you’re looking for an example of how to use these APIs, check out SimpleFTPSample. Note This sample hasn’t been updated since 2013 and is unlikely to ever be updated given Apple’s position on FTP. The FTP support in URLSession has significant limitations: It only supports FTP downloads; there’s no support for uploads or any other FTP operations. It doesn’t support resumable FTP downloads [3]. It doesn’t work in background sessions. That prevents it from running FTP downloads in the background on iOS. It’s only supported in classic loading mode. See the usesClassicLoadingMode property and the doc comments in <Foundation/NSURLSession.h>. If Apple’s FTP APIs are insufficient for your needs, you’ll need to write or acquire your own FTP library. Before you do that, however, consider switching to an alternative protocol. After all, if you’re going to go to the trouble of importing a large FTP library into your code base, you might as well import a library for a better protocol. The next section discusses some options in this space. Alternative Protocols There are numerous better alternatives to FTP: HTTPS is by far the best alternative to FTP, offering good security, good APIs on Apple platforms, good server support, and good network compatibility. Implementing traditional FTP operations over HTTPS can be a bit tricky. One possible way forward is to enable DAV extensions on the server. FTPS is FTP over TLS (aka SSL). While FTPS adds security to the protocol, which is very important, it still inherits many of FTP’s other problems. Personally I try to avoid this protocol. SFTP is a file transfer protocol that’s completely unrelated to FTP. It runs over SSH, making it a great alternative in many of the ad hoc setups that traditionally use FTP. Apple doesn’t have an API for either FTPS or SFTP, although on macOS you may be able to make some headway by invoking the sftp command-line tool. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" [1] In another thread someone asked me about FTP’s other problems, those not related to security, so let’s talk about that. One of FTP’s implicit design goals was to provide cross-platform support that exposes the target platform. You can think of FTP as being kinda like telnet. When you telnet from Unix to VMS, it doesn’t aim to abstract away VMS commands, so that you can type Unix commands at the VMS prompt. Rather, you’re expected to run VMS commands. FTP is (a bit) like that. This choice made sense back when the FTP protocol was invented. Folks were expecting to use FTP via a command-line client, so there was a human in the loop. If they ran a command and it produced VMS-like output, that was fine because they knew that they were FTPing into a VMS machine. However, most users today are using GUI clients, and this design choice makes it very hard to create a general GUI client for FTP. Let’s consider the simple problem of getting the contents of a directory. When you send an FTP LIST command, the server would historically run the platform native directory list command and pipe the results back to you. To create a GUI client you have to parse that data to extract the file names. Doing that is a serious challenge. Indeed, just the first step, working out the text encoding, is a challenge. Many FTP servers use UTF-8, but some use ISO-Latin-1, some use other standard encodings, some use Windows code pages, and so on. I say “historically” above because there have been various efforts to standardise this stuff, both in the RFCs and in individual server implementations. However, if you’re building a general client you can’t rely on these efforts. After all, the reason why folks continue to use FTP is because of it widespread support. [2] To quote the macOS 13 Ventura Release Notes: FTP is deprecated for URLSession and related APIs. Please adopt modern secure networking protocols such as HTTPS. (92623659) [3] Although you can implement resumable downloads using the lower-level CFFTPStream API, courtesy of the kCFStreamPropertyFTPFileTransferOffset property. Revision History 2025-10-06 Explained that URLSession only supports FTP in classic loading mode. Made other minor editorial changes. 2024-04-15 Added a footnote about FTP’s other problems. Made other minor editorial changes. 2022-08-09 Noted that the FTP support in URLSession is now deprecated. Made other minor editorial changes. 2021-04-06 Fixed the formatting. Fixed some links. 2018-02-23 First posted.
Replies
0
Boosts
0
Views
5.8k
Activity
Oct ’25
iPhone App 进行网络请求的时候出错,报错信息为:未能完成该操作。设备上无剩余空间
1、已经检查过手机的存储空间,还有一百多G的空间。app端进行网络接口情况的时候报错了,报错信息如下: Error : Error Domain=NSPOSIXErrorDomain Code=28 "No space left on device" UserInfo={_NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <7DB1CBFD-B9BE-422D-9C9A-78D8FC04DC1B>.<76>, _kCFStreamErrorDomainKey=1, _kCFStreamErrorCodeKey=28, _NSURLErrorRelatedURLSessionTaskErrorKey=( "LocalDataTask <7DB1CBFD-B9BE-422D-9C9A-78D8FC04DC1B>.<76>" ), _NSURLErrorNWPathKey=satisfied (Path is satisfied), interface: pdp_ip0[lte], ipv4, ipv6, dns, expensive, estimated upload: 65536Bps, uses cell} 2、手机型号是iPhone 15 Plus,iOS 17.6.1
Replies
2
Boosts
0
Views
418
Activity
Jun ’25
What does iOS do wrt Shared Web Credentials when it makes a call to a server to perform a message filter request
In order to create a Message Filter Extension it is necessary to set up Shared Web Credentials. I'd like to form an understanding of what role SWC plays when the OS is making request to the associated network service (when the extension has called deferQueryRequestToNetwork()) and how this differs from when an app directly uses Shared Web Credentials itself. When an app is making direct use of SWC, it makes a request to obtain the user's credentials from the web site. However in the case of a Message Filter Extension, there aren't any individual user credentials, so what is happening behind the scenes when the OS makes a server request on behalf of a Message Filtering Extension? A more general question - the documentation for Shared Web Credentials says "Associated domains establish a secure association between domains and your app.". Thank you
Replies
2
Boosts
0
Views
477
Activity
Apr ’25
Content filtering
Hello team, Would this mean that content filters intended for all browsing can only be implemented for managed devices using MDM? My goal would be to create a content filtering app for all users, regardless of if their device is managed/supervised. thanks.
Replies
1
Boosts
0
Views
109
Activity
Jan ’26
Pair iOS Central with MacOS Peripheral for encrypted characteristic
Is this even possible? Instead of any pairing dialog appearing, my central code get the "Authentication is insufficient" error when reading the characteristic. My peripheral (in the macOS app) code uses the .notifyEncryptionRequired property and uses .readEncryptionRequired and .writeEncryptionRequired permissions. No descriptors are set, but I think they get added automatically since this characteristic notifies. 2900 and 2902 descriptors are set by the peripheral/CoreBluetooth. If the Mac and iPhone are using the same Apple ID does that affect pairing?
Replies
0
Boosts
0
Views
94
Activity
Feb ’26
https address of a certain page within my app
I need to know the https address of a certain page within my app. This is going to be used as a redirect URL. I don't think it is a good idea to use deep links because it has to be an https address. I don't think Universal Links will work because it is not my website that I will be communicating with.
Replies
1
Boosts
0
Views
178
Activity
Jun ’25
URL Filter OHTTP Gateway
Hello team, We are using below example https://github.com/apple/pir-service-example as a starting point to setup PIR server for our backend, but I am not really understanding what else we need in this example to configure OHTTP gateway. Any help will be appreciated.
Replies
1
Boosts
0
Views
52
Activity
1w
Does app launch recency affect NEPacketTunnelProvider, HotspotHelper, or NEHotspotManager functionality?
We are assisting a client with their app integration. The client believes that NEPacketTunnelProvider, NEHotspotHelper, and NEHotspotManager extensions stop functioning if the containing app hasn't been launched by the user within some recent window (e.g. 30, 60, or 90 days). We haven't been able to find any documentation supporting this claim. Specifically, we'd like to know: Is there any app launch recency requirement that would cause iOS to stop invoking a registered NEHotspotHelper or NEHotspotManager configuration? Is there any app launch recency requirement that would cause iOS to tear down or prevent activation of a NEPacketTunnelProvider? More generally, does iOS enforce any kind of "staleness" check on apps that provide Network Extension or Hotspot-related functionality, where not being foregrounded for some period causes the system to stop honoring their registrations? If such a mechanism exists, we'd appreciate any pointers to documentation or technical notes describing the behavior and timeframes involved. If it doesn't exist, confirmation would help us guide our client's debugging in the right direction. Thank you.
Replies
1
Boosts
0
Views
75
Activity
Mar ’26
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
70
Activity
3w
URL Filter Prefetch Interval guarantee
Hello, I have implemented a URL Filter using the sample provided here: Filtering Traffic by URL. I am also using an App Group to dynamically manage the Bloom filter and block list data. However, when I update my block list URLs and create a new Bloom filter plist in the App Group, the extension does not seem to use the updated Bloom filter even after the prefetch interval expires. Also for testing purpose can I keep this interval to 10 mins or below ?
Replies
3
Boosts
0
Views
261
Activity
2w
About the Relay payload in iOS configuration profiles
Are the network relays introduced in 2023 and https://developer.apple.com/videos/play/wwdc2023/10002/ the same thing as the Private Relay introduced in 2021? https://developer.apple.com/videos/play/wwdc2021/10096/ We are considering verifying the relay function, but we are not sure whether they are the same function or different functions. https://developer.apple.com/documentation/devicemanagement/relay?language=objc
Replies
0
Boosts
0
Views
61
Activity
Apr ’25
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
425
Activity
May ’25
Triggering “realtime” mode for peer-to-peer WiFi via awdl to fix jitter problems
This is a bit complicated to explain so bare with me. I am working on building an app that allows you to send real time video/camera captures from one Apple device to another. I am using a custom UDP protocol built on top of NWListener, NWBrowser, and NWConnection APIs. It works fine, but there are a few issues that seems to all be related to awdl: When transmitting via WiFi over the router (not using peer-to-peer), there are periodic interruptions when the wireless card on the device changes channels for awdl polling. This is resolved by changing the 5GHz WiFi channel on the router to channel 149 (or disabling AWDL altogether which is not really feasible). In order to work around number 1, I decided to build in an option to toggle/prefer peer-to-peer transmission in the app thinking that if everything goes over a peer-to-peer connection the jitter caused from the channel switching should go away. This also works, but with an important caveat. The default transmission is extremely choppy until you take an OS action that “elevates” the AWDL connection into “realtime” mode. I am using includePeerToPeer on the listener, browser, and connection as well as serviceClass interactiveVideo. For number 1, you can understand that asking users to change the channel on their router is not a great user experience, but the problem is the peer-to-peer connection workaround is also not great by default. For number 2, as an example of the behavior, I can send a stream from my Mac to my iPad over a peer-to-peer connection and it works but the video is very choppy until I move my cursor from my Mac to my iPad to trigger Universal Control. I captured the OS logs while doing this and can confirm that something happens to trigger “realtime” mode on the AWDL connection. After that, the streaming is totally smooth with zero latency. Some log samples: 2026-03-19 12:42:01.277968-0400 0x1ae294c Default 0x0 495 3 rapportd: (CoreUtils) [com.apple.rapport:CLinkD] Update client from UniversalControl:697 2026-03-19 12:42:01.278031-0400 0x1ae294c Default 0x0 495 0 rapportd: (CoreUtils) [com.apple.CoreUtils:AsyncCnx] CLinkCnx-6089: Connect start: 'CLink-ed3b9618b4e0._companion-link._tcp.local.%13' 2026-03-19 12:42:01.278149-0400 0x1ae294c Default 0x0 495 0 rapportd: (CoreUtils) [com.apple.CoreUtils:AsyncCnx] CLinkCnx-6089: Querying SRV CLink-ed3b9618b4e0._companion-link._tcp.local.%13 2026-03-19 12:42:01.279454-0400 0x1ae253a Info 0x0 382 0 wifip2pd: [com.apple.awdl:datapathInitiator] Created AWDLDatapathInitiator clink-ed3b9618b4e0._companion-link._tcp.local <To: 2e:f2:5a:15:76:52> 2026-03-19 12:42:01.279498-0400 0x1ae294c Default 0x0 495 0 rapportd: (CoreUtils) [com.apple.CoreUtils:AsyncCnx] CLinkCnx-6089: Resolving DNS f970afcc-1f1c-47af-a3f3-0236c9f9bbb0.local.%13 2026-03-19 12:42:01.279588-0400 0x1ae253a Default 0x0 382 0 wifip2pd: [com.apple.awdl:datapathInitiator] AWDLDatapathInitiator clink-ed3b9618b4e0._companion-link._tcp.local <To: 2e:f2:5a:15:76:52> was started 2026-03-19 12:42:01.282537-0400 0x1ae294c Default 0x0 495 0 rapportd: (Network) [com.apple.network:path] nw_path_evaluator_start [5C54D967-624D-4269-B080-6C7AE63218C7 IPv6#1e905043%awdl0.49154 generic, attribution: developer] path: satisfied (Path is satisfied), interface: awdl0[802.11], dns, uses wifi 2026-03-19 12:42:01.596450-0400 0x1ae253a Debug 0x0 382 0 wifip2pd: [com.apple.awdl:driver] Received event realtimeMode 2026-03-19 12:42:01.596589-0400 0x1ae253a Default 0x0 382 0 wifip2pd: [com.apple.awdl:interface] Realtime mode updated true I noticed that on iOS 26 and iPadOS 26 a realtime mode was added specifically to the Wi-Fi Aware API which I assume does what I want: https://developer.apple.com/documentation/wifiaware/waperformancemode/realtime, but I am looking for a solution that works with the existing network API and also on previous OS versions. I have already tried a lot of things, but is there any way to programmatically trigger “realtime” mode? For additional context, the goal here is to have extremely low latency that also works for gaming. The actual latency introduced in 1 is approximately 30-50ms around once a second… adding a buffer to the stream makes the video completely smooth, but the extra delay on the receiver end is not acceptable for this use case. Any help or ideas would be appreciated. I can’t easily share a reproduce case right now, and even if I could, getting multiple devices into the exact state along with the router configuration in order to reproduce is going to be pretty difficult anyway.
Replies
3
Boosts
0
Views
147
Activity
2w
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.3k
Activity
1w
Sporadic "no route to host" over ssh
When connecting to my M1 mac mini over ssh, certain programs are often unable to reach network destinations in the corporate LAN, although they can usually reach external addresses like www.apple.com. For example, a java program attempting to download from teamcity.dev.corp.com:8111 often fails like: java.net.NoRouteToHostException: No route to host Running the exact same command from the Apple Terminal program works like normal, simply connecting over ethernet on en0 to a TeamCity server inside the same building. Basic diagnostics from the ssh session do not show anything unusual: > traceroute teamcity.dev.corp.com traceroute to teamcity.dev.corp.com (10.21.4.1), 64 hops max, 40 byte packets 1 teamcity.dev.corp.com (10.21.4.1) 1.702 ms 0.409 ms 0.336 ms > route -n get teamcity.dev.corp.com route to: 10.21.4.1 destination: 10.21.4.1 interface: en0 flags: <UP,HOST,DONE,LLINFO,WASCLONED,IFSCOPE,IFREF> recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire 0 0 0 0 0 0 1500 1194 > uname -a Darwin mac 25.1.0 Darwin Kernel Version 25.1.0: Mon Oct 20 19:32:47 PDT 2025; root:xnu-12377.41.6~2/RELEASE_ARM64_T8103 arm64 Similar problems occur in docker commands to a remote daemon ("no route to host" or "connection refused"): docker -H tcp://<ip>:<port> ... Most other programs are never affected by this problem. Are there other diagnostic steps that might reveal the cause?
Replies
3
Boosts
0
Views
138
Activity
Jan ’26
URLSession basic auth question
How do I make a basic request with URLSession? See https://stackoverflow.com/questions/30573898 for reference. Also https://developer.apple.com/documentation/ has details.
Replies
1
Boosts
0
Views
92
Activity
1w
URLSession concurrent requests performance question
URLSession question
Replies
1
Boosts
0
Views
94
Activity
1w
CallKit and PushToTalk related changes in iOS 26
Starting in iOS 26, two notable changes have been made to CallKit, LiveCommunicationKit, and the PushToTalk framework: As a diagnostic aid, we're introducing new dialogs to warn apps of voip push related issue, for example when they fail to report a call or when when voip push delivery stops. The specific details of that behavior are still being determined and are likely to change over time, however, the critical point here is that these alerts are only intended to help developers debug and improve their app. Because of that, they're specifically tied to development and TestFlight signed builds, so the alert dialogs will not appear for customers running app store builds. The existing termination/crashes will still occur, but the new warning alerts will not appear. As PushToTalk developers have previously been warned, the last unrestricted PushKit entitlement ("com.apple.developer.pushkit.unrestricted-voip.ptt") has been disabled in the iOS 26 SDK. ALL apps that link against the iOS 26 SDK which receive a voip push through PushKit and which fail to report a call to CallKit will be now be terminated by the system, as the API contract has long specified. __ Kevin Elliott DTS Engineer, CoreOS/Hardware
Replies
0
Boosts
0
Views
1k
Activity
Jun ’25