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

OS 26.0 mDNSResponder suppresses DNS queries ("blocked by policy") for some devices until reboot
Hello, Since the release of iOS 26.0, we are seeing DNS traffic being blocked from within our NEPacketTunnelExtension on some devices. We have not isolated exact reproduction steps, but DNS resolves successfully for a period of time after enabling "iCloud Private Relay" (varying from 1-day to 2-weeks), until it then fails as MDNSResponder then returns: mDNSResponder [Q37046] DetermineUnicastQuerySuppression: Query suppressed for <mask.hash: 'REDACTED'> Addr (blocked by policy) DNS resolution continues to fail for all domains with the above until the device is rebooted. The Packet Tunnel intentionally does not have a DNS server set and this occurs for traffic from the Extension yet off-tunnel, which needs resolution from the system DNS server (and this configuration works perfectly for a period of time before being "blocked by policy"). The following do not resolve the issue once DNS queries are being "blocked by policy" on affected devices: disconnecting then reconnecting the vpn; toggling airplane mode for 10+ seconds; switching connection between WiFi & cellular data; disabling iCloud Private Relay. We have currently only seen this on unmanaged devices running iOS 26.0 or 26.1 beta and with iCloud Private Relay enabled. We did not see this issue on iOS 16,17 nor 18. We also have not yet seen this when iCloud Private Relay is disabled nor on iOS 26.0.1, however we cannot confirm whether they too are also affected. Is there a known a bug with iOS 26.0 & 26.1 Beta 1 that could cause this? How can we prevent DNS requests from NEPacketTunnelExtension being sporadically "blocked by policy" until the device is rebooted? Many thanks in advance.
1
1
80
Oct ’25
Multipeer Connectivity connection is flaky on iOS 26
While updating our test devices to iOS 26, we noticed that the connection between devices are flaky. Often when connecting to a Peer from a device running iOS 26 we can observe the invite coming through and when accepting said invite, both ends going to .connecting state and a while later going back to .notConnected within the peer(_ peerID: MCPeerID, didChange state: MCSessionState) function. This happens regularly and retrying the invitation process several times usually resolves it. Do anyone have any information or guidance on how to resolve this issue?
1
0
211
Oct ’25
Local Hotspot
Hello, we are developing hardware that needs to connect to an iPhone via Wi-Fi to send requests to a server. On Android, we have managed to create a programmatic local hotspot within the app to facilitate connection and improve the user experience. On iOS, however, Personal Hotspot must be manually enabled from the system settings, and the user must manually enter the SSID and password, which significantly degrades the UX. My questions are: Is there a workaround, unofficial method, or private API to generate a local hotspot from an app on iOS, similar to what can be done on Android? Is there an alternative within the MFi program or through specific frameworks to facilitate a quick and automatic connection between the hardware and the iPhone without relying on the manual Personal Hotspot? Are there any best practices for improving the local Wi-Fi connection experience between an accessory and an iPhone in the absence of hotspot controls? I would appreciate any guidance, experience, or resources that would help me better understand the feasible options in iOS for scenarios where fast and direct communication between hardware and mobile devices via Wi-Fi is required.
1
0
79
Sep ’25
Completion handler blocks are not supported in background sessions
When I try to implement the new Background Task options in the same way as they show in the WWDC video (on watchOS) likes this: let config = URLSessionConfiguration.background(withIdentifier: "SESSION_ID") config.sessionSendsLaunchEvents = true let session = URLSession(configuration: config) let response = await withTaskCancellationHandler {       try? await session.data(for: request) } onCancel: {       let task = session.downloadTask(with: request))       task.resume() } I'm receiving the following error: Terminating app due to uncaught exception 'NSGenericException', reason: 'Completion handler blocks are not supported in background sessions. Use a delegate instead.' Did I forget something?
7
2
2.5k
Apr ’25
A server with the specified hostname could not be found exception
Hi, I have been working on the app that implements DNS Proxy Extension for a while now, and after a couple builds to TestFlight I noticed that I got a couple crashes that seem to be triggered by EXC_BREAKPOINT (SIGTRAP) After some investigation, it was found that crashes are connected to CFNetwork framework. So, I decided to additionally look into memory issues, but I found the app has no obvious memory leaks, no memory regression (within recommended 25%, actual value is at 20% as of right now), but the app still uses 11mb of memory footprint and most of it (6.5 mb is Swift metadata). At this point, not sure what's triggering those crashes, but I noticed that sometimes app will return message like this to the console (this example is for PostHog api that I use in the app): Task <0ABDCF4A-9653-4583-9150-EC11D852CA9E>.<1> finished with error [18 446 744 073 709 550 613] Error Domain=NSURLErrorDomain Code=-1003 "A server with the specified hostname could not be found." UserInfo={_kCFStreamErrorCodeKey=8, NSUnderlyingError=0x1072df0f0 {Error Domain=kCFErrorDomainCFNetwork Code=-1003 "(null)" UserInfo={_kCFStreamErrorDomainKey=12, _kCFStreamErrorCodeKey=8, _NSURLErrorNWResolutionReportKey=Resolved 0 endpoints in 2ms using unknown from cache, _NSURLErrorNWPathKey=satisfied (Path is satisfied), interface: en0[802.11], ipv4, dns, uses wifi}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalUploadTask <0ABDCF4A-9653-4583-9150-EC11D852CA9E>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=( "LocalUploadTask <0ABDCF4A-9653-4583-9150-EC11D852CA9E>.<1>" ), NSLocalizedDescription=A server with the specified hostname could not be found., NSErrorFailingURLStringKey=https://us.i.posthog.com/batch, NSErrorFailingURLKey=https://us.i.posthog.com/batch, _kCFStreamErrorDomainKey=12} If DNS Proxy Provider uses custom DoH server for resolving packets, could the cache policy for URLSession be a reason? I had a couple other ideas (HTTP3 failure, CFNetwork core issues like described here) but not sure if they are valid Would be grateful if someone could give me a hint of what I should look at
19
1
3.4k
Nov ’24
Accessory Setup Kit (BLE) not showing multiple options nor the advertising name
I'm developing an application using the accessory setup kit (BLE) on iOS 18+. An important aspect of the connection process is being able to find and choose the correct device. I noticed on iOS 18.2 that I was able to both scroll through the discovered accessories as well as view the advertised name. However, after upgrading to 18.7.2, only a single device is viewable and the advertised name is no longer available. Is there a trigger for this feature that I need to enable or was this "multiple discovery" feature removed? If so, why?
0
1
89
Oct ’25
Get grpc trailer fields through NSURLSession
I'm trying to implement support for grpc http/2 streams using NSURLSession. Almost everything works fine, data streaming is flowing from the server and from the client and responses are coming through my NSURLSessionTaskDelegate. I'm getting the responses and streamed data through the appropriate handlers (didReceiveData, didReceiveResponse). However, I cannot seem to find an API to access the trailers expected by grpc. Specifically, the expected trailer "grpc-status: 0" is in the response, but after the data. Is there no way to gain access to trailers in the NSURLSession Framework?
3
0
126
3w
The network connection fails with NEFilterDataProvider and QQMusic running at the same time
The environment: macOS 12.0 ~ 15.6 A NetworkExtension NEFilterDataProvider configured with filterSockets = YES, filterPackets = NO, and it doesn't actually block any network connection. QQMusic (download: https://y.qq.com/n/ryqq/download_detail/mac?ADTAG=YQQ) is constantly playing. Any of the following operations can reproduce the issue: Kill the NetworkExtension process and then restarted by the system. Disable the NEFilterDataProvider, and then enable it. When this problem occurs, there are two different phenomena on the NetworkExtension process: It is zombie, or is in high CPU state (100%). When the NetworkExtension process is zombie, obviously, the new network connections will enter it, and they can't be disposed by the old zombie process, so the network is disconnected. Spindump-qqmusic-ne-zombie When the NetworkExtension process is in high CPU state, its thread DispatchQueue "NEFilterExtensionProviderContext queue" is blocked in the kernel when calling close. Spindump-qqmusic-ne-cpuhigh In most cases, the network will recover after stopping QQ Music, that is the suspended zombie NetworkExtension process will exist or the cpu of it return to normal. To reproduce the issue in a simple environment, I have tried many ways to simulate the network behavior of QQMusic, but all failed. It seems that this issue is caused by UDP traffic of QQMusic, because everything is ok after blocking the UDP connections of QQMusic (the music is still playing at this time) in the NEFilterDataProvider.
2
0
101
4w
DeviceDiscoveryUI and Bonjour for iOS
I have some confusion around the usage of DeviceDiscoveryUI. The documentation suggests that it is available only on TVOS. But with the recent announcement of WifiAware, it has been used in iOS devices as well. Within DeviceDiscoveryUI, the DevicePicker or the DevicePairingView documentation seems to be available with iOS. Is this just a documentation mistake? Followup - Can I use DeviceDiscoveryUI's DevicePicker/ DevicePairingView to discover devices through Bonjour and then establish a connection through Network framework?
2
1
104
Oct ’25
URL Filter - blocked web page behaviour
1) Blocked page UX When a URL is blocked, the browser typically shows a generic error like “"Safari cannot open the page because it couldn’t load any data,” with no indication that the page was blocked by a policy. Is there any plan to add an API that allows developers to present a custom “blocked” page or remediation action, similar to NEFilterControlProvider’s remediationMap? Even a minimal hook (custom HTML, deep link, or support URL) would make the experience clearer for users. 2) Cross‑app link‑opening behavior With a block rule in place, direct navigation in Safari is blocked as expected. However, tapping the same URL in a messaging app (e.g., WhatsApp) opens Safari - and the page loads, not blocked. Repro steps: Configure a URL Filter extension that blocks https://example.com. Case A: Open a browser and type the URL in the address bar → blocked (expected). Case B: Tap the same URL in WhatsApp (or another messenger) → a browser opens and the page loads (unexpected). iOS version - 26.0
1
0
113
Sep ’25
URL Filter not blocking specified keywords
I have been playing around with the new URL Filtering API. I have successfully installed and configured the sample code, Installed the example app to my iPhone, and am also running the PIR server locally on my Mac. In my input.txtpb file, I simply have 2 endpoints: rows: [{ keyword: "instagram.com", value: "1" }, { keyword: "youtube.com/shorts", value: "1" }] Neither of these are blocked when I attempt to load them from either a browser, or their dedicated apps. Are there any debugging tips I should know about? Additionally, I have also noticed a few times I have left the filter running on my phone, after leaving my LAN (where the PIR server is running), suddenly throughout the day I'm having random, completely unrelated endpoints blocked on my phone. I thought this API was never supposed to produce false positives (without calling back to the PIR server for confirmation).
2
0
124
Sep ’25
VPN Split DNS behaviour
I encountered an undesired DNS behaviour when using L2TP/ipsec VPN. I have DHCP configured Wi-Fi connection, which send dns servers and search domain (192.168.0.10, lan) VPN sends its own DNS server (10.0.0.2), search domain (intranet) is added manually in VPN DNS config settings. I expect, when VPN is connected, to be still able to resolve local names, i.e some-host.lan. However, they become unresolvable. quick check shows that the remote dns server is used to resolve local names. shilishper@mac ~ % host -v some-host.lan Trying "some-host.lan" Host some-host.lan not found: 3(NXDOMAIN) Received 106 bytes from 10.0.0.2#53 in 16 ms Received 106 bytes from 10.0.0.2#53 in 16 ms Actually, all dns queries are going to the remote server. I would expect that only queries for the configured domain (intranet) should go to that server. I played with the service order, but it didn't change anything. Is anything can be done about this, programmatically? PS new to macOS, but have extensive linux knowledge
2
0
113
Sep ’25
Applications stuck in UDP sendto syscall
Hi, We’re seeing our build system (Gradle) get stuck in sendto system calls while trying to communicate with other processes via the local interface over UDP. To the end user it appears that the build is stuck or they will receive an error “Timeout waiting to lock XXX. It is currently in use by another Gradle instance”. But when the process is sampled/profiled, we can see one of the threads is stuck in a sendto system call. The only way to resolve the issue is to kill -s KILL <pid> the stuck Gradle process. A part of the JVM level stack trace: "jar transforms Thread 12" #90 prio=5 os_prio=31 cpu=0.85ms elapsed=1257.67s tid=0x000000012e6cd400 nid=0x10f03 runnable [0x0000000332f0d000] java.lang.Thread.State: RUNNABLE at sun.nio.ch.DatagramChannelImpl.send0(java.base@17.0.10/Native Method) at sun.nio.ch.DatagramChannelImpl.sendFromNativeBuffer(java.base@17.0.10/DatagramChannelImpl.java:901) at sun.nio.ch.DatagramChannelImpl.send(java.base@17.0.10/DatagramChannelImpl.java:863) at sun.nio.ch.DatagramChannelImpl.send(java.base@17.0.10/DatagramChannelImpl.java:821) at sun.nio.ch.DatagramChannelImpl.blockingSend(java.base@17.0.10/DatagramChannelImpl.java:853) at sun.nio.ch.DatagramSocketAdaptor.send(java.base@17.0.10/DatagramSocketAdaptor.java:218) at java.net.DatagramSocket.send(java.base@17.0.10/DatagramSocket.java:664) at org.gradle.cache.internal.locklistener.FileLockCommunicator.pingOwner(FileLockCommunicator.java:61) at org.gradle.cache.internal.locklistener.DefaultFileLockContentionHandler.maybePingOwner(DefaultFileLockContentionHandler.java:203) at org.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock$1.run(DefaultFileLockManager.java:380) at org.gradle.internal.io.ExponentialBackoff.retryUntil(ExponentialBackoff.java:72) at org.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock.lockStateRegion(DefaultFileLockManager.java:362) at org.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock.lock(DefaultFileLockManager.java:293) at org.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock.<init>(DefaultFileLockManager.java:164) at org.gradle.cache.internal.DefaultFileLockManager.lock(DefaultFileLockManager.java:110) at org.gradle.cache.internal.LockOnDemandCrossProcessCacheAccess.incrementLockCount(LockOnDemandCrossProcessCacheAccess.java:106) at org.gradle.cache.internal.LockOnDemandCrossProcessCacheAccess.acquireFileLock(LockOnDemandCrossProcessCacheAccess.java:168) at org.gradle.cache.internal.CrossProcessSynchronizingCache.put(CrossProcessSynchronizingCache.java:57) at org.gradle.api.internal.changedetection.state.DefaultFileAccessTimeJournal.setLastAccessTime(DefaultFileAccessTimeJournal.java:85) at org.gradle.internal.file.impl.SingleDepthFileAccessTracker.markAccessed(SingleDepthFileAccessTracker.java:51) at org.gradle.internal.classpath.DefaultCachedClasspathTransformer.markAccessed(DefaultCachedClasspathTransformer.java:209) at org.gradle.internal.classpath.DefaultCachedClasspathTransformer.transformFile(DefaultCachedClasspathTransformer.java:194) at org.gradle.internal.classpath.DefaultCachedClasspathTransformer.lambda$cachedFile$6(DefaultCachedClasspathTransformer.java:186) at org.gradle.internal.classpath.DefaultCachedClasspathTransformer$$Lambda$368/0x0000007001393a78.call(Unknown Source) at org.gradle.internal.UncheckedException.unchecked(UncheckedException.java:74) at org.gradle.internal.classpath.DefaultCachedClasspathTransformer.lambda$transformAll$8(DefaultCachedClasspathTransformer.java:233) at org.gradle.internal.classpath.DefaultCachedClasspathTransformer$$Lambda$372/0x0000007001398470.call(Unknown Source) at java.util.concurrent.FutureTask.run(java.base@17.0.10/FutureTask.java:264) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64) at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@17.0.10/ThreadPoolExecutor.java:1136) at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@17.0.10/ThreadPoolExecutor.java:635) at java.lang.Thread.run(java.base@17.0.10/Thread.java:840) A part of the process sample: 2097 Thread_3879661: Java: jar transforms Thread 12 + 2097 thread_start (in libsystem_pthread.dylib) + 8 [0x18c42eb80] ...removed for brevity... + 2097 Java_sun_nio_ch_DatagramChannelImpl_send0 (in libnio.dylib) + 84 [0x102ef371c] + 2097 __sendto (in libsystem_kernel.dylib) + 8 [0x18c3f612c] We have observed the following system logs around the time the issue manifests: 2025-08-26 22:03:23.280255+0100 0x3b2c00 Default 0x0 0 0 kernel: cfil_hash_entry_log:6088 <CFIL: Error: sosend_reinject() failed>: [4628 java] <UDP(17) in so 9e934ceda1c13379 50826943645358435 50826943645358435 ag> 2025-08-26 22:03:23.280267+0100 0x3b2c00 Default 0x0 0 0 kernel: cfil_service_inject_queue:4472 CFIL: sosend() failed 22 The issue seems to be rooted in the built-in Application Firewall, as disabling it “fixes” the issue. It doesn’t seem to matter that the process is on the “allow” list. We’re using Gradle 7.6.4, 8.0.2 and 8.14.1 in various repositories, so the version doesn’t seem to matter, neither does which repo we use. The most reliable way to reproduce is to run two Gradle builds at the same time or very quickly after each other. We would really appreciate a fix for this as it really negatively affects the developer experience. I've raised FB19916240 for this. Many thanks,
1
1
306
Aug ’25
PacketTunnelProvider gets corrupted when app updated with connected Tunnel
We currently supporting proxy app with Tunnel.appEx and PacketTunnelProvider. Some users report about constant error "The VPN session failed because an internal error occurred." on VPN start (which fails rapidly). This error occur mostly after user updated app with active VPN. Rebooting device solves the problem and it doesnt come again, but it is still very frustrating. I can provide any required info about app setup to solve this issue if you need. Thanks
6
1
174
Aug ’25
Getting list of wifi networks nearby with a specific prefix
I'm building an app that helps manage my own wifi access points. Now, all my wifis emit SSIDs starting with the same prefix. Is it possible for me to list down all the SSIDs near me that start with that prefix, so that determine which of my wifis are near me? (Swift) Can NEHotspotHelper or NEHotspotConfigurationManager help in this regard?
1
1
297
Feb ’25
During the Wi-Fi Aware's pairing process, Apple is unable to recognize the follow-up PMF sent by Android.
iPhone 12 pro with iOS 26.0 (23A5276f) App: https://developer.apple.com/documentation/wifiaware/building-peer-to-peer-apps We aim to use Wi-Fi Aware to establish file transfer between Android and Apple devices. Apple will act as the Publisher, and Android will act as the Subscriber. According to the pairing process outlined in the Wi-Fi Aware protocol (Figure 49 in the Wi-Fi Aware 4.0 specification), the three PASN Authentication frames have been successfully exchanged. Subsequently, Android sends the encrypted Follow-up PMF to Apple, but the Apple log shows: Failed to parse event. Please refer to the attached complete log. We request Apple to provide a solution. apple Log-20250808a.txt
10
1
535
Aug ’25
Prevent SSL Handshake with User Installed Certificates
how can I prevent handshake when certificate is user installed for example if user is using Proxyman or Charles proxy and they install their own certificates now system is trusting those certificates I wanna prevent that, and exclude those certificates that are installed by user, and accept the handshake if CA certificate is in a real valid certificate defined in OS I know this can be done in android by setting something like <network-security-config> <base-config> <trust-anchors> <certificates src="system" /> </trust-anchors> </base-config> </network-security-config>
4
1
146
Aug ’25
Unable to understand Flow of Network extension for iOS
For a past few days, I have been exploring control Filter and data filter. I am unable to understand how control moves from various functions of data filter to control Filter. One thing that I am unable to figure out is that when I pass verdict as .allow in dataFilter's handleNewFlow and mark .shouldReport as true, I get inBytes and outbytes in the flow report of handle() in controlFilter. But when I pass verdict as needRules and wait till the handle is called in controlFilter when the report.event == .flowClosed, I don't get inBytes and outBytes. I am unable to understand this complete flow of network extension from the apple documentation. Can someone provide me with some flow chart or some pictorial representation or detailed explanation of network extension for iOS? Also is there some way to imitate the ..statisticsReportFrequency for iOS as it is not available for iOS?
3
1
145
Aug ’25