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

My app suddenly getting "A server with the specified hostname could not be found"
I've had no problem running my app in a simulator or on a device, but today my app is failing on a URLRequest to my local machine (in a sim). From the same simulator I can go to Safari and manually enter the URL that the app is using (and that appears in the error message), and it works fine. I think there was a recent Xcode update; did something change in this regard?
6
0
183
May ’25
Web Socket and HTTP connection will work under under a carrier-provided satellite network?
We are currently working on enhancing our iOS app with satellite mode support, allowing users to access a limited set of core features even in the absence of traditional cellular or Wi-Fi connectivity. As part of this capability, we're introducing a chatbot feature that relies on both WebSocket and HTTP connections for real-time interaction and data exchange. Given the constrained nature of satellite networks—especially in terms of latency, bandwidth, and connection stability—we're evaluating the feasibility of supporting these communication protocols under such conditions. Could you please advise whether WebSocket and HTTP connections are expected to work over satellite networks?
6
0
219
Jul ’25
NSURLErrorDomain Code=-1003 ... again!
This happens when trying to connect to my development web server. The app works fine when connecting to my production server. The production server has a certificate purchased from a CA. My development web server has a locally generated certificate (from mkcert). I have dragged and dropped the rootCA.pem onto the Simulator, although it doesn't indicate it has been loaded the certificate does appear in the Settings app and is checked to be trusted. I have enabled "App Sandbox" and "Outgoing connections (Client)". I have tested the URL from my local browser which is working fine. What am I missing?
6
0
685
Jul ’25
How can I programmatically access the NETunnelProviderManager of a Per-App VPN?
I have an iOS app which contains a Network Extension that subclasses the NEPacketTunnelProvider, acting as a packet-tunnel VPN. After deploying the app on the device as a regular app, it runs the following code fragment: NETunnelProviderManager.loadAllFromPreferences { managers, _ in self.manager = managers?.first ?? NETunnelProviderManager() self.manager.protocolConfiguration = getConfiguration() self.manager.saveToPreferences { error in // Handle errors or show a "Connect" button in the UI } } This asks the user to install the extension as a "Device VPN". I can then use try? self.manager?.connection.startVPNTunnel() to start the VPN (and later stop it when needed). So far, this works fine. Now, I want to deploy the app with an MDM and set it up as the "custom VPN" of a "Per-App VPN". I have tested the setup using a real MDM, AND using the "development" setup described in NETunnelProviderManager. In both cases, the "Per-App VPN" shows up as a VPN in the "Settings" app. However, in both cases I am unable to retrieve, configure or use the "Per-App VPN". The code fragment posted above returns no NETunnelProviderManager at all. When instantiating one on my own and triggering self.manager.saveToPreferences(), it queries the user to install a "Device VPN". While I can control and use the latter, this is clearly not what I want after having gone through the pain of installing the "Per-App VPN". How can I retrieve the NETunnelProviderManager of the "Per-App VPN"? And then use it to configure and control the VPN connection? (Ideally, I would like to use the same app and the same Network Extension for both use cases, leaving the choice of which VPN type to use to the user or the user's MDM administrator.)
6
0
309
Jan ’25
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
244
3d
How many instances of the same NEFilterDataProvider can there be in a running NE?
[Q] How many instances of the same NEFilterDataProvider subclass can there be in a single running Network Extension at any given time? I would expect that there can be only 1 instance but I'm looking at a memgraph where 2 instances are listed. As it's the Network Extension framework that is responsible for creating, starting and stopping these instances, this is rather strange.
6
0
127
Jul ’25
iOS NSURLSession mTLS: Client certificate not sent, error -1206
Hi everyone, I'm trying to establish a connection to a server that requires mutual TLS (mTLS) using NSURLSession in an iOS app. The server is configured with a self-signed root CA (in the project, we are using ca.cer) and requires clients to present a valid certificate during the TLS handshake. What I’ve done so far: Server trust is working: I manually trust the custom root CA using SecTrustSetAnchorCertificates and SecTrustEvaluateWithError. I also configured the necessary NSAppTransportSecurity exception in Info.plist to allow the server certificate to pass ATS. This is confirmed by logs showing: Server trust succeeded The .p12 identity is correctly created: Contains the client certificate and private key. Loaded using SecPKCS12Import with the correct password. I implemented the delegate method: func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust { // Server trust override code (working) ... } if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate { print("🔐 Client cert challenge triggered") if let identity = loadIdentity() { let credential = URLCredential(identity: identity, certificates: nil, persistence: .forSession) completionHandler(.useCredential, credential) } else { completionHandler(.cancelAuthenticationChallenge, nil) } return } completionHandler(.performDefaultHandling, nil) } The session is correctly created using my custom delegate: let delegate = MTLSDelegate(identity: identity, certificates: certs) let session = URLSession(configuration: .default, delegate: delegate, delegateQueue: nil) Despite everything above, the client certificate is never sent, and the request fails with: Error Domain=NSURLErrorDomain Code=-1206 "The server requires a client certificate." From logs, it's clear the delegate is being hit for NSURLAuthenticationMethodServerTrust, but not for NSURLAuthenticationMethodClientCertificate.
6
0
169
Aug ’25
NEPacketTunnelProvider Start Issue on macOS 14.5
We're encountering an issue with our Network Extension (utilizing NEPacketTunnelProvider and NETransparentProxy) on macOS 14.5 (23F79). On some systems, the VPN fails to automatically start after a reboot despite calling startVPNTunnel(). There are no error messages. Our code attempts to start the tunnel: ....... do { try manager.connection.startVPNTunnel() Logger.default("Started tunnel successfully") } catch { Logger.error("Failed to launch tunnel") } ...... System log analysis reveals the tunnel stopping due to userLogout (NEProviderStopReason(rawValue: 12)) during reboot. However, the Transparent Proxy stops due to userInitiated (NEProviderStopReason(rawValue: 1)) for the same reboot. We need to understand: Why the VPNTunnel isn't starting automatically. Why the userLogout reason is triggered during reboot. Additional Context: We have manually started the VPN from System Settings before reboot.
6
0
715
Oct ’25
[networkextesion] dnsproxy
hello I am testing the use of network extension. When we use dnsproxy to proxy DNS requests, we will send you a message that the udp pcbcount of your system continues to increase. For example for ((i=1; i<=99999; i++));do echo "Attempt $i:" dig google.com done when the dig command is used continuously, the dig command will show the following errors when pcbcount reaches a certain number. isc_socket_bind: address not available Can you help us determine what the problem might be? thank you
5
0
282
Feb ’25
CoreWLAN scanForNetworks does not expose SSIDs even when Location permission is authorized (Sequoia 15.1)
Hi, I've read a bunch of threads regarding the changes in Sonoma and later requiring Location permission for receiving SSIDs. However, as far as I can see, in Sequoia 15.1 SSIDs and BSSIDs are empty regardless. In particular, this makes it not possible to use associate(withName:) and associate(withSSID:) because the network object returned by scanForNetwork(withSSID: "...") has its .ssid and .bssid set to nil. Here is an example: First we have a wrapper to call the code after the location permission is authorized: import Foundation import CoreLocation class LocationDelegate: NSObject, CLLocationManagerDelegate { var onAuthorized: (() -> Void)? var onDenied: (() -> Void)? func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { let authStatus = manager.authorizationStatus print("Location authorization status changed: \(authStatusToString(authStatus))") if authStatus == .authorizedAlways { onAuthorized?() } else if authStatus == .denied || authStatus == .restricted { onDenied?() } } } let locationManager = CLLocationManager() let locationDelegate = LocationDelegate() func authorizeLocation(onAuthorized: @escaping () -> Void, onDenied: @escaping () -> Void) { let authStatus = locationManager.authorizationStatus print("Location authorization status: \(authStatusToString(authStatus))") if authStatus == .notDetermined { print("Waiting for location authorization...") locationDelegate.onAuthorized = onAuthorized locationDelegate.onDenied = onDenied locationManager.delegate = locationDelegate locationManager.requestAlwaysAuthorization() } else if authStatus == .authorizedAlways { onAuthorized() } else if authStatus == .denied || authStatus == .restricted { onDenied() } RunLoop.main.run() } func authStatusToString(_ status: CLAuthorizationStatus) -> String { switch status { case .notDetermined: return "Not Determined" case .restricted: return "Restricted" case .denied: return "Denied" case .authorizedAlways: return "Always Authorized" case .authorizedWhenInUse: return "Authorized When In Use" @unknown default: return "Unknown" } } Then, a demo program itself: import Foundation import CoreWLAN import Network let client = CWWiFiClient.shared() guard let interface = client.interface() else { print("No wifi interface") exit(1) } authorizeLocation( onAuthorized: { do { print("Scanning for wifi networks...") let scanResults = try interface.scanForNetworks(withSSID: nil) let networks = scanResults.compactMap { network -> [String: Any]? in return [ "ssid": network.ssid ?? "unknown", "bssid": network.bssid ?? "unknown" ] } let jsonData = try JSONSerialization.data(withJSONObject: networks, options: .prettyPrinted) if let jsonString = String(data: jsonData, encoding: .utf8) { print(jsonString) } exit(0) } catch { print("Error: \(error)") exit(1) } }, onDenied: { print("Location access denied") exit(1) } ) When launched, the program asks for permission, and after that, is shown as enabled in Privacy & Security Settings panel. Here is the output where it can be seen that the scan is performed after location access was authorized, and regardless of that, all ssids are empty: Location authorization status: Not Determined Waiting for location authorization... Location authorization status changed: Always Authorized Scanning for wifi networks... [ { "ssid" : "unknown", "bssid" : "unknown" }, { "ssid" : "unknown", "bssid" : "unknown" }, .... further omitted Calling scanForNetworks() with explicitly specified network name does this as well, returns a CWNetwork object with .ssid / .bssid = nil.
5
0
766
Dec ’24
XPC connection consistently invalidated on app upgrade
Hi, Our project is a MacOS SwiftUI GUI application that bundles a System Network Extension, signed with a Developer ID certificate for distribution outside of the app store. The system network extension is used to write a packet tunnel provider. The signing of the app & network extension is handled by XCode (v16.0.0), we do not run codesign ourselves. We have no issues with XPC or the system network extension during normal usage, nor when the application is installed on a user's device for the first time. The problem only arises when the user upgrades the application. I have experienced this issue myself, as have our users. It's been reported on Apple Silicon macbooks running at least macOS 15.3.2. Much like the SimpleFirewall example (which we used as a reference), we use XPC for basic communication of state between the app and NE. These XPC connections stop working when the user installs a new version of the app, with OS logs from the process indicating that the connection is immediately invalidated. Subsequent connection attempts are also immediately invalidated. Toggling the VPN in system settings (or via the app) does not resolve the problem, nor does restarting the app, nor does deleting and reinstalling the app, nor does restarting the device. The only reliable workaround is to delete the system extension in Login Items & Extensions, under Network Extensions. No device restart is necessary to garbage collect the old extension - once the extension is reapproved by the user, the XPC issue resolves itself. This would be an acceptable workaround were it possible to automate the deleting of the system extension, but that appears deliberately not possible, and requiring our users to do this each time they update is unreasonable. When the upgraded app is opened for the first time, the OSSystemExtensionRequest request is sent, and the outcome is that the previously installed system network extension is replaced, as both the CFBundleVersion and CFBundleShortVersionString differ. When this issue is encountered, the output of systemextensionsctl list shows the later version is installed and activated. I've been able to reproduce this bug on my personal laptop, with SIP on and systemextensionsctl developer off, but on my work laptop with SIP off and systemextensionsctl developer on (where the network extension is replaced on each activation request, instead of only when the version strings differ), I do not encounter this issue, which leads me to believe it has something to do with the notarization process. We notarize the pkg using xcrun notarytool, and then staple to the pkg. This is actually the same issue described in: https://developer.apple.com/forums/thread/711713 https://developer.apple.com/forums/thread/667597 https://developer.apple.com/forums/thread/742992 https://developer.apple.com/forums/thread/728063 but it's been a while since any of these threads were updated, and we've made attempts to address it off the suggestions in the threads to no avail. Those suggestions are: Switching to a .pkg installer from a .dmg As part of the .pkg preinstall, doing all of the following: Stopping the VPN (scutil --nc stop), shutting down the app (using osascript 'quit app id'), and deleting the app (which claims to delete the network extension, but not the approval in Login Items & Extensions remains??), by running rm -rf on the bundle in /Applications As part of the .pkg postinstall: Forcing macOS to ingest the App bundle's notarization ticket using spctl --assess. Ensuring NSXPCListener.resume() is called after autoreleasepool { NEProvider.startSystemExtensionMode() } (mentioned in a forum thread above as a fix, did not help.) One thing I'm particularly interested in is the outcome of this feedback assistant ticket, as I can't view it: FB11086599. It was shared on this forum in the first thread above, and supposedly describes the same issue. I almost find it hard to believe that this issue has been around for this many years without a workaround (there's system network extension apps out there that appear to work fine when updating, are they not using XPC?), so I wonder if there's a fix described in that FB ticket. Since I can't view that above feedback ticket, I've created my own: FB17032197
5
0
329
Jun ’25
connect() iOS 18.5 Developer Beta (22EF5042g)
Hello! 👋 I am noticing new failures in the iOS 18.5 Developer Beta build (22EF5042g) when calling the system call connect() (from C++ source, in network extension). When using cell/mobile data (Mint & T-Mobile) this returns with EINTR (interrupted system call) right away. When I switch over to wifi, everything works fine. Note: I have not tested on other mobile carriers; which could make a difference since T-Mobile/Mint are IPv6 networks. FWIW, this is working in the previous developer beta (18.4). Anyone have any ideas?
5
0
309
Apr ’25
How to restore macOS routing table after VPN crash or routing changes?
Hi, I have a VPN product for macOS. When activated, it creates a virtual interface that capture all outgoing traffic for the VPN. the VPN encrypt it, and send it to the tunnel gateway. The gateway then decapsulates the packet and forwards it to the original destination. To achieve this, The vpn modifies the routing table with the following commands: # after packets were encoded with the vpn protocol, re-send them through # the physical interface /sbin/route add -host <tunnel_gateway_address_in_physical_subnet> <default_gateway> -ifp en0 > /dev/null 2>&1 # remove the default rule for en0 and replace it with scoped rule /sbin/route delete default <default_gateway> -ifp en0 > /dev/null 2>&1 /sbin/route add default <default_gateway> -ifscope en0 > /dev/null 2>&1 # create new rule for the virtual interface that will catch all packets # for the vpn /sbin/route add default <tunnel_gateway_address_in_tunnel_subnet> -ifp utunX > /dev/null 2>&1 This works in most cases. However, there are scenarios where the VPN process may crash, stop responding, or another VPN product may alter the routing table. When that happens, packets may no longer go out through the correct interface. Question: Is there a way to reliably reconstruct the routing table from scratch in such scenarios? Ideally, I would like to rebuild the baseline rules for the physical interface (e.g., en0) and then reapply the VPN-specific rules on top. Are there APIs, system utilities, or best practices in macOS for restoring the original routing configuration before reapplying custom VPN routes? Thanks
5
0
327
Sep ’25
Network Push Provider Wifi Selection Behavior
In our App, we have a network extension with a NEAppPushProvider subclass running. We run the following steps Setup a dual-band wireless router per the following: Broadcasting 2.4 GHz and 5 GHz channels Same SSID names for both channels Connected to the production network to the router DHCP assigning addresses in the 10.1.x.x network Connect the mobile device to the 5 GHz network (if needed, turn off the 2.4 GHz network temporarily; once the device connects to the 5 GHz network, the 2.4 GHz network can be turned back on). Create a NEAppPushManager in the App, using the SSID from the above mentioned network and set it to the matchSSIDs property. Call saveToPreferences() on the push manager to save. A. We have UI that shows the extension has been started and it has connected to the server successfully. Walk out of the range of the 5 GHz channel of the router, but stay within range of the 2.4ghz channel. Wait for the mobile device to connect to the 2.4 GHz channel. Expected: The extension would reconnect to the 2.4ghz network. Observed: The extension does not reconnect. Checking the logs for the extension we see that the following was called in the push provider subclass. stop(with:completionHandler:) > PID: 808 | 🗒️🛑 Stopped with reason 3: "noNetworkAvailable" The expectation is that start() on the NEAppPushProvider subclass would be called. Is this an incorrect expectation? How does the NEAppPushProvider handle same network SSID roaming among various band frequencies? I looked at the documentation and did not find any settings targeting 2.4 or 5 ghz networks. Please advise on what to do.
5
1
118
Apr ’25
Network extension doesn't get the updated preferred language after changing phone language
We’ve noticed an issue where after running a network extension, if the phone’s language is changed the Locale.preferredLanguages array is not updated and still returns the old array. It only returns the updated array when the app is reinstalled or the phone is restarted. This is unlike the app itself where using the same Locale.preferredLanguages API immediately returns the updated array. We think this issue is also the cause of notifications that are sent by the network extension being in the previous language as long as the app isn’t reinstalled or the phone is restarted, despite our Localizable file having localised strings for the new language. Feedback ID: FB20086051 The feedback report includes a sample project with steps on how to reproduce the issue.
5
1
139
Sep ’25
XPC listener initialized in System Extesnion invalidates incoming connection under certain conditions
I found a problem where a process tries to connect to System Extension and connection is invalidated. XPC listener has to be disposed and initialized again. This happens when System Extension executes tasks in following order: NSXPCListener initialized NSXPCListener.resume() NSProvider.startSystemExtensionMode() Result: Connection is invalidated and not only that the client has to retry connection, nut also System Extension must reinitialize listener (execute step 1 and 2). However if I call NSProvider.startSystemExtensionMode() NSXPCListener initialized NSXPCListener.resume() It works as expected and even if the connection is invalidated/interrupted, client process can always reconnect and no other action is necessary in System Extension (no need to reinitialize XPC listener), In Apple docs about NSProvider.startSystemExtensionMode() it says that this method starts handling request, but in another online article written by Scott Knight I found that startSystemExtensionMode() also starts listener server. Is that right? PLease could you add this info into the docs if it is so? https://knight.sc/reverse%20engineering/2019/08/24/system-extension-internals.html I would like to use following logic: Call NSProvider.startSystemExtensionMode() only under certain circumstances - I have received some configuration that I need to process and do some setup. If I don't receive it, there is no reason to call startSystemExtensionMode() yet, I don't need to handle handleNewFlow() yet. Connect XPC client to System Extension under certain conditions. Ideally communicate with client even though System Extension is not handling network requests yet, that is without receiving handleNewFlow(). Basically I consider XPC and System Extension handling network requests as separate things. Is that correct, are they separate and independent? Does XPC communication really depend on calling startSystemExtensionMode()? Another potential issue: Is it possible that XPC listener fails to validate connection when client tries to connect before System Extension manages to complete init and park the main thread in CFRunLoop? Note: These querstions arose mostly from handling upgrades of System Extension (extension is already running, network filter is created and is connected and new version of the app upgrades System Exension). Thanks.
5
0
1.3k
Apr ’25
Socket Becomes Unresponsive in Local Connectivity Extension After Lock Screen
I’m developing an app designed for hospital environments, where public internet access may not be available. The app includes two components: the main app and a Local Connectivity Extension. Both rely on persistent TCP socket connections to communicate with a local server. We’re observing a recurring issue where the extension’s socket becomes unresponsive every 1–3 hours, but only when the device is on the lock screen, even if the main app remains in the foreground. When the screen is not locked, the connection is stable and no disconnections occur. ❗ Issue Details: • What’s going on: The extension sends a keep-alive ping packet every second, and the server replies with a pong and a system time packet. • The bug: The server stops receiving keep alive packets from the extension.  • On the server, we detect about 30 second gap on the server, a gap that shows no packets were received by the extension. This was confirmed via server logs and Wireshark).  • On the extension, from our logs there was no gap in sending packets. From it’s perspective, all packets were sent with no error.  • Because no packet are being received by the server, no packets will be sent to the extension. Eventually the server closes the connection due to keep-alive timeout.  • FYI we log when the NEAppPushProvider subclass sleeps and it did NOT go to sleep while we were debugging. 🧾 Example Logs: Extension log: 2025-03-24 18:34:48.808 sendKeepAliveRequest() 2025-03-24 18:34:49.717 sendKeepAliveRequest() 2025-03-24 18:34:50.692 sendKeepAliveRequest() ... // continuous sending of the ping packet to the server, no problems here 2025-03-24 18:35:55.063 sendKeepAliveRequest() 2025-03-24 18:35:55.063 keepAliveTimer IS TIME OUT... in CoreService. // this is triggered because we did not receive any packets from the server Server log: 2025-03-24 18:34:16.298 No keep-alive received for 16 seconds... connection ID=95b3... // this shows that there has been no packets being received by the extension ... 2025-03-24 18:34:30.298 Connection timed out on keep-alive. connection ID=95b3... // eventually closes due to no packets being received 2025-03-24 18:34:30.298 Remote Subsystem Disconnected {name=iPhone|Replica-Ext|...} ✅ Observations: • The extension process continues running and logging keep-alive attempts. • However, network traffic stops reaching the server, and no inbound packets are received by the extension. • It looks like the socket becomes silently suspended or frozen, without being properly closed or throwing an error. ❓Questions: • Do you know why this might happen within a Local Connectivity Extension, especially under foreground conditions and locked ? • Is there any known system behavior that might cause the socket to be suspended or blocked in this way after running for a few hours? Any insights or recommendations would be greatly appreciated. Thank you!
5
0
131
Apr ’25
Disable Local Network Access permission check
I'm using a Mac Studio in a homelab context and use Homebrew to manage the installed services. The services include things that access the local network, for example Prometheus which monitors some other servers, a reverse proxy which fronts other web services on the network, and a DNS server which can use another as upstream. Local Network Access permissions make it impossible to reliably perform unattended updates of services because an updated binary requires a GUI login to grant local network permissions (again). I use brew services to manage the services as launchd agents, i.e. they run in a non-root GUI context. I know that I can also use sudo brew services which instead installs the services as launchd daemons, but running services as root has negative security implication and generally doesn't look like a good idea to me. If only there was a way to disable local network access checks altogether…
5
0
191
Jun ’25
Reduced certificate lifespan: CA root
I have some concerns related to shortening the lifetime of certificates, as per https://support.apple.com/en-gb/102028 Does this apply to Private CA root certificates? And if yes: does it apply if I use ATS and higher level API like URLSession does it apply it I carry my root CA cert in my app payload and use low level libraries without ATS support?
5
0
471
Feb ’25