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

Performance degradation of HTTP/3 requests in iOS app under specific network conditions
Hello Apple Support Team, We are experiencing a performance issue with HTTP/3 in our iOS application during testing. Problem Description: Network requests using HTTP/3 are significantly slower than expected. This issue occurs on both Wi-Fi and 4G networks, with both IPv4 and IPv6. The same setup worked correctly in an earlier experiment. Key Observations: The slowdown disappears when the device uses: · A personal hotspot. · Network Link Conditioner (with no limitations applied). · Internet sharing from a MacBook via USB (where traffic was also inspected with Wireshark without issues). The problem is specific to HTTP/3 and does not occur with HTTP/2. The issue is reproducible on iOS 15, 18.7, and the latest iOS 26 beta. HTTP/3 is confirmed to be active (via assumeHttp3Capable and Alt-Svc header). Crucially, the same backend endpoint works with normal performance on Android devices and using curl with HTTP/3 support from the same network. I've checked the CFNetwork logs in the Console but haven't found any suspicious errors or obvious clues that explain the slowdown. We are using a standard URLSession with basic configuration. Attempted to collect qlog diagnostics by setting the QUIC_LOG_DIRECTORY=~/ tmp environment variable, but the logs were not generated. Question: What could cause HTTP/3 performance to improve only when the device is connected through a hotspot, unrestricted Network Link Conditioner, or USB-tethered connection? The fact that Android and curl work correctly points to an issue specific to the iOS network stack. Are there known conditions or policies (e.g., related to network interface handling, QoS, or specific packet processing) that could lead to this behavior? Additionally, why might the qlog environment variable fail to produce logs, and are there other ways to obtain detailed HTTP/3 diagnostic information from iOS? Any guidance on further diagnostic steps or specific system logs to examine would be greatly appreciated. Thank you for your assistance.
6
0
468
Nov ’25
Disable URLSession auto retry policy
We are developing an iOS application that is interacting with HTTP APIs that requires us to put a unique UUID (a nonce) as an header on every request (obviously there's more than that, but that's irrilevant to the question here). If the same nonce is sent on two subsequent requests the server returns a 412 error. We should avoid generating this kind of errors as, if repeated, they may be flagged as a malicious activity by the HTTP APIs. We are using URLSession.shared.dataTaskPublisher(for: request) to call the HTTP APIs with request being generated with the unique nonce as an header. On our field tests we are seeing a few cases of the same HTTP request (same nonce) being repeated a few seconds on after the other. Our code has some retry logic only on 401 errors, but that involves a token refresh, and this is not what we are seeing from logs. We were able to replicate this behaviour on our own device using Network Link Conditioner with very bad performance, with XCode's Network inspector attached we can be certain that two HTTP requests with identical headers are actually made automatically, the first request has an "End Reason" of "Retry", the second is "Success" with Status 412. Our questions are: can we disable this behaviour? can we provide a new request for the retry (so that we can update headers)? Thanks, Francesco
7
3
357
Aug ’25
AccessorySetupKit – WiFi picker – show accessories after factory reset?
Hi there, We’re developing a companion app for a smart home product that communicates over the user’s local network. To provision the device, it initially creates its own Wi-Fi network. The user joins this temporary network and enters their home Wi-Fi credentials via our app. The app then sends those credentials directly to the device, which stores them and connects to the local network for normal operation. We’re using AccessorySetupKit to discover nearby devices (via SSID prefix) and NEHotspotManager to join the accessory’s Wi-Fi network once the user selects it. This workflow works well in general. However, we’ve encountered a problem: if the user factory-resets the accessory, or needs to restart setup (for example, after entering the wrong Wi-Fi password), the device no longer appears in the accessory picker. In iOS 18, we were able to work around this by calling removeAccessory() after the device is selected. This forces the picker to always display the accessory again. But in iOS 26, a new confirmation dialog now appears when calling removeAccessory(), which confuses users during setup. We’re looking for a cleaner way to handle this scenario — ideally a way to make the accessory rediscoverable without prompting the user to confirm removal. Thanks for your time and guidance.
0
3
241
Nov ’25
Content Filter Permission Prompt Not Appearing in TestFlight
I added a Content Filter to my app, and when running it in Xcode (Debug/Release), I get the expected permission prompt: "Would like to filter network content (Allow / Don't Allow)". However, when I install the app via TestFlight, this prompt doesn’t appear at all, and the feature doesn’t work. Is there a special configuration required for TestFlight? Has anyone encountered this issue before? Thanks!
23
1
1.1k
2w
When updating a VPN app with `includeAllNetworks`, the newer instance of the packet tunnel is not started via on-demand rules
When installing a new version the app while a tunnel is connected, seemingly the old packet tunnel process gets stopped but the new one does not come back up. Reportedly, a path monitor is reporting that the device has no connectivity. Is this the expected behavior? When installing an update from TestFlight or the App store, the packet tunnel instance from the old tunnel is stopped, but, due to the profile being on-demand and incldueAllNetworks, the path monitoring believes the device has no connectivity - so the new app is never downloaded. Is this the expected behavior? During development, the old packet tunnel gets stopped, the new app is installed, but the new packet tunnel is never started. To start it, the user has to toggle the VPN twice from the Settings app. The tunnel could be started from the VPN app too, if we chose to not take the path monitor into account, but then the user still needs to attempt to start the tunnel twice - it only works on the second try. As far as we can tell, the first time around, the packet tunnel never gets started, the app receives an update about NEVPNStatus being set to disconnecting yet NEVPNConnection does not throw. The behavior I was naively expecting was that the packet tunnel process would be stopped only when the new app is fully downloaded and when the update is installed, Are we doing something horribly wrong here?
7
3
657
Jan ’26
Bluetooth 5 Coded PHY (Long Range) removed in iOS 14
I am pretty sure iOS 13.4 (beta and later) did support Coded PHY (Long Range). Tested devices are iPhone SE2 and iPhone 11 Pro. However, it seems iOS 14 removed the support of Coded PHY, accidentally or on purpose, I don't know? The same PHY update request returns "1M PHY" in iOS 14, but "Coded PHY" in iOS 13 (13.4 beta and later). Anyone knows why? Samson
10
1
5.9k
Oct ’25
Title: DNS Proxy Not Capturing Traffic When Public DNS Is Set in WiFi Settings
I'm working on a Network Extension using NEDNSProxyProvider to inspect DNS traffic. However, I've run into a couple of issues: DNS Proxy is not capturing traffic when a public DNS (like 8.8.8.8 or 1.1.1.1) is manually configured in the WiFi settings. It seems like the system bypasses the proxy in this case. Is this expected behavior? Is there a way to force DNS traffic through the proxy even if a public DNS is set? Using DNS Proxy and DNS Settings simultaneously doesn't work. Is there a known limitation or a correct way to combine these? How to set DNS or DNSSettings using DNSProxy? import NetworkExtension import SystemExtensions import SwiftUI protocol DNSProxyManagerDelegate { func managerStateDidChange(_ manager: DNSProxyManager) } class DNSProxyManager: NSObject { private let manager = NEDNSProxyManager.shared() var delegate: DNSProxyManagerDelegate? private(set) var isEnabled: Bool = false { didSet { delegate?.managerStateDidChange(self) } } var completion: (() -> Void)? override init() { super.init() self.load() } func toggle() { isEnabled ? disable() : start() } private func start() { let request = OSSystemExtensionRequest .activationRequest(forExtensionWithIdentifier: Constants.extensionBundleID, queue: DispatchQueue.main) request.delegate = self OSSystemExtensionManager.shared.submitRequest(request) log.info("Submitted extension activation request") } private func enable() { update { self.manager.localizedDescription = "DNS Proxy" let proto = NEDNSProxyProviderProtocol() proto.providerBundleIdentifier = Constants.extensionBundleID self.manager.providerProtocol = proto self.manager.isEnabled = true } } private func disable() { update { self.manager.isEnabled = false } } private func remove() { update { self.manager.removeFromPreferences { _ in self.isEnabled = self.manager.isEnabled } } } private func update(_ body: @escaping () -> Void) { self.manager.loadFromPreferences { (error) in if let error = error { log.error("Failed to load DNS manager: \(error)") return } self.manager.saveToPreferences { (error) in if let error = error { return } log.info("Saved DNS manager") self.isEnabled = self.manager.isEnabled } } } private func load() { manager.loadFromPreferences { error in guard error == nil else { return } self.isEnabled = self.manager.isEnabled } } } extension DNSProxyManager: OSSystemExtensionRequestDelegate { func requestNeedsUserApproval(_ request: OSSystemExtensionRequest) { log.info("Extension activation request needs user approval") } func request(_ request: OSSystemExtensionRequest, didFailWithError error: Error) { log.error("Extension activation request failed: \(error)") } func request(_ request: OSSystemExtensionRequest, foundProperties properties: [OSSystemExtensionProperties]) { log.info("Extension activation request found properties: \(properties)") } func request(_ request: OSSystemExtensionRequest, didFinishWithResult result: OSSystemExtensionRequest.Result) { guard result == .completed else { log.error("Unexpected result \(result.description) for system extension request") return } log.info("Extension activation request did finish with result: \(result.description)") enable() } func request(_ request: OSSystemExtensionRequest, actionForReplacingExtension existing: OSSystemExtensionProperties, withExtension ext: OSSystemExtensionProperties) -> OSSystemExtensionRequest.ReplacementAction { log.info("Existing extension willt be replaced: \(existing.bundleIdentifier) -> \(ext.bundleIdentifier)") return .replace } } import NetworkExtension class DNSProxyProvider: NEDNSProxyProvider { var handlers: [String: FlowHandler] = [:] var isReady = false let queue = DispatchQueue(label: "DNSProxyProvider") override func startProxy(options:[String: Any]? = nil, completionHandler: @escaping (Error?) -> Void) { completionHandler(nil) } override func stopProxy(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { completionHandler() } override func handleNewUDPFlow(_ flow: NEAppProxyUDPFlow, initialRemoteEndpoint remoteEndpoint: NWEndpoint) -> Bool { let id = shortUUID() handlers[id] = FlowHandler(flow: flow, remoteEndpoint: remoteEndpoint, id: id, delegate: self) return true } override func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool { return false } } class FlowHandler { let id: String let flow: NEAppProxyUDPFlow let remoteEndpoint: NWHostEndpoint let delegate: FlowHandlerDelegate private var connections: [String: RemoteConnection] = [:] private var pendingPacketsByDomain: [String: [(packet: Data, endpoint: NWEndpoint, uniqueID: String, timestamp: Date)]] = [:] private let packetQueue = DispatchQueue(label: "com.flowhandler.packetQueue") init(flow: NEAppProxyUDPFlow, remoteEndpoint: NWEndpoint, id: String, delegate: FlowHandlerDelegate) { log.info("Flow received for \(id) flow: \(String(describing: flow))") self.flow = flow self.remoteEndpoint = remoteEndpoint as! NWHostEndpoint self.id = id self.delegate = delegate defer { start() } } deinit { closeAll(nil) } func start() { flow.open(withLocalEndpoint: flow.localEndpoint as? NWHostEndpoint) { error in if let error = error { self.delegate.flowClosed(self) return } self.readFromFlow() } } func readFromFlow() { self.flow.readDatagrams { packets, endpoint, error in if let error = error { self.closeAll(error) return } guard let packets = packets, let endpoints = endpoint, !packets.isEmpty, !endpoints.isEmpty else { self.closeAll(nil) return } self.processFlowPackets(packets, endpoints) self.readFromFlow() } } } Any insights or suggestions would be greatly appreciated. Thanks!
2
3
345
Apr ’25
Title: Accessing Wi-Fi SSID for custom On-Demand logic in PacketTunnelProvider on macOS
We are developing a macOS VPN application using NEPacketTunnelProvider with a custom encryption protocol. We are using standard On-Demand VPN rules with Wi-Fi SSID matching but we want to add some additional feature to the native behaviour.  We want to control the 'conenect/disconnect' button status and allow the user to interact with the tunnel even when the on demand rule conditions are satisfied, is there a native way to do it? In case we need to implement our custom on-demand behaviour we need to access to this information: connected interface type ssid name and being informed when it changes so to trigger our logic, how to do it from the app side? we try to use CWWiFiClient along with ssidDidChangeForWiFiInterface monitoring, it returns just the interface name en0 and not the wifi ssid name. Is location access mandatory to access wifi SSID on macOS even if we have a NEPacketTunnelProvider? Please note that we bundle our Network Extension as an App Extension (not SystemExtension).
9
2
391
Jan ’26
Network Extension App for MacOS with 3 Extensions
Hi All, I am currently working on a Network Extension App for MacOS using 3 types of extensions provided by Apple's Network Extension Framework. Content Filter, App Proxy (Want to get/capture/log all HTTP/HTTPS traffic), DNS Proxy (Want to get/capture/log all DNS records). Later parse into human readable format. Is my selection of network extension types correct for the intended logs I need? I am able to run with one extension: Main App(Xcode Target1) <-> Content Filter Extension. Here there is a singleton class IPCConnection between App(ViewController.swift) which is working fine with NEMachServiceName from Info.plist of ContentFilter Extension(Xcode Target2) However, when I add an App Proxy extension as a new Xcode Target3, I think the App and extension's communication getting messed up and App not getting started/Crashing. Here, In the same Main App, I am adding new separate IPCConnection for this extension. Here is the project organization/folder structure. MyNetworkExtension ├──MyNetworkExtension(Xcode Target1) │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── Info.plist │ ├── MyNetworkExtension.entitlement │ | ── Main │ |-----ViewController.swift │ └── Base.lproj │ └── Main.storyboard ├── ContentFilterExtension(Xcode Target2) │ ├── ContentFilterExtension.entitlement │ │ ├── FilterDataProvider.swift │ │ ├── Info.plist │ │ ├── IPCConnection.swift │ │ └── main.swift ├── AppProxyProviderExtension(Xcode Target3) │ ├── AppProxyProviderExtension.entitlement │ │ ├── AppProxyIPCConnection.swift │ │ ├── AppProxyProvider.swift │ │ ├── Info.plist │ │ └── main.swift └── Frameworks ├── libbsm.tbd └── NetworkExtension.framework Is my Approach for creating a single Network Extension App with Multiple extensions correct or is there any better approach of project organization that will make future modifications/working easier and makes the maintenance better? I want to keep the logic for each extension separate while having the same, single Main App that manages everything(installing, activating, managing identifiers, extensions, etc). What's the best approach to establish a Communication from MainApp to each extension separately, without affecting one another? Is it good idea to establish 3 separate IPC Connections(each is a singleton class) for each extension? Are there any suggestions you can provide that relates to my use case of capturing all the network traffic logs(including HTTP/HTTPS, DNS Records, etc), especially on App to Extension Communication, where my app unable to keep multiple IPC Connections and maintain them separately? I've been working on it for a while, and still unable to make the Network Extension App work with multiple extensions(each as a new Xcode target). Main App with single extension is working fine, but if I add new extension, App getting crashed. I suspect it's due to XPC/IPC connection things! I really appreciate any support on this either directly or by any suggestions/resources that will help me get better understand and make some progress. Please reach out if in case any clarifications or specific information that's needed to better understand my questions. Thank you very much
4
0
367
Sep ’25
Push notifications not delivered over Wi-Fi with includeAllNetworks = true regardless of excludeAPNS setting
We have a VPN app that uses NEPacketTunnelProvider with includeAllNetworks = true. We've encountered an issue where push notifications are not delivered over Wi-Fi while the tunnel is active in a pre-MFA quarantine state (tunnel is up but traffic is blocked on server side), regardless of whether excludeAPNS is set to true or false. Observed behavior Wi-Fi excludeAPNS = true - Notifications not delivered Wi-Fi excludeAPNS = false - Notifications not delivered Cellular excludeAPNS = true - Notifications delivered Cellular excludeAPNS = false - Notifications not delivered On cellular, the behavior matches our expectations: setting excludeAPNS = true allows APNS traffic to bypass the tunnel and notifications arrive; setting it to false routes APNS through the tunnel and notifications are blocked (as expected for a non-forwarding tunnel). On Wi-Fi, notifications fail to deliver in both cases. Our question Is this expected behavior when includeAllNetworks is enabled on Wi-Fi, or is this a known issue / bug with APNS delivery? Is there something else in the Wi-Fi networking path that includeAllNetworks affects beyond routing, which could prevent APNS from functioning even when the traffic is excluded from the tunnel? Sample Project Below is the minimal code that reproduces this issue. The project has two targets: a main app and a Network Extension. The tunnel provider captures all IPv4 and IPv6 traffic via default routes but does not forward packets — simulating a pre-MFA quarantine state. The main app configures the tunnel with includeAllNetworks = true and provides a UI toggle for excludeAPNS. PacketTunnelProvider.swift (Network Extension target): import NetworkExtension class PacketTunnelProvider: NEPacketTunnelProvider { override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) { let settings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "127.0.0.1") let ipv4 = NEIPv4Settings(addresses: ["198.51.100.1"], subnetMasks: ["255.255.255.0"]) ipv4.includedRoutes = [NEIPv4Route.default()] settings.ipv4Settings = ipv4 let ipv6 = NEIPv6Settings(addresses: ["fd00::1"], networkPrefixLengths: [64]) ipv6.includedRoutes = [NEIPv6Route.default()] settings.ipv6Settings = ipv6 let dns = NEDNSSettings(servers: ["198.51.100.1"]) settings.dnsSettings = dns settings.mtu = 1400 setTunnelNetworkSettings(settings) { error in if let error = error { completionHandler(error) return } self.readPackets() completionHandler(nil) } } private func readPackets() { packetFlow.readPackets { [weak self] packets, protocols in self?.readPackets() } } override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { completionHandler() } override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)?) { if let handler = completionHandler { handler(messageData) } } override func sleep(completionHandler: @escaping () -> Void) { completionHandler() } override func wake() { } } ContentView.swift (Main app target) — trimmed to essentials: import SwiftUI import NetworkExtension struct ContentView: View { @State private var excludeAPNs = false @State private var manager: NETunnelProviderManager? var body: some View { VStack { Toggle("Exclude APNs", isOn: $excludeAPNs) .onChange(of: excludeAPNs) { Task { await saveAndReload() } } Button("Connect") { Task { await toggleVPN() } } } .padding() .task { await loadManager() } } private func loadManager() async { let managers = try? await NETunnelProviderManager.loadAllFromPreferences() if let existing = managers?.first { manager = existing } else { let m = NETunnelProviderManager() let proto = NETunnelProviderProtocol() proto.providerBundleIdentifier = "<your-extension-bundle-id>" proto.serverAddress = "127.0.0.1" proto.includeAllNetworks = true proto.excludeAPNs = excludeAPNs m.protocolConfiguration = proto m.localizedDescription = "TestVPN" m.isEnabled = true try? await m.saveToPreferences() try? await m.loadFromPreferences() manager = m } if let proto = manager?.protocolConfiguration as? NETunnelProviderProtocol { excludeAPNs = proto.excludeAPNs } } private func saveAndReload() async { guard let manager else { return } if let proto = manager.protocolConfiguration as? NETunnelProviderProtocol { proto.includeAllNetworks = true proto.excludeAPNs = excludeAPNs } manager.isEnabled = true try? await manager.saveToPreferences() try? await manager.loadFromPreferences() } private func toggleVPN() async { guard let manager else { return } if manager.connection.status == .connected { manager.connection.stopVPNTunnel() } else { await saveAndReload() try? manager.connection.startVPNTunnel() } } } Steps to reproduce Build and run the sample project with above code on a physical iOS device. Connect to a Wi-Fi network. Set excludeAPNS = true using the toggle and tap Connect. Send a push notification to the device to a test app with remote notification capability (e.g., via a test push service or the push notification console). Observe that the notification is not delivered. Disconnect. Switch to cellular. Reconnect with the same settings. Send the same push notification — observe that it is delivered. Environment iOS 26.2 Xcode 26.2 Physical device (iPhone 15 Pro)
5
1
274
Mar ’26
DNS Proxy system extension – OSSystemExtensionErrorDomain error 9 “validationFailed” on clean macOS machine
Hi, I’m implementing a macOS DNS Proxy as a system extension and running into a persistent activation error: OSSystemExtensionErrorDomain error 9 (validationFailed) with the message: extension category returned error This happens both on an MDM‑managed Mac and on a completely clean Mac (no MDM, fresh install). Setup macOS: 15.x (clean machine, no MDM) Xcode: 16.x Team ID: AAAAAAA111 (test) Host app bundle ID: com.example.agent.NetShieldProxy DNS Proxy system extension bundle ID: com.example.agent.NetShieldProxy.dnsProxy The DNS Proxy is implemented as a NetworkExtension system extension, not an app extension. Host app entitlements From codesign -d --entitlements :- /Applications/NetShieldProxy.app: xml com.apple.application-identifier AAAAAAA111.com.example.agent.NetShieldProxy <key>com.apple.developer.system-extension.install</key> <true/> <key>com.apple.developer.team-identifier</key> <string>AAAAAAA111</string> <key>com.apple.security.app-sandbox</key> <true/> <key>com.apple.security.application-groups</key> <array> <string>group.com.example.NetShieldmac</string> </array> <key>com.apple.security.files.user-selected.read-only</key> <true/> xml com.apple.application-identifier AAAAAAA111.com.example.agent.NetShieldProxy.dnsProxy <key>com.apple.developer.networking.networkextension</key> <array> <string>dns-proxy-systemextension</string> </array> <key>com.apple.developer.team-identifier</key> <string>AAAAAAA111</string> <key>com.apple.security.application-groups</key> <array> <string>group.com.example.NetShieldmac</string> <string>group.example.NetShieldmac</string> <string>group.example.agent.enterprise.macos</string> <string>group.example.com.NetShieldmac</string> </array> DNS Proxy system extension Info.plist On the clean Mac, from: bash plutil -p "/Applications/NetShieldProxy.app/Contents/Library/SystemExtensions/com.example.agent.NetShieldProxy.dnsProxy.systemextension/Contents/Info.plist" I get: json { "CFBundleExecutable" => "com.example.agent.NetShieldProxy.dnsProxy", "CFBundleIdentifier" => "com.example.agent.NetShieldProxy.dnsProxy", "CFBundleName" => "com.example.agent.NetShieldProxy.dnsProxy", "CFBundlePackageType" => "SYSX", "CFBundleShortVersionString" => "1.0.1.8", "CFBundleSupportedPlatforms" => [ "MacOSX" ], "CFBundleVersion" => "0.1.1", "LSMinimumSystemVersion" => "13.5", "NSExtension" => { "NSExtensionPointIdentifier" => "com.apple.dns-proxy", "NSExtensionPrincipalClass" => "com_example_agent_NetShieldProxy_dnsProxy.DNSProxyProvider" }, "NSSystemExtensionUsageDescription" => "SYSTEM_EXTENSION_USAGE_DESCRIPTION" } The DNSProxyProvider class inherits from NEDNSProxyProvider and is built in the system extension target. Activation code In the host app, I use: swift import SystemExtensions final class SystemExtensionActivator: NSObject, OSSystemExtensionRequestDelegate { private let extensionIdentifier = "com.example.agent.NetShieldProxy.dnsProxy" func activate(completion: @escaping (Bool) -> Void) { let request = OSSystemExtensionRequest.activationRequest( forExtensionWithIdentifier: extensionIdentifier, queue: .main ) request.delegate = self OSSystemExtensionManager.shared.submitRequest(request) } func request(_ request: OSSystemExtensionRequest, didFailWithError error: Error) { let nsError = error as NSError print("Activation failed:", nsError) } func request(_ request: OSSystemExtensionRequest, didFinishWithResult result: OSSystemExtensionRequest.Result) { print("Result:", result.rawValue) } } Runtime behavior on a clean Mac (no MDM) config.plist is created under /Library/Application Support/NetShield (via a root shell script). A daemon runs, contacts our backend, and writes /Library/Application Support/NetShield/state.plist with a valid dnsToken and other fields. The app NetShieldProxy.app is installed via a notarized, stapled Developer ID .pkg. The extension bundle is present at: /Applications/NetShieldProxy.app/Contents/Library/SystemExtensions/com.example.agent.NetShieldProxy.dnsProxy.systemextension. When I press Activate DNS Proxy in the UI, I see in the unified log: text NetShieldProxy: [com.example.agent:SystemExtensionActivator] Requesting activation for system extension: com.example.agent.NetShieldProxy.dnsProxy NetShieldProxy: [com.example.agent:SystemExtensionActivator] SystemExtensionActivator - activation failed: extension category returned error (domain=OSSystemExtensionErrorDomain code=9) NetShieldProxy: [com.example.agent:SystemExtensionActivator] SystemExtensionActivator - OSSystemExtensionError code enum: 9 NetShieldProxy: [com.example.agent:SystemExtensionActivator] SystemExtensionActivator - validationFailed And: bash systemextensionsctl list -> 0 extension(s) There is no prompt in Privacy & Security on this clean Mac. Question Given: The extension is packaged as a system extension (CFBundlePackageType = SYSX) with NSExtensionPointIdentifier = "com.apple.dns-proxy". Host and extension share the same Team ID and Developer ID Application cert. Entitlements on the target machine match the provisioning profile and Apple’s docs for DNS Proxy system extensions (dns-proxy-systemextension). This is happening on a clean Mac with no MDM profiles at all. What are the likely reasons for OSSystemExtensionErrorDomain error 9 (validationFailed) with "extension category returned error" in this DNS Proxy system extension scenario? Is there any additional configuration required for DNS Proxy system extensions (beyond entitlements and Info.plist) that could trigger this category-level validation failure? Any guidance or examples of a working DNS Proxy system extension configuration (host entitlements + extension Info.plist + entitlements) would be greatly appreciated. Thanks!
9
0
449
Jan ’26
Is it possible to scan for nearby WiFi networks and connect to a device in AP mode on iOS?
In our iOS application, we need to list available WiFi networks so that users can select one for device configuration. Here's the workflow: Initially, the hardware device acts as a WiFi Access Point (AP). The app should scan for nearby WiFi networks to detect the device's AP. The app connects temporarily to this AP and sends the selected WiFi credentials to the device. The device then connects to the selected WiFi network and stops broadcasting its AP. Is this flow achievable on iOS? We understand that Apple restricts access to WiFi scanning APIs — are there any supported methods (e.g., using NEHotspotHelper) or entitlements (such as MFi) that could enable this?
2
2
154
Jun ’25
Internal error, NEHotspotConfigurationErrorDomain
Hello eveybody,Currently I'm working on an app which connects to a device. During testing I encounter an internal error of NEHotspotConfigurationErrorDomain. See the log snippet:Domain=NEHotspotConfigurationErrorDomain Code=8 "internal error." UserInfo={NSLocalizedDescription=internal error.}This error appears randomly. In one day I encountered it three times. The only solution I can think of is catching this error somehow and then telling the user to restart the device.After this error appears, the wifi functionality of iOS in all third party apps seems to be broken. Only restarting helps as far as I know. Also there seems to be nothing we as app developers can do about it. Therefor I wonder if there is some way to prevent this error somehow? The only solution I can think of is catching this error somehow and then telling the user to restart the device.Also since there is not much information about this error on the web, it would be really nice if someone can clarify whats going on with this error.Regards.
16
0
10k
Jan ’26
How to avoid my local server flows in Transparent App Proxy
I have written the Transparent App Proxy and can capture the network flow and send it to my local server. I want to avoid any processing on the traffic outgoing from my server and establish a connection with a remote server, but instead of connecting to the remote server, it again gets captured and sent back to my local server. I am not getting any clue on how to ignore these flows originating from my server. Any pointers, API, or mechanisms that will help me?
9
2
349
Apr ’25
Is it allowed for a third-party iOS app to query time.apple.com (NTP/SNTP)? Any official usage guidance / rate limits?
I’m developing an iOS idle game (guild management). To detect manual device time changes that would break progression, I need a trusted “current real-world time” reference. I’m considering querying Apple’s NTP host time.apple.com, but I couldn’t find any official guidance about whether third-party apps may use time.apple.com directly (acceptable use, rate limits, whether it’s discouraged, etc.). Apple Developer Support couldn’t provide info and suggested asking on the forums. Questions: 1. Is it permitted for a third-party iOS app to query time.apple.com via NTP/SNTP (Yes/No or conditional)? 2. If permitted, are there any published or recommended constraints (rate limits, caching, prohibited patterns, commercial app considerations)? 3. If not permitted / not recommended, what is the recommended alternative approach (run our own time service, use public NTP pool, or any Apple-recommended mechanism)? 4. If there is any official document / policy covering this, could you point me to it? For context: I do not need sub-second accuracy and I do not intend high-frequency polling. If implemented at all, it would be very low frequency (e.g., first launch + once per 24h) with caching and graceful fallback on failure. My main goal is policy clarity rather than implementation details.
2
0
145
Jan ’26
App Crashes on iOS 26 in Network.framework / boringssl – objc_release & memory corruption
Hello Apple Support Team, We are seeing a production crash on iOS 26 devices that appears to originate from Apple system frameworks rather than application code. 1. Crash Details OS Version: iOS 26.x App built with: Xcode 16 Devices: Multiple models (not device-specific) Exception Type: SIGSEGV SEGV_ACCERR Fault Address: 0x0000000000000100 Crashed Thread: 4 (network background queue) Crash trace summary: Last Exception : 0 libobjc.A.dylib _objc_release_x8 + 8 1 libboringssl.dylib _nw_protocol_boringssl_deallocate_options + 92 2 Network 0x000000019695207c 0x00000001968dc000 + 483452 3 libswiftCore.dylib __swift_release_dealloc + 56 4 libswiftCore.dylib bool swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1> >::doDecrementSlow<(swift::PerformDeinit)1>(swift::RefCountBitsT<(swift::RefCountInlinedness)1>, unsigned int) + 152 5 Network 0x0000000196951f6c 0x00000001968dc000 + 483180 6 Network 0x0000000196952000 0x00000001968dc000 + 483328 7 libswiftCore.dylib __swift_release_dealloc + 56 8 libswiftCore.dylib bool swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1> >::doDecrementSlow<(swift::PerformDeinit)1>(swift::RefCountBitsT<(swift::RefCountInlinedness)1>, unsigned int) + 152 9 libswiftCore.dylib void multiPayloadEnumFN<&handleRefCountsDestroy>(swift::TargetMetadata<swift::InProcess> const*, swift::LayoutStringReader1&, unsigned long&, unsigned char*) + 248 10 libswiftCore.dylib swift::swift_cvw_arrayDestroy(swift::OpaqueValue*, unsigned long, unsigned long, swift::TargetMetadata<swift::InProcess> const*) + 1172 11 libswiftCore.dylib _$sSp12deinitialize5countSvSi_tF + 40 12 CollectionsInternal ___swift_instantiateGenericMetadata + 1236 13 CollectionsInternal ___swift_instantiateGenericMetadata + 388 14 CollectionsInternal ___swift_instantiateGenericMetadata + 1044 15 libswiftCore.dylib __swift_release_dealloc + 56 16 libswiftCore.dylib bool swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1> >::doDecrementSlow<(swift::PerformDeinit)1>(swift::RefCountBitsT<(swift::RefCountInlinedness)1>, unsigned int) + 152 17 Network 0x000000019695f9fc 0x00000001968dc000 + 539132 18 Network 0x000000019695f9bc 0x00000001968dc000 + 539068 19 libswiftCore.dylib __swift_release_dealloc + 56 20 libswiftCore.dylib bool swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1> >::doDecrementSlow<(swift::PerformDeinit)1>(swift::RefCountBitsT<(swift::RefCountInlinedness)1>, unsigned int) + 152 21 libswiftCore.dylib swift_cvw_destroyImpl(swift::OpaqueValue*, swift::TargetMetadata<swift::InProcess> const*) + 212 22 Network 0x0000000196def5d8 0x00000001968dc000 + 5322200 23 Network 0x0000000196ded130 0x00000001968dc000 + 5312816 24 libswiftCore.dylib __swift_release_dealloc + 56 25 libswiftCore.dylib bool swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1> >::doDecrementSlow<(swift::PerformDeinit)1>(swift::RefCountBitsT<(swift::RefCountInlinedness)1>, unsigned int) + 152 26 Network 0x000000019695fde0 0x00000001968dc000 + 540128 27 libobjc.A.dylib object_cxxDestructFromClass(objc_object*, objc_class*) + 116 28 libobjc.A.dylib objc_destructInstance_nonnull_realized(objc_object*) + 76 29 libobjc.A.dylib __objc_rootDealloc + 72 30 Network 0x000000019695f99c 0x00000001968dc000 + 539036 31 Network 0x000000019695fae4 0x00000001968dc000 + 539364 32 Network 0x0000000196b078b8 0x00000001968dc000 + 2275512 33 libobjc.A.dylib object_cxxDestructFromClass(objc_object*, objc_class*) + 116 34 libobjc.A.dylib objc_destructInstance_nonnull_realized(objc_object*) + 76 35 libobjc.A.dylib __objc_rootDealloc + 72 36 Network 0x0000000196b07658 0x00000001968dc000 + 2274904 37 Network 0x00000001968e51d4 nw_queue_context_async_if_needed + 92 38 Network 0x0000000197686ea0 0x00000001968dc000 + 14331552 39 libswiftCore.dylib swift::swift_cvw_arrayDestroy(swift::OpaqueValue*, unsigned long, unsigned long, swift::TargetMetadata<swift::InProcess> const*) + 436 40 libswiftCore.dylib _$sSp12deinitialize5countSvSi_tF + 40 41 CollectionsInternal ___swift_instantiateGenericMetadata + 1236 42 CollectionsInternal ___swift_instantiateGenericMetadata + 388 43 CollectionsInternal ___swift_instantiateGenericMetadata + 1044 44 libswiftCore.dylib __swift_release_dealloc + 56 45 libswiftCore.dylib bool swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1> >::doDecrementSlow<(swift::PerformDeinit)1>(swift::RefCountBitsT<(swift::RefCountInlinedness)1>, unsigned int) + 152 46 Network 0x000000019694a010 0x00000001968dc000 + 450576 47 libobjc.A.dylib object_cxxDestructFromClass(objc_object*, objc_class*) + 116 48 libobjc.A.dylib objc_destructInstance_nonnull_realized(objc_object*) + 76 49 libobjc.A.dylib __objc_rootDealloc + 72 50 Network 0x0000000196a330e0 0x00000001968dc000 + 1405152 51 Network 0x00000001974378e0 0x00000001968dc000 + 11909344 52 Network 0x0000000196a17178 0x00000001968dc000 + 1290616 53 libdispatch.dylib __dispatch_call_block_and_release + 32 54 libdispatch.dylib __dispatch_client_callout + 16 55 libdispatch.dylib _dispatch_workloop_invoke.cold.4 + 32 56 libdispatch.dylib __dispatch_workloop_invoke + 1980 57 libdispatch.dylib __dispatch_root_queue_drain_deferred_wlh + 292 58 libdispatch.dylib __dispatch_workloop_worker_thread + 692 59 libsystem_pthread.dylib __pthread_wqthread + 292 ------ Exception Type: SIGSEGV SEGV_ACCERR Exception Codes: fault addr: 0x0000000000000100 Crashed Thread: 4 2. Behavior & Context The crash occurs during normal HTTPS networking using standard URLSession (no direct usage of Network.framework nor boringssl APIs). It appears to be triggered during QUIC connection establishment or TLS fallback. The stack trace contains no application code frames — all symbols are from system libraries. The crash strongly indicates double-free, over-release, or dangling pointer inside nw_protocol_boringssl_options deallocation. 3. Questions for Apple Is this a known issue in iOS 26 within Network.framework / boringssl related to nw_protocol_boringssl_deallocate_options? What is the root cause of the over‑release / invalid objc_release in this path? Is there a workaround we can implement from the app side (e.g., disabling QUIC, adjusting TLS settings, or queue configuration)? Do you have a target iOS version or patch where this issue will be fixed? We can provide full crash logs and additional metrics upon request. 4. Additional Information Developed using Swift 5, with a deployment target of iOS 12+. Thank you for your support.
1
2
153
Mar ’26
URLCache behavior for request with different header values
Greetings, I would like to understand this URLCache behavior for two different requests to the same end point but with a different header value. Here is a code with comment explaining the behavior. // Create a request to for a url. let url = URL(string: "https://&lt;my url&gt;?f=json")! var request = URLRequest(url: url) // Set custom header with a value. request.setValue("myvalue", forHTTPHeaderField: "CustomField") // Send request to get the response. let (data, response) = try await URLSession.shared.data(for: request) print("data: \(String(describing: String(data: data, encoding: .utf8)))") print("response: \(response)") // Create second request to the same url but with different value of custom header field. var request2 = URLRequest(url: url) request2.setValue("newvalue", forHTTPHeaderField: "CustomField") // Check the URL cache for second request and it returns the response // of the first request even though the second request has different header value. let cachedResponse = URLCache.shared.cachedResponse(for: request2) print("cachedResponse: \(cachedResponse?.response)") Is this a bug in URLCache that request headers are not matched while returning the response? Is this an expected behavior? If yes, why?
8
2
1.7k
Aug ’25
Need Inputs on Which Extension to Use
Hi all, I have a working macOS (Intel) system extension app that currently uses only a Content Filter (NEFilterDataProvider). I need to capture/log HTTP and HTTPS traffic in plain text, and I understand NETransparentProxyProvider is the right extension type for that. For HTTPS I will need TLS inspection / a MITM proxy — I’m new to that and unsure how complex it will be. For DNS data (in plain text), can I use the same extension, or do I need a separate extension type such as NEPacketTunnelProvider, NEFilterPacketProvider, or NEDNSProxyProvider? Current architecture: Two Xcode targets: MainApp and a SystemExtension target. The SystemExtension target contains multiple network extension types. MainApp ↔ SystemExtension communicate via a bidirectional NSXPC connection. I can already enable two extensions (Content Filter and TransparentProxy). With the NETransparentProxy, I still need to implement HTTPS capture. Questions I’d appreciate help with: Can NETransparentProxy capture the DNS fields I need (dns_hostname, dns_query_type, dns_response_code, dns_answer_number, etc.), or do I need an additional extension type to capture DNS in plain text? If a separate extension is required, is it possible or problematic to include that extension type (Packet Tunnel / DNS Proxy / etc.) in the same SystemExtension Xcode target as the TransparentProxy? Any recommended resources or guidance on TLS inspection / MITM proxy setup for capturing HTTPS logs? There are multiple DNS transport types — am I correct that capturing DNS over UDP (port 53) is not necessarily sufficient? Which DNS types should I plan to handle? I’ve read that TransparentProxy and other extension types (e.g., Packet Tunnel) cannot coexist in the same Xcode target. Is that true? Best approach for delivering logs from multiple extensions to the main app (is it feasible)? Or what’s the best way to capture logs so an external/independent process (or C/C++ daemon) can consume them? Required data to capture (not limited to): All HTTP/HTTPS (request, body, URL, response, etc.) DNS fields: dns_hostname, dns_query_type, dns_response_code, dns_answer_number, and other DNS data — all in plain text. I’ve read various resources but remain unclear which extension(s) to use and whether multiple extension types can be combined in one Xcode target. Please ask if you need more details. Thank you.
5
0
310
Jan ’26
Bonjour Conformance Test WARNING in Multicast DNS SHARED REPLY TIMING resolution
Hello and Good day! We are conducting Bonjour Conformance Test (BCT) for Printer device. BCT result is PASSED but with warning in Multicast DNS, specifically, WARNING: SHARED REPLY TIMING - UNIFORM RANDOM REPLY TIME DISTRIBUTION Other Shared Reply Timing is passed: PASSED: MULTIPLE QUESTIONS - SHARED REPLY TIMING - UNIFORM RANDOM REPLY TIME DISTRIBUTION Environment: BCT Tool Version: 1.5.4 (15400) MacOS Sequioa 15.5 DUT Firmware : Linux Debian 9 Apple mDNSResponder 1790.80.10 Service types: _ipps._tcp, _uscans._tcp, _ipp._tcp, _uscan._tcp Router : NEC AtermWR8370N Setup: 1-to-1 [Mac->Router<-DUT connection] Based on debug.log, this is where WARNING occurs: NOTICE 2026-03-04 10:51:06.870187+0900 _shared_reply_timing 04103: Shared reply response times: min = 26ms, max = 114ms, avg = 65.50ms WARNING 2026-03-04 10:51:06.870361+0900 _shared_reply_timing 04136: 50 percent of the replies within the correct range fell in the interval 20ms and 46ms (should be close to 25%). PASSED (SHARED REPLY TIMING) In the same debug.log for MULTIPLE QUESTIONS - SHARED REPLY TIMING is PASSED: NOTICE 2026-03-04 10:52:29.912334+0900 _shared_reply_timing 04103: Shared reply response times: min = 22ms, max = 112ms, avg = 78.00ms DEBUG_2 2026-03-04 10:52:29.912849+0900 recv_packet 01997: received packet (558 bytes) PASSED (MULTIPLE QUESTIONS - SHARED REPLY TIMING) [Details] Looking at Bonjour_Conformance_Guideline.pdf https://download.developer.apple.com/Documentation/Bonjour_Conformance_Test_Guideline/Bonjour_Conformance_Guideline.pdf there were some differences: In 1.6.2 Expected Result: Test Result File of Test that All Tests Passed, this is not displayed: PASSED: SHARED REPLY TIMING - UNIFORM RANDOM REPLY TIME DISTRIBUTION And in II.8 Shared Reply Timing: (Ideally, 25% of the answers should fall in each 21ms quadrant of the range 20ms - 125ms.) and comparing to the debug.log, there was a discrepancy of the interval, because 20ms and 46ms is 26ms interval. From RFC6762 6. Responding, Ideal range is from 20ms-120ms Because of this, please advise on the questions below: I would like to know on the possible cause and resolution for these WARNINGS. And since in current BCT result, (Test result integrity signature is generated), I would like to know if this is acceptable for BCT certification. Thank you.
9
0
247
3w
NEAppProxyUDPFlow.writeDatagrams fails with "The datagram was too large" on macOS 15.x, macOS 26.x
I'm implementing a NEDNSProxyProvider on macOS 15.x and macOS 26.x. The flow works correctly up to the last step — returning the DNS response to the client via writeDatagrams. Environment: macOS 15.x, 26.x Xcode 26.x NEDNSProxyProvider with NEAppProxyUDPFlow What I'm doing: override func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool { guard let udpFlow = flow as? NEAppProxyUDPFlow else { return false } udpFlow.readDatagrams { datagrams, endpoints, error in // 1. Read DNS request from client // 2. Forward to upstream DNS server via TCP // 3. Receive response from upstream // 4. Try to return response to client: udpFlow.writeDatagrams([responseData], sentBy: [endpoints.first!]) { error in // Always fails: "The datagram was too large" // responseData is 50-200 bytes — well within UDP limits } } return true } Investigation: I added logging to check the type of endpoints.first : // On macOS 15.0 and 26.3.1: // type(of: endpoints.first) → NWAddressEndpoint // Not NWHostEndpoint as expected On both macOS 15.4 and 26.3.1, readDatagrams returns [NWEndpoint] where each endpoint appears to be NWAddressEndpoint — a type that is not publicly documented. When I try to create NWHostEndpoint manually from hostname and port, and pass it to writeDatagrams, the error "The datagram was too large" still occurs in some cases. Questions: What is the correct endpoint type to pass to writeDatagrams on macOS 15.x, 26.x? Should we pass the exact same NWEndpoint objects returned by readDatagrams, or create new ones? NWEndpoint, NWHostEndpoint, and writeDatagrams are all deprecated in macOS 15. Is there a replacement API for NEAppProxyUDPFlow that works with nw_endpoint_t from the Network framework? Is the error "The datagram was too large" actually about the endpoint type rather than the data size? Any guidance would be appreciated. :-))
7
0
188
1w
Performance degradation of HTTP/3 requests in iOS app under specific network conditions
Hello Apple Support Team, We are experiencing a performance issue with HTTP/3 in our iOS application during testing. Problem Description: Network requests using HTTP/3 are significantly slower than expected. This issue occurs on both Wi-Fi and 4G networks, with both IPv4 and IPv6. The same setup worked correctly in an earlier experiment. Key Observations: The slowdown disappears when the device uses: · A personal hotspot. · Network Link Conditioner (with no limitations applied). · Internet sharing from a MacBook via USB (where traffic was also inspected with Wireshark without issues). The problem is specific to HTTP/3 and does not occur with HTTP/2. The issue is reproducible on iOS 15, 18.7, and the latest iOS 26 beta. HTTP/3 is confirmed to be active (via assumeHttp3Capable and Alt-Svc header). Crucially, the same backend endpoint works with normal performance on Android devices and using curl with HTTP/3 support from the same network. I've checked the CFNetwork logs in the Console but haven't found any suspicious errors or obvious clues that explain the slowdown. We are using a standard URLSession with basic configuration. Attempted to collect qlog diagnostics by setting the QUIC_LOG_DIRECTORY=~/ tmp environment variable, but the logs were not generated. Question: What could cause HTTP/3 performance to improve only when the device is connected through a hotspot, unrestricted Network Link Conditioner, or USB-tethered connection? The fact that Android and curl work correctly points to an issue specific to the iOS network stack. Are there known conditions or policies (e.g., related to network interface handling, QoS, or specific packet processing) that could lead to this behavior? Additionally, why might the qlog environment variable fail to produce logs, and are there other ways to obtain detailed HTTP/3 diagnostic information from iOS? Any guidance on further diagnostic steps or specific system logs to examine would be greatly appreciated. Thank you for your assistance.
Replies
6
Boosts
0
Views
468
Activity
Nov ’25
Disable URLSession auto retry policy
We are developing an iOS application that is interacting with HTTP APIs that requires us to put a unique UUID (a nonce) as an header on every request (obviously there's more than that, but that's irrilevant to the question here). If the same nonce is sent on two subsequent requests the server returns a 412 error. We should avoid generating this kind of errors as, if repeated, they may be flagged as a malicious activity by the HTTP APIs. We are using URLSession.shared.dataTaskPublisher(for: request) to call the HTTP APIs with request being generated with the unique nonce as an header. On our field tests we are seeing a few cases of the same HTTP request (same nonce) being repeated a few seconds on after the other. Our code has some retry logic only on 401 errors, but that involves a token refresh, and this is not what we are seeing from logs. We were able to replicate this behaviour on our own device using Network Link Conditioner with very bad performance, with XCode's Network inspector attached we can be certain that two HTTP requests with identical headers are actually made automatically, the first request has an "End Reason" of "Retry", the second is "Success" with Status 412. Our questions are: can we disable this behaviour? can we provide a new request for the retry (so that we can update headers)? Thanks, Francesco
Replies
7
Boosts
3
Views
357
Activity
Aug ’25
AccessorySetupKit – WiFi picker – show accessories after factory reset?
Hi there, We’re developing a companion app for a smart home product that communicates over the user’s local network. To provision the device, it initially creates its own Wi-Fi network. The user joins this temporary network and enters their home Wi-Fi credentials via our app. The app then sends those credentials directly to the device, which stores them and connects to the local network for normal operation. We’re using AccessorySetupKit to discover nearby devices (via SSID prefix) and NEHotspotManager to join the accessory’s Wi-Fi network once the user selects it. This workflow works well in general. However, we’ve encountered a problem: if the user factory-resets the accessory, or needs to restart setup (for example, after entering the wrong Wi-Fi password), the device no longer appears in the accessory picker. In iOS 18, we were able to work around this by calling removeAccessory() after the device is selected. This forces the picker to always display the accessory again. But in iOS 26, a new confirmation dialog now appears when calling removeAccessory(), which confuses users during setup. We’re looking for a cleaner way to handle this scenario — ideally a way to make the accessory rediscoverable without prompting the user to confirm removal. Thanks for your time and guidance.
Replies
0
Boosts
3
Views
241
Activity
Nov ’25
Content Filter Permission Prompt Not Appearing in TestFlight
I added a Content Filter to my app, and when running it in Xcode (Debug/Release), I get the expected permission prompt: "Would like to filter network content (Allow / Don't Allow)". However, when I install the app via TestFlight, this prompt doesn’t appear at all, and the feature doesn’t work. Is there a special configuration required for TestFlight? Has anyone encountered this issue before? Thanks!
Replies
23
Boosts
1
Views
1.1k
Activity
2w
When updating a VPN app with `includeAllNetworks`, the newer instance of the packet tunnel is not started via on-demand rules
When installing a new version the app while a tunnel is connected, seemingly the old packet tunnel process gets stopped but the new one does not come back up. Reportedly, a path monitor is reporting that the device has no connectivity. Is this the expected behavior? When installing an update from TestFlight or the App store, the packet tunnel instance from the old tunnel is stopped, but, due to the profile being on-demand and incldueAllNetworks, the path monitoring believes the device has no connectivity - so the new app is never downloaded. Is this the expected behavior? During development, the old packet tunnel gets stopped, the new app is installed, but the new packet tunnel is never started. To start it, the user has to toggle the VPN twice from the Settings app. The tunnel could be started from the VPN app too, if we chose to not take the path monitor into account, but then the user still needs to attempt to start the tunnel twice - it only works on the second try. As far as we can tell, the first time around, the packet tunnel never gets started, the app receives an update about NEVPNStatus being set to disconnecting yet NEVPNConnection does not throw. The behavior I was naively expecting was that the packet tunnel process would be stopped only when the new app is fully downloaded and when the update is installed, Are we doing something horribly wrong here?
Replies
7
Boosts
3
Views
657
Activity
Jan ’26
Bluetooth 5 Coded PHY (Long Range) removed in iOS 14
I am pretty sure iOS 13.4 (beta and later) did support Coded PHY (Long Range). Tested devices are iPhone SE2 and iPhone 11 Pro. However, it seems iOS 14 removed the support of Coded PHY, accidentally or on purpose, I don't know? The same PHY update request returns "1M PHY" in iOS 14, but "Coded PHY" in iOS 13 (13.4 beta and later). Anyone knows why? Samson
Replies
10
Boosts
1
Views
5.9k
Activity
Oct ’25
Title: DNS Proxy Not Capturing Traffic When Public DNS Is Set in WiFi Settings
I'm working on a Network Extension using NEDNSProxyProvider to inspect DNS traffic. However, I've run into a couple of issues: DNS Proxy is not capturing traffic when a public DNS (like 8.8.8.8 or 1.1.1.1) is manually configured in the WiFi settings. It seems like the system bypasses the proxy in this case. Is this expected behavior? Is there a way to force DNS traffic through the proxy even if a public DNS is set? Using DNS Proxy and DNS Settings simultaneously doesn't work. Is there a known limitation or a correct way to combine these? How to set DNS or DNSSettings using DNSProxy? import NetworkExtension import SystemExtensions import SwiftUI protocol DNSProxyManagerDelegate { func managerStateDidChange(_ manager: DNSProxyManager) } class DNSProxyManager: NSObject { private let manager = NEDNSProxyManager.shared() var delegate: DNSProxyManagerDelegate? private(set) var isEnabled: Bool = false { didSet { delegate?.managerStateDidChange(self) } } var completion: (() -> Void)? override init() { super.init() self.load() } func toggle() { isEnabled ? disable() : start() } private func start() { let request = OSSystemExtensionRequest .activationRequest(forExtensionWithIdentifier: Constants.extensionBundleID, queue: DispatchQueue.main) request.delegate = self OSSystemExtensionManager.shared.submitRequest(request) log.info("Submitted extension activation request") } private func enable() { update { self.manager.localizedDescription = "DNS Proxy" let proto = NEDNSProxyProviderProtocol() proto.providerBundleIdentifier = Constants.extensionBundleID self.manager.providerProtocol = proto self.manager.isEnabled = true } } private func disable() { update { self.manager.isEnabled = false } } private func remove() { update { self.manager.removeFromPreferences { _ in self.isEnabled = self.manager.isEnabled } } } private func update(_ body: @escaping () -> Void) { self.manager.loadFromPreferences { (error) in if let error = error { log.error("Failed to load DNS manager: \(error)") return } self.manager.saveToPreferences { (error) in if let error = error { return } log.info("Saved DNS manager") self.isEnabled = self.manager.isEnabled } } } private func load() { manager.loadFromPreferences { error in guard error == nil else { return } self.isEnabled = self.manager.isEnabled } } } extension DNSProxyManager: OSSystemExtensionRequestDelegate { func requestNeedsUserApproval(_ request: OSSystemExtensionRequest) { log.info("Extension activation request needs user approval") } func request(_ request: OSSystemExtensionRequest, didFailWithError error: Error) { log.error("Extension activation request failed: \(error)") } func request(_ request: OSSystemExtensionRequest, foundProperties properties: [OSSystemExtensionProperties]) { log.info("Extension activation request found properties: \(properties)") } func request(_ request: OSSystemExtensionRequest, didFinishWithResult result: OSSystemExtensionRequest.Result) { guard result == .completed else { log.error("Unexpected result \(result.description) for system extension request") return } log.info("Extension activation request did finish with result: \(result.description)") enable() } func request(_ request: OSSystemExtensionRequest, actionForReplacingExtension existing: OSSystemExtensionProperties, withExtension ext: OSSystemExtensionProperties) -> OSSystemExtensionRequest.ReplacementAction { log.info("Existing extension willt be replaced: \(existing.bundleIdentifier) -> \(ext.bundleIdentifier)") return .replace } } import NetworkExtension class DNSProxyProvider: NEDNSProxyProvider { var handlers: [String: FlowHandler] = [:] var isReady = false let queue = DispatchQueue(label: "DNSProxyProvider") override func startProxy(options:[String: Any]? = nil, completionHandler: @escaping (Error?) -> Void) { completionHandler(nil) } override func stopProxy(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { completionHandler() } override func handleNewUDPFlow(_ flow: NEAppProxyUDPFlow, initialRemoteEndpoint remoteEndpoint: NWEndpoint) -> Bool { let id = shortUUID() handlers[id] = FlowHandler(flow: flow, remoteEndpoint: remoteEndpoint, id: id, delegate: self) return true } override func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool { return false } } class FlowHandler { let id: String let flow: NEAppProxyUDPFlow let remoteEndpoint: NWHostEndpoint let delegate: FlowHandlerDelegate private var connections: [String: RemoteConnection] = [:] private var pendingPacketsByDomain: [String: [(packet: Data, endpoint: NWEndpoint, uniqueID: String, timestamp: Date)]] = [:] private let packetQueue = DispatchQueue(label: "com.flowhandler.packetQueue") init(flow: NEAppProxyUDPFlow, remoteEndpoint: NWEndpoint, id: String, delegate: FlowHandlerDelegate) { log.info("Flow received for \(id) flow: \(String(describing: flow))") self.flow = flow self.remoteEndpoint = remoteEndpoint as! NWHostEndpoint self.id = id self.delegate = delegate defer { start() } } deinit { closeAll(nil) } func start() { flow.open(withLocalEndpoint: flow.localEndpoint as? NWHostEndpoint) { error in if let error = error { self.delegate.flowClosed(self) return } self.readFromFlow() } } func readFromFlow() { self.flow.readDatagrams { packets, endpoint, error in if let error = error { self.closeAll(error) return } guard let packets = packets, let endpoints = endpoint, !packets.isEmpty, !endpoints.isEmpty else { self.closeAll(nil) return } self.processFlowPackets(packets, endpoints) self.readFromFlow() } } } Any insights or suggestions would be greatly appreciated. Thanks!
Replies
2
Boosts
3
Views
345
Activity
Apr ’25
Title: Accessing Wi-Fi SSID for custom On-Demand logic in PacketTunnelProvider on macOS
We are developing a macOS VPN application using NEPacketTunnelProvider with a custom encryption protocol. We are using standard On-Demand VPN rules with Wi-Fi SSID matching but we want to add some additional feature to the native behaviour.  We want to control the 'conenect/disconnect' button status and allow the user to interact with the tunnel even when the on demand rule conditions are satisfied, is there a native way to do it? In case we need to implement our custom on-demand behaviour we need to access to this information: connected interface type ssid name and being informed when it changes so to trigger our logic, how to do it from the app side? we try to use CWWiFiClient along with ssidDidChangeForWiFiInterface monitoring, it returns just the interface name en0 and not the wifi ssid name. Is location access mandatory to access wifi SSID on macOS even if we have a NEPacketTunnelProvider? Please note that we bundle our Network Extension as an App Extension (not SystemExtension).
Replies
9
Boosts
2
Views
391
Activity
Jan ’26
Network Extension App for MacOS with 3 Extensions
Hi All, I am currently working on a Network Extension App for MacOS using 3 types of extensions provided by Apple's Network Extension Framework. Content Filter, App Proxy (Want to get/capture/log all HTTP/HTTPS traffic), DNS Proxy (Want to get/capture/log all DNS records). Later parse into human readable format. Is my selection of network extension types correct for the intended logs I need? I am able to run with one extension: Main App(Xcode Target1) <-> Content Filter Extension. Here there is a singleton class IPCConnection between App(ViewController.swift) which is working fine with NEMachServiceName from Info.plist of ContentFilter Extension(Xcode Target2) However, when I add an App Proxy extension as a new Xcode Target3, I think the App and extension's communication getting messed up and App not getting started/Crashing. Here, In the same Main App, I am adding new separate IPCConnection for this extension. Here is the project organization/folder structure. MyNetworkExtension ├──MyNetworkExtension(Xcode Target1) │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── Info.plist │ ├── MyNetworkExtension.entitlement │ | ── Main │ |-----ViewController.swift │ └── Base.lproj │ └── Main.storyboard ├── ContentFilterExtension(Xcode Target2) │ ├── ContentFilterExtension.entitlement │ │ ├── FilterDataProvider.swift │ │ ├── Info.plist │ │ ├── IPCConnection.swift │ │ └── main.swift ├── AppProxyProviderExtension(Xcode Target3) │ ├── AppProxyProviderExtension.entitlement │ │ ├── AppProxyIPCConnection.swift │ │ ├── AppProxyProvider.swift │ │ ├── Info.plist │ │ └── main.swift └── Frameworks ├── libbsm.tbd └── NetworkExtension.framework Is my Approach for creating a single Network Extension App with Multiple extensions correct or is there any better approach of project organization that will make future modifications/working easier and makes the maintenance better? I want to keep the logic for each extension separate while having the same, single Main App that manages everything(installing, activating, managing identifiers, extensions, etc). What's the best approach to establish a Communication from MainApp to each extension separately, without affecting one another? Is it good idea to establish 3 separate IPC Connections(each is a singleton class) for each extension? Are there any suggestions you can provide that relates to my use case of capturing all the network traffic logs(including HTTP/HTTPS, DNS Records, etc), especially on App to Extension Communication, where my app unable to keep multiple IPC Connections and maintain them separately? I've been working on it for a while, and still unable to make the Network Extension App work with multiple extensions(each as a new Xcode target). Main App with single extension is working fine, but if I add new extension, App getting crashed. I suspect it's due to XPC/IPC connection things! I really appreciate any support on this either directly or by any suggestions/resources that will help me get better understand and make some progress. Please reach out if in case any clarifications or specific information that's needed to better understand my questions. Thank you very much
Replies
4
Boosts
0
Views
367
Activity
Sep ’25
Push notifications not delivered over Wi-Fi with includeAllNetworks = true regardless of excludeAPNS setting
We have a VPN app that uses NEPacketTunnelProvider with includeAllNetworks = true. We've encountered an issue where push notifications are not delivered over Wi-Fi while the tunnel is active in a pre-MFA quarantine state (tunnel is up but traffic is blocked on server side), regardless of whether excludeAPNS is set to true or false. Observed behavior Wi-Fi excludeAPNS = true - Notifications not delivered Wi-Fi excludeAPNS = false - Notifications not delivered Cellular excludeAPNS = true - Notifications delivered Cellular excludeAPNS = false - Notifications not delivered On cellular, the behavior matches our expectations: setting excludeAPNS = true allows APNS traffic to bypass the tunnel and notifications arrive; setting it to false routes APNS through the tunnel and notifications are blocked (as expected for a non-forwarding tunnel). On Wi-Fi, notifications fail to deliver in both cases. Our question Is this expected behavior when includeAllNetworks is enabled on Wi-Fi, or is this a known issue / bug with APNS delivery? Is there something else in the Wi-Fi networking path that includeAllNetworks affects beyond routing, which could prevent APNS from functioning even when the traffic is excluded from the tunnel? Sample Project Below is the minimal code that reproduces this issue. The project has two targets: a main app and a Network Extension. The tunnel provider captures all IPv4 and IPv6 traffic via default routes but does not forward packets — simulating a pre-MFA quarantine state. The main app configures the tunnel with includeAllNetworks = true and provides a UI toggle for excludeAPNS. PacketTunnelProvider.swift (Network Extension target): import NetworkExtension class PacketTunnelProvider: NEPacketTunnelProvider { override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) { let settings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "127.0.0.1") let ipv4 = NEIPv4Settings(addresses: ["198.51.100.1"], subnetMasks: ["255.255.255.0"]) ipv4.includedRoutes = [NEIPv4Route.default()] settings.ipv4Settings = ipv4 let ipv6 = NEIPv6Settings(addresses: ["fd00::1"], networkPrefixLengths: [64]) ipv6.includedRoutes = [NEIPv6Route.default()] settings.ipv6Settings = ipv6 let dns = NEDNSSettings(servers: ["198.51.100.1"]) settings.dnsSettings = dns settings.mtu = 1400 setTunnelNetworkSettings(settings) { error in if let error = error { completionHandler(error) return } self.readPackets() completionHandler(nil) } } private func readPackets() { packetFlow.readPackets { [weak self] packets, protocols in self?.readPackets() } } override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { completionHandler() } override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)?) { if let handler = completionHandler { handler(messageData) } } override func sleep(completionHandler: @escaping () -> Void) { completionHandler() } override func wake() { } } ContentView.swift (Main app target) — trimmed to essentials: import SwiftUI import NetworkExtension struct ContentView: View { @State private var excludeAPNs = false @State private var manager: NETunnelProviderManager? var body: some View { VStack { Toggle("Exclude APNs", isOn: $excludeAPNs) .onChange(of: excludeAPNs) { Task { await saveAndReload() } } Button("Connect") { Task { await toggleVPN() } } } .padding() .task { await loadManager() } } private func loadManager() async { let managers = try? await NETunnelProviderManager.loadAllFromPreferences() if let existing = managers?.first { manager = existing } else { let m = NETunnelProviderManager() let proto = NETunnelProviderProtocol() proto.providerBundleIdentifier = "<your-extension-bundle-id>" proto.serverAddress = "127.0.0.1" proto.includeAllNetworks = true proto.excludeAPNs = excludeAPNs m.protocolConfiguration = proto m.localizedDescription = "TestVPN" m.isEnabled = true try? await m.saveToPreferences() try? await m.loadFromPreferences() manager = m } if let proto = manager?.protocolConfiguration as? NETunnelProviderProtocol { excludeAPNs = proto.excludeAPNs } } private func saveAndReload() async { guard let manager else { return } if let proto = manager.protocolConfiguration as? NETunnelProviderProtocol { proto.includeAllNetworks = true proto.excludeAPNs = excludeAPNs } manager.isEnabled = true try? await manager.saveToPreferences() try? await manager.loadFromPreferences() } private func toggleVPN() async { guard let manager else { return } if manager.connection.status == .connected { manager.connection.stopVPNTunnel() } else { await saveAndReload() try? manager.connection.startVPNTunnel() } } } Steps to reproduce Build and run the sample project with above code on a physical iOS device. Connect to a Wi-Fi network. Set excludeAPNS = true using the toggle and tap Connect. Send a push notification to the device to a test app with remote notification capability (e.g., via a test push service or the push notification console). Observe that the notification is not delivered. Disconnect. Switch to cellular. Reconnect with the same settings. Send the same push notification — observe that it is delivered. Environment iOS 26.2 Xcode 26.2 Physical device (iPhone 15 Pro)
Replies
5
Boosts
1
Views
274
Activity
Mar ’26
DNS Proxy system extension – OSSystemExtensionErrorDomain error 9 “validationFailed” on clean macOS machine
Hi, I’m implementing a macOS DNS Proxy as a system extension and running into a persistent activation error: OSSystemExtensionErrorDomain error 9 (validationFailed) with the message: extension category returned error This happens both on an MDM‑managed Mac and on a completely clean Mac (no MDM, fresh install). Setup macOS: 15.x (clean machine, no MDM) Xcode: 16.x Team ID: AAAAAAA111 (test) Host app bundle ID: com.example.agent.NetShieldProxy DNS Proxy system extension bundle ID: com.example.agent.NetShieldProxy.dnsProxy The DNS Proxy is implemented as a NetworkExtension system extension, not an app extension. Host app entitlements From codesign -d --entitlements :- /Applications/NetShieldProxy.app: xml com.apple.application-identifier AAAAAAA111.com.example.agent.NetShieldProxy <key>com.apple.developer.system-extension.install</key> <true/> <key>com.apple.developer.team-identifier</key> <string>AAAAAAA111</string> <key>com.apple.security.app-sandbox</key> <true/> <key>com.apple.security.application-groups</key> <array> <string>group.com.example.NetShieldmac</string> </array> <key>com.apple.security.files.user-selected.read-only</key> <true/> xml com.apple.application-identifier AAAAAAA111.com.example.agent.NetShieldProxy.dnsProxy <key>com.apple.developer.networking.networkextension</key> <array> <string>dns-proxy-systemextension</string> </array> <key>com.apple.developer.team-identifier</key> <string>AAAAAAA111</string> <key>com.apple.security.application-groups</key> <array> <string>group.com.example.NetShieldmac</string> <string>group.example.NetShieldmac</string> <string>group.example.agent.enterprise.macos</string> <string>group.example.com.NetShieldmac</string> </array> DNS Proxy system extension Info.plist On the clean Mac, from: bash plutil -p "/Applications/NetShieldProxy.app/Contents/Library/SystemExtensions/com.example.agent.NetShieldProxy.dnsProxy.systemextension/Contents/Info.plist" I get: json { "CFBundleExecutable" => "com.example.agent.NetShieldProxy.dnsProxy", "CFBundleIdentifier" => "com.example.agent.NetShieldProxy.dnsProxy", "CFBundleName" => "com.example.agent.NetShieldProxy.dnsProxy", "CFBundlePackageType" => "SYSX", "CFBundleShortVersionString" => "1.0.1.8", "CFBundleSupportedPlatforms" => [ "MacOSX" ], "CFBundleVersion" => "0.1.1", "LSMinimumSystemVersion" => "13.5", "NSExtension" => { "NSExtensionPointIdentifier" => "com.apple.dns-proxy", "NSExtensionPrincipalClass" => "com_example_agent_NetShieldProxy_dnsProxy.DNSProxyProvider" }, "NSSystemExtensionUsageDescription" => "SYSTEM_EXTENSION_USAGE_DESCRIPTION" } The DNSProxyProvider class inherits from NEDNSProxyProvider and is built in the system extension target. Activation code In the host app, I use: swift import SystemExtensions final class SystemExtensionActivator: NSObject, OSSystemExtensionRequestDelegate { private let extensionIdentifier = "com.example.agent.NetShieldProxy.dnsProxy" func activate(completion: @escaping (Bool) -> Void) { let request = OSSystemExtensionRequest.activationRequest( forExtensionWithIdentifier: extensionIdentifier, queue: .main ) request.delegate = self OSSystemExtensionManager.shared.submitRequest(request) } func request(_ request: OSSystemExtensionRequest, didFailWithError error: Error) { let nsError = error as NSError print("Activation failed:", nsError) } func request(_ request: OSSystemExtensionRequest, didFinishWithResult result: OSSystemExtensionRequest.Result) { print("Result:", result.rawValue) } } Runtime behavior on a clean Mac (no MDM) config.plist is created under /Library/Application Support/NetShield (via a root shell script). A daemon runs, contacts our backend, and writes /Library/Application Support/NetShield/state.plist with a valid dnsToken and other fields. The app NetShieldProxy.app is installed via a notarized, stapled Developer ID .pkg. The extension bundle is present at: /Applications/NetShieldProxy.app/Contents/Library/SystemExtensions/com.example.agent.NetShieldProxy.dnsProxy.systemextension. When I press Activate DNS Proxy in the UI, I see in the unified log: text NetShieldProxy: [com.example.agent:SystemExtensionActivator] Requesting activation for system extension: com.example.agent.NetShieldProxy.dnsProxy NetShieldProxy: [com.example.agent:SystemExtensionActivator] SystemExtensionActivator - activation failed: extension category returned error (domain=OSSystemExtensionErrorDomain code=9) NetShieldProxy: [com.example.agent:SystemExtensionActivator] SystemExtensionActivator - OSSystemExtensionError code enum: 9 NetShieldProxy: [com.example.agent:SystemExtensionActivator] SystemExtensionActivator - validationFailed And: bash systemextensionsctl list -> 0 extension(s) There is no prompt in Privacy & Security on this clean Mac. Question Given: The extension is packaged as a system extension (CFBundlePackageType = SYSX) with NSExtensionPointIdentifier = "com.apple.dns-proxy". Host and extension share the same Team ID and Developer ID Application cert. Entitlements on the target machine match the provisioning profile and Apple’s docs for DNS Proxy system extensions (dns-proxy-systemextension). This is happening on a clean Mac with no MDM profiles at all. What are the likely reasons for OSSystemExtensionErrorDomain error 9 (validationFailed) with "extension category returned error" in this DNS Proxy system extension scenario? Is there any additional configuration required for DNS Proxy system extensions (beyond entitlements and Info.plist) that could trigger this category-level validation failure? Any guidance or examples of a working DNS Proxy system extension configuration (host entitlements + extension Info.plist + entitlements) would be greatly appreciated. Thanks!
Replies
9
Boosts
0
Views
449
Activity
Jan ’26
Is it possible to scan for nearby WiFi networks and connect to a device in AP mode on iOS?
In our iOS application, we need to list available WiFi networks so that users can select one for device configuration. Here's the workflow: Initially, the hardware device acts as a WiFi Access Point (AP). The app should scan for nearby WiFi networks to detect the device's AP. The app connects temporarily to this AP and sends the selected WiFi credentials to the device. The device then connects to the selected WiFi network and stops broadcasting its AP. Is this flow achievable on iOS? We understand that Apple restricts access to WiFi scanning APIs — are there any supported methods (e.g., using NEHotspotHelper) or entitlements (such as MFi) that could enable this?
Replies
2
Boosts
2
Views
154
Activity
Jun ’25
Internal error, NEHotspotConfigurationErrorDomain
Hello eveybody,Currently I'm working on an app which connects to a device. During testing I encounter an internal error of NEHotspotConfigurationErrorDomain. See the log snippet:Domain=NEHotspotConfigurationErrorDomain Code=8 "internal error." UserInfo={NSLocalizedDescription=internal error.}This error appears randomly. In one day I encountered it three times. The only solution I can think of is catching this error somehow and then telling the user to restart the device.After this error appears, the wifi functionality of iOS in all third party apps seems to be broken. Only restarting helps as far as I know. Also there seems to be nothing we as app developers can do about it. Therefor I wonder if there is some way to prevent this error somehow? The only solution I can think of is catching this error somehow and then telling the user to restart the device.Also since there is not much information about this error on the web, it would be really nice if someone can clarify whats going on with this error.Regards.
Replies
16
Boosts
0
Views
10k
Activity
Jan ’26
How to avoid my local server flows in Transparent App Proxy
I have written the Transparent App Proxy and can capture the network flow and send it to my local server. I want to avoid any processing on the traffic outgoing from my server and establish a connection with a remote server, but instead of connecting to the remote server, it again gets captured and sent back to my local server. I am not getting any clue on how to ignore these flows originating from my server. Any pointers, API, or mechanisms that will help me?
Replies
9
Boosts
2
Views
349
Activity
Apr ’25
Is it allowed for a third-party iOS app to query time.apple.com (NTP/SNTP)? Any official usage guidance / rate limits?
I’m developing an iOS idle game (guild management). To detect manual device time changes that would break progression, I need a trusted “current real-world time” reference. I’m considering querying Apple’s NTP host time.apple.com, but I couldn’t find any official guidance about whether third-party apps may use time.apple.com directly (acceptable use, rate limits, whether it’s discouraged, etc.). Apple Developer Support couldn’t provide info and suggested asking on the forums. Questions: 1. Is it permitted for a third-party iOS app to query time.apple.com via NTP/SNTP (Yes/No or conditional)? 2. If permitted, are there any published or recommended constraints (rate limits, caching, prohibited patterns, commercial app considerations)? 3. If not permitted / not recommended, what is the recommended alternative approach (run our own time service, use public NTP pool, or any Apple-recommended mechanism)? 4. If there is any official document / policy covering this, could you point me to it? For context: I do not need sub-second accuracy and I do not intend high-frequency polling. If implemented at all, it would be very low frequency (e.g., first launch + once per 24h) with caching and graceful fallback on failure. My main goal is policy clarity rather than implementation details.
Replies
2
Boosts
0
Views
145
Activity
Jan ’26
App Crashes on iOS 26 in Network.framework / boringssl – objc_release & memory corruption
Hello Apple Support Team, We are seeing a production crash on iOS 26 devices that appears to originate from Apple system frameworks rather than application code. 1. Crash Details OS Version: iOS 26.x App built with: Xcode 16 Devices: Multiple models (not device-specific) Exception Type: SIGSEGV SEGV_ACCERR Fault Address: 0x0000000000000100 Crashed Thread: 4 (network background queue) Crash trace summary: Last Exception : 0 libobjc.A.dylib _objc_release_x8 + 8 1 libboringssl.dylib _nw_protocol_boringssl_deallocate_options + 92 2 Network 0x000000019695207c 0x00000001968dc000 + 483452 3 libswiftCore.dylib __swift_release_dealloc + 56 4 libswiftCore.dylib bool swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1> >::doDecrementSlow<(swift::PerformDeinit)1>(swift::RefCountBitsT<(swift::RefCountInlinedness)1>, unsigned int) + 152 5 Network 0x0000000196951f6c 0x00000001968dc000 + 483180 6 Network 0x0000000196952000 0x00000001968dc000 + 483328 7 libswiftCore.dylib __swift_release_dealloc + 56 8 libswiftCore.dylib bool swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1> >::doDecrementSlow<(swift::PerformDeinit)1>(swift::RefCountBitsT<(swift::RefCountInlinedness)1>, unsigned int) + 152 9 libswiftCore.dylib void multiPayloadEnumFN<&handleRefCountsDestroy>(swift::TargetMetadata<swift::InProcess> const*, swift::LayoutStringReader1&, unsigned long&, unsigned char*) + 248 10 libswiftCore.dylib swift::swift_cvw_arrayDestroy(swift::OpaqueValue*, unsigned long, unsigned long, swift::TargetMetadata<swift::InProcess> const*) + 1172 11 libswiftCore.dylib _$sSp12deinitialize5countSvSi_tF + 40 12 CollectionsInternal ___swift_instantiateGenericMetadata + 1236 13 CollectionsInternal ___swift_instantiateGenericMetadata + 388 14 CollectionsInternal ___swift_instantiateGenericMetadata + 1044 15 libswiftCore.dylib __swift_release_dealloc + 56 16 libswiftCore.dylib bool swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1> >::doDecrementSlow<(swift::PerformDeinit)1>(swift::RefCountBitsT<(swift::RefCountInlinedness)1>, unsigned int) + 152 17 Network 0x000000019695f9fc 0x00000001968dc000 + 539132 18 Network 0x000000019695f9bc 0x00000001968dc000 + 539068 19 libswiftCore.dylib __swift_release_dealloc + 56 20 libswiftCore.dylib bool swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1> >::doDecrementSlow<(swift::PerformDeinit)1>(swift::RefCountBitsT<(swift::RefCountInlinedness)1>, unsigned int) + 152 21 libswiftCore.dylib swift_cvw_destroyImpl(swift::OpaqueValue*, swift::TargetMetadata<swift::InProcess> const*) + 212 22 Network 0x0000000196def5d8 0x00000001968dc000 + 5322200 23 Network 0x0000000196ded130 0x00000001968dc000 + 5312816 24 libswiftCore.dylib __swift_release_dealloc + 56 25 libswiftCore.dylib bool swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1> >::doDecrementSlow<(swift::PerformDeinit)1>(swift::RefCountBitsT<(swift::RefCountInlinedness)1>, unsigned int) + 152 26 Network 0x000000019695fde0 0x00000001968dc000 + 540128 27 libobjc.A.dylib object_cxxDestructFromClass(objc_object*, objc_class*) + 116 28 libobjc.A.dylib objc_destructInstance_nonnull_realized(objc_object*) + 76 29 libobjc.A.dylib __objc_rootDealloc + 72 30 Network 0x000000019695f99c 0x00000001968dc000 + 539036 31 Network 0x000000019695fae4 0x00000001968dc000 + 539364 32 Network 0x0000000196b078b8 0x00000001968dc000 + 2275512 33 libobjc.A.dylib object_cxxDestructFromClass(objc_object*, objc_class*) + 116 34 libobjc.A.dylib objc_destructInstance_nonnull_realized(objc_object*) + 76 35 libobjc.A.dylib __objc_rootDealloc + 72 36 Network 0x0000000196b07658 0x00000001968dc000 + 2274904 37 Network 0x00000001968e51d4 nw_queue_context_async_if_needed + 92 38 Network 0x0000000197686ea0 0x00000001968dc000 + 14331552 39 libswiftCore.dylib swift::swift_cvw_arrayDestroy(swift::OpaqueValue*, unsigned long, unsigned long, swift::TargetMetadata<swift::InProcess> const*) + 436 40 libswiftCore.dylib _$sSp12deinitialize5countSvSi_tF + 40 41 CollectionsInternal ___swift_instantiateGenericMetadata + 1236 42 CollectionsInternal ___swift_instantiateGenericMetadata + 388 43 CollectionsInternal ___swift_instantiateGenericMetadata + 1044 44 libswiftCore.dylib __swift_release_dealloc + 56 45 libswiftCore.dylib bool swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1> >::doDecrementSlow<(swift::PerformDeinit)1>(swift::RefCountBitsT<(swift::RefCountInlinedness)1>, unsigned int) + 152 46 Network 0x000000019694a010 0x00000001968dc000 + 450576 47 libobjc.A.dylib object_cxxDestructFromClass(objc_object*, objc_class*) + 116 48 libobjc.A.dylib objc_destructInstance_nonnull_realized(objc_object*) + 76 49 libobjc.A.dylib __objc_rootDealloc + 72 50 Network 0x0000000196a330e0 0x00000001968dc000 + 1405152 51 Network 0x00000001974378e0 0x00000001968dc000 + 11909344 52 Network 0x0000000196a17178 0x00000001968dc000 + 1290616 53 libdispatch.dylib __dispatch_call_block_and_release + 32 54 libdispatch.dylib __dispatch_client_callout + 16 55 libdispatch.dylib _dispatch_workloop_invoke.cold.4 + 32 56 libdispatch.dylib __dispatch_workloop_invoke + 1980 57 libdispatch.dylib __dispatch_root_queue_drain_deferred_wlh + 292 58 libdispatch.dylib __dispatch_workloop_worker_thread + 692 59 libsystem_pthread.dylib __pthread_wqthread + 292 ------ Exception Type: SIGSEGV SEGV_ACCERR Exception Codes: fault addr: 0x0000000000000100 Crashed Thread: 4 2. Behavior & Context The crash occurs during normal HTTPS networking using standard URLSession (no direct usage of Network.framework nor boringssl APIs). It appears to be triggered during QUIC connection establishment or TLS fallback. The stack trace contains no application code frames — all symbols are from system libraries. The crash strongly indicates double-free, over-release, or dangling pointer inside nw_protocol_boringssl_options deallocation. 3. Questions for Apple Is this a known issue in iOS 26 within Network.framework / boringssl related to nw_protocol_boringssl_deallocate_options? What is the root cause of the over‑release / invalid objc_release in this path? Is there a workaround we can implement from the app side (e.g., disabling QUIC, adjusting TLS settings, or queue configuration)? Do you have a target iOS version or patch where this issue will be fixed? We can provide full crash logs and additional metrics upon request. 4. Additional Information Developed using Swift 5, with a deployment target of iOS 12+. Thank you for your support.
Replies
1
Boosts
2
Views
153
Activity
Mar ’26
URLCache behavior for request with different header values
Greetings, I would like to understand this URLCache behavior for two different requests to the same end point but with a different header value. Here is a code with comment explaining the behavior. // Create a request to for a url. let url = URL(string: "https://&lt;my url&gt;?f=json")! var request = URLRequest(url: url) // Set custom header with a value. request.setValue("myvalue", forHTTPHeaderField: "CustomField") // Send request to get the response. let (data, response) = try await URLSession.shared.data(for: request) print("data: \(String(describing: String(data: data, encoding: .utf8)))") print("response: \(response)") // Create second request to the same url but with different value of custom header field. var request2 = URLRequest(url: url) request2.setValue("newvalue", forHTTPHeaderField: "CustomField") // Check the URL cache for second request and it returns the response // of the first request even though the second request has different header value. let cachedResponse = URLCache.shared.cachedResponse(for: request2) print("cachedResponse: \(cachedResponse?.response)") Is this a bug in URLCache that request headers are not matched while returning the response? Is this an expected behavior? If yes, why?
Replies
8
Boosts
2
Views
1.7k
Activity
Aug ’25
Need Inputs on Which Extension to Use
Hi all, I have a working macOS (Intel) system extension app that currently uses only a Content Filter (NEFilterDataProvider). I need to capture/log HTTP and HTTPS traffic in plain text, and I understand NETransparentProxyProvider is the right extension type for that. For HTTPS I will need TLS inspection / a MITM proxy — I’m new to that and unsure how complex it will be. For DNS data (in plain text), can I use the same extension, or do I need a separate extension type such as NEPacketTunnelProvider, NEFilterPacketProvider, or NEDNSProxyProvider? Current architecture: Two Xcode targets: MainApp and a SystemExtension target. The SystemExtension target contains multiple network extension types. MainApp ↔ SystemExtension communicate via a bidirectional NSXPC connection. I can already enable two extensions (Content Filter and TransparentProxy). With the NETransparentProxy, I still need to implement HTTPS capture. Questions I’d appreciate help with: Can NETransparentProxy capture the DNS fields I need (dns_hostname, dns_query_type, dns_response_code, dns_answer_number, etc.), or do I need an additional extension type to capture DNS in plain text? If a separate extension is required, is it possible or problematic to include that extension type (Packet Tunnel / DNS Proxy / etc.) in the same SystemExtension Xcode target as the TransparentProxy? Any recommended resources or guidance on TLS inspection / MITM proxy setup for capturing HTTPS logs? There are multiple DNS transport types — am I correct that capturing DNS over UDP (port 53) is not necessarily sufficient? Which DNS types should I plan to handle? I’ve read that TransparentProxy and other extension types (e.g., Packet Tunnel) cannot coexist in the same Xcode target. Is that true? Best approach for delivering logs from multiple extensions to the main app (is it feasible)? Or what’s the best way to capture logs so an external/independent process (or C/C++ daemon) can consume them? Required data to capture (not limited to): All HTTP/HTTPS (request, body, URL, response, etc.) DNS fields: dns_hostname, dns_query_type, dns_response_code, dns_answer_number, and other DNS data — all in plain text. I’ve read various resources but remain unclear which extension(s) to use and whether multiple extension types can be combined in one Xcode target. Please ask if you need more details. Thank you.
Replies
5
Boosts
0
Views
310
Activity
Jan ’26
Bonjour Conformance Test WARNING in Multicast DNS SHARED REPLY TIMING resolution
Hello and Good day! We are conducting Bonjour Conformance Test (BCT) for Printer device. BCT result is PASSED but with warning in Multicast DNS, specifically, WARNING: SHARED REPLY TIMING - UNIFORM RANDOM REPLY TIME DISTRIBUTION Other Shared Reply Timing is passed: PASSED: MULTIPLE QUESTIONS - SHARED REPLY TIMING - UNIFORM RANDOM REPLY TIME DISTRIBUTION Environment: BCT Tool Version: 1.5.4 (15400) MacOS Sequioa 15.5 DUT Firmware : Linux Debian 9 Apple mDNSResponder 1790.80.10 Service types: _ipps._tcp, _uscans._tcp, _ipp._tcp, _uscan._tcp Router : NEC AtermWR8370N Setup: 1-to-1 [Mac->Router<-DUT connection] Based on debug.log, this is where WARNING occurs: NOTICE 2026-03-04 10:51:06.870187+0900 _shared_reply_timing 04103: Shared reply response times: min = 26ms, max = 114ms, avg = 65.50ms WARNING 2026-03-04 10:51:06.870361+0900 _shared_reply_timing 04136: 50 percent of the replies within the correct range fell in the interval 20ms and 46ms (should be close to 25%). PASSED (SHARED REPLY TIMING) In the same debug.log for MULTIPLE QUESTIONS - SHARED REPLY TIMING is PASSED: NOTICE 2026-03-04 10:52:29.912334+0900 _shared_reply_timing 04103: Shared reply response times: min = 22ms, max = 112ms, avg = 78.00ms DEBUG_2 2026-03-04 10:52:29.912849+0900 recv_packet 01997: received packet (558 bytes) PASSED (MULTIPLE QUESTIONS - SHARED REPLY TIMING) [Details] Looking at Bonjour_Conformance_Guideline.pdf https://download.developer.apple.com/Documentation/Bonjour_Conformance_Test_Guideline/Bonjour_Conformance_Guideline.pdf there were some differences: In 1.6.2 Expected Result: Test Result File of Test that All Tests Passed, this is not displayed: PASSED: SHARED REPLY TIMING - UNIFORM RANDOM REPLY TIME DISTRIBUTION And in II.8 Shared Reply Timing: (Ideally, 25% of the answers should fall in each 21ms quadrant of the range 20ms - 125ms.) and comparing to the debug.log, there was a discrepancy of the interval, because 20ms and 46ms is 26ms interval. From RFC6762 6. Responding, Ideal range is from 20ms-120ms Because of this, please advise on the questions below: I would like to know on the possible cause and resolution for these WARNINGS. And since in current BCT result, (Test result integrity signature is generated), I would like to know if this is acceptable for BCT certification. Thank you.
Replies
9
Boosts
0
Views
247
Activity
3w
NEAppProxyUDPFlow.writeDatagrams fails with "The datagram was too large" on macOS 15.x, macOS 26.x
I'm implementing a NEDNSProxyProvider on macOS 15.x and macOS 26.x. The flow works correctly up to the last step — returning the DNS response to the client via writeDatagrams. Environment: macOS 15.x, 26.x Xcode 26.x NEDNSProxyProvider with NEAppProxyUDPFlow What I'm doing: override func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool { guard let udpFlow = flow as? NEAppProxyUDPFlow else { return false } udpFlow.readDatagrams { datagrams, endpoints, error in // 1. Read DNS request from client // 2. Forward to upstream DNS server via TCP // 3. Receive response from upstream // 4. Try to return response to client: udpFlow.writeDatagrams([responseData], sentBy: [endpoints.first!]) { error in // Always fails: "The datagram was too large" // responseData is 50-200 bytes — well within UDP limits } } return true } Investigation: I added logging to check the type of endpoints.first : // On macOS 15.0 and 26.3.1: // type(of: endpoints.first) → NWAddressEndpoint // Not NWHostEndpoint as expected On both macOS 15.4 and 26.3.1, readDatagrams returns [NWEndpoint] where each endpoint appears to be NWAddressEndpoint — a type that is not publicly documented. When I try to create NWHostEndpoint manually from hostname and port, and pass it to writeDatagrams, the error "The datagram was too large" still occurs in some cases. Questions: What is the correct endpoint type to pass to writeDatagrams on macOS 15.x, 26.x? Should we pass the exact same NWEndpoint objects returned by readDatagrams, or create new ones? NWEndpoint, NWHostEndpoint, and writeDatagrams are all deprecated in macOS 15. Is there a replacement API for NEAppProxyUDPFlow that works with nw_endpoint_t from the Network framework? Is the error "The datagram was too large" actually about the endpoint type rather than the data size? Any guidance would be appreciated. :-))
Replies
7
Boosts
0
Views
188
Activity
1w