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

Created

How to use Network.framework
It doesn’t seem like there’s any high level, first-party documentation on how to use what is the recommended API for executing networking logic that you otherwise wouldn’t use URLSession for; which is a lot of things. There’s a sample app, and docs on how to choose the right network API in general, but apparently no high level API docs for Network.framework itself. Am I missing something? How do people learn to use this? Know which classes to use? Know the various ways it can be configured?
4
0
256
Mar ’25
IOS VPN APP DEPLOYMENT
Hi everyone, I developed an Android version of a VPN app built with Flutter using OpenVPN, and it works perfectly on Android. However, when porting it to iOS, I’ve encountered an issue: the app connects successfully but then automatically disconnects when tested via TestFlight. We’ve already added all the necessary network extensions. Despite this, we decided to submit the app to the App Store. It’s been five days now, and the app is still 'Waiting for Review.' Could anyone share their experience deploying and working on an iOS version of a VPN app? I’d really appreciate your insights!
1
0
136
Mar ’25
DNS duration 4294893875545978
When I use NSURLSessionTaskTransactionMetrics property domainLookupStartDate and domainLookupEndDate to calculate the duration of DNS, sometimes I get 4294893875545978 or -4294893875545978 return method like this [NSNumber numberWithLongLong:[taskMetrics.domainLookupEndDate timeIntervalSinceDate:taskMetrics.domainLookupStartDate?]*1000000000] The hexadecimal value of 4294893875545978 is 0xF3F3F3F3F3F3A. Is 4294893875545978 a special value?
3
0
82
Mar ’25
Retrieve Only the Certificates Presented by the Server
Is it possible using the network framework to retrieve the list of certificates presented by the host alone, and not the reconstructed chain assembled by the system? For example, in OpenSSL one can call SSL_get_peer_cert_chain which will return exactly this - a list of the certificates presented by the server. This is useful for when you may want to manually reconstruct the chain, or if the server is misconfigured (for example, is missing an intermediate cert). Is something like this possible with the network framework? If I connect to a host that I know only returns 1 certificate, the trust ref already has the reconstructed chain by the time my code is called: sec_protocol_options_set_verify_block(tlsOptions.securityProtocolOptions, { metadata, trustRef, verifyComplete in let trust = sec_trust_copy_ref(trustRef).takeRetainedValue() let numberOfCertificates = SecTrustGetCertificateCount(trust) // Returns 3 even though the server only sent 1
1
0
107
Mar ’25
Error Domain=NSURLErrorDomain Code=-1009
When I make a local network HTTP request, an error occurs. I'm sure I've granted wireless data permissions and local network permissions, and I'm connected to the correct Wi-Fi. This problem is intermittent, but once it happens, it will keep happening, and the only way to fix it is to restart the phone. Here is the error log: sessionTaskFailed(error: Error Domain=NSURLErrorDomain Code=-1009 "似乎已断开与互联网的连接。" UserInfo={_kCFStreamErrorCodeKey=50, NSUnderlyingError=0x30398a5b0 {Error Domain=kCFErrorDomainCFNetwork Code=-1009 "(null)" UserInfo={_NSURLErrorNWPathKey=unsatisfied (Local network prohibited), interface: en0[802.11], uses wifi, _kCFStreamErrorCodeKey=50, _kCFStreamErrorDomainKey=1}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask .<63>, _NSURLErrorRelatedURLSessionTaskErrorKey=( "LocalDataTask .<63>" ), NSLocalizedDescription=似乎已断开与互联网的连接。, NSErrorFailingURLStringKey=http://192.168.2.1:80/v1/parameters, NSErrorFailingURLKey=http://192.168.2.1:80/v1/parameters, _kCFStreamErrorDomainKey=1})
1
0
235
Mar ’25
DNS Resolving Issue with iCloud Private Relay and VPN Connection
Problem Description When using iCloud Private Relay (Limit IP address tracking) on macOS Sonoma, I'm experiencing a DNS resolving issue when simultaneously connected via OpenVPN. The system activates iCloud Private Relay instead of using the DNS servers provided by the VPN connection, resulting in incorrect IP address resolution. Specific issues: When connected to my company VPN, the system ignores DNS servers set by the VPN connection When attempting to ping internal servers in the corporate network, I receive public IP addresses instead of internal corporate IP addresses These public IP addresses are not accessible from outside as some services are disabled for external access Tools like nslookup and dig correctly resolve internal addresses, but ping and regular applications use incorrect (public) IP addresses Access to local servers in the corporate network/subnet is problematic Expected Behavior I need the system to: Use DNS servers provided by the VPN connection for accessing internal corporate resources when connected via VPN Simultaneously maintain iCloud Private Relay protection for regular internet browsing while connected to VPN Technical Details Based on available information, the problem is likely caused by "iCloud Private Relay" inserting an additional DNS resolver that isn't visible through the scutil tool. Regular applications use macOS internal API for DNS resolving, while tools like dig and nslookup work differently. According to Apple documentation, it should be possible to use custom DNS settings with iCloud Private Relay, but it doesn't seem to work properly with OpenVPN. Temporary Solutions I've Tried Some sources suggest: Disabling iCloud Private Relay (I don't want to lose privacy protection) Creating an /etc/resolver directory with configuration for specific domains Manually adding static routes for specific IP addresses None of these solutions provide the ideal combination of VPN DNS functionality and privacy protection. Request for Solution Please implement a solution that allows: Prioritizing DNS servers provided by VPN connection for internal domains Maintaining iCloud Private Relay protection for other communications Ensuring consistent behavior of all applications during DNS resolving Thank you for your help.
2
0
188
Mar ’25
What kind of situation is the NEProviderStopReasonInternalError enum value supposed to describe?
The newly introduced enum value NEProviderStopReasonInternalError (macOS 15.1) is not documented (assuming being documented means having at least a sentence describing the enum value). [Q] What kind of situation is the NEProviderStopReasonInternalError enum value supposed to describe? An internal error that requires to try to restart the provider? A fatal error that requires to reinstall macOS? A fatal error that requires to purchase a new Mac? Something less serious but with a human friendly description in the headers (I'm using Xcode 16.2) and online documentation.
2
0
87
Mar ’25
URLSession is broken in iOS 18.4 RC Simulator
I'm seeing fully reproducible issues with URLSession on iOS 18.4 RC Simulator running from Xcode 16.3 RC. URLSession seems to get into a broken state after a second app run. The following sample succeeds in fetching the JSON on first app run but when the app is closed and ran again it fails with one of these errors: Error: Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." Error: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." I'm wondering if this something related to my OS setup or is this due to internal URLSession changes in iOS 18.4. Already submitted as FB17006003. Sample code attached below: import SwiftUI @main struct NetworkIssue18_4App: App { var body: some Scene { WindowGroup { ContentView() } } } struct ContentView: View { @State private var message: String = "" var body: some View { VStack { Text(message) Button("Try Again") { Task { await fetch() } } } .task { await fetch() } } private func fetch() async { message = "Loading..." let url = URL(string: "https://poetrydb.org/title/Ozymandias/lines.json")! let session = URLSession.shared do { let response = try await session.data(from: url) print("Response: \(response)") message = "Success, data length: \(response.0.count)" } catch { print("Error: \(error)") message = "Error: \(error.localizedDescription)" } } }
55
41
24k
Mar ’25
No Local Network prompt for ios18
We are developers of an app, we found that there's no LN prompt for users to install the app for the 1st time on ios18. We used the following method to prompt the "allow/not allow" alert: // Attempts to trigger the local network privacy alert. /// /// This builds a list of link-local IPv6 addresses and then creates a connected /// UDP socket to each in turn. Connecting a UDP socket triggers the local /// network alert without actually sending any traffic. /// /// This is a ‘best effort’ approach, and it handles errors by ignoring them. /// There’s no guarantee that it’ll actually trigger the alert (FB8711182). func triggerLocalNetworkPrivacyAlert() { let addresses = selectedLinkLocalIPv6Addresses() for address in addresses { let sock6 = socket(AF_INET6, SOCK_DGRAM, 0) guard sock6 >= 0 else { return } defer { close(sock6) } withUnsafePointer(to: address) { sa6 in sa6.withMemoryRebound(to: sockaddr.self, capacity: 1) { sa in _ = connect(sock6, sa, socklen_t(sa.pointee.sa_len)) >= 0 } } } }
1
0
110
Mar ’25
Custom IPSec IKEv2 with Packet Tunnel Provider Extension on iOS
We’re looking to implement a custom IPSec IKEv2 VPN using the Packet Tunnel Provider network extension on iOS because we need to add extra information to EAP, which the built-in IKEv2 VPN configuration does not support. Is it possible to handle the full IKEv2 negotiation and IPSec tunneling within the Packet Tunnel Provider extension? Or are there limitations that would prevent implementing a full IKEv2 stack this way? Any insights or alternative approaches would be appreciated. Thanks!
1
0
105
Mar ’25
NSProcessInfo hostName holds the process for 30+ seconds
We have used ::gethostname to retrieve hostname in our tunnel provider extension and found it returns "localhost" on iOS 17+. So we changed to use [[NSProcessInfo processInfo] hostName]. However it often caused 30+ delay in the extension process on a few devices and always returns "localhost". The sysdiagnose shows a lot of DNS query logs as below: default mDNSResponder 2025-03-19 17:15:12.453769 +0800 75281: 0x11ad501 [R80937] DNSServiceCreateConnection START PID[79767](ACExtension) default mDNSResponder 2025-03-19 17:15:12.453892 +0800 75281: 0x11ad501 [R80938] DNSServiceQueryRecord START -- qname: <mask.hash: 'fNnSAdyuhKXqCny8+neXvw=='>, qtype: PTR, flags: 0x15000, interface index: -1, client pid: 79767 (ACExtension), name hash: 84de01e1 default mDNSResponder 2025-03-19 17:15:12.458395 +0800 75281: 0x11ad501 [R80939] DNSServiceQueryRecord START -- qname: <mask.hash: '2X6qN/YT0yh2psKwrGWokg=='>, qtype: PTR, flags: 0x15000, interface index: 0, client pid: 79767 (ACExtension), name hash: f25c923e default mDNSResponder 2025-03-19 17:15:12.462924 +0800 75281: 0x11ad501 [R80940] DNSServiceQueryRecord START -- qname: <mask.hash: 'peyRWEblLKbNvcOXPjSeMQ=='>, qtype: PTR, flags: 0x15000, interface index: 0, client pid: 79767 (ACExtension), name hash: 83323cc4
1
0
131
Mar ’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 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!
1
0
83
Mar ’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
157
Mar ’25
Sequoia 'local network' permission failure from launch agent
I'm trying to invoke a 3rd party command line tool from a launch agent to connect to a server on my LAN. It seems impossible. I have a little shell script that does what I need, and it works fine invoked in Terminal.app. The first time I run it that way I get permission prompts and I agree to them all. Subsequent invocations work. Now I put a launch agent in ~/Library/Launch Agents. It does nothing more than invoke my shell script at some specific time daily. launchd launches it, but it fails to access the LAN, with a 'no route to host' error message. The command line tool I'm trying to use is not a macOS-provided one, but one from MacPorts/HomeBrew (I tried both). It doesn't even matter which tool I'm using, I tried a very simple case of just using nc/netcat. If I use the macOS-provided nc, then I can access my LAN. If I install nc from MacPorts /HomeBrew, that nc cannot access my LAN. This I've reproed on a literally brand new Mac, then updated to newest Sequoia (15.3.2), then done all I've described above. I've ruled out DNS by working with raw IP addresses. I've disabled gatekeeper with sudo spctl --master-disable. I've tried using cron instead of launch agents, same results. I've tried codesigning with codesign -dvvv /opt/homebrew/bin/nc, no help. I've read TN3179 Understanding local network privacy. In summary: Terminal.app -> script -> macOS/brew nc -> internet/LAN = works launchagent -> script -> macOS nc -> internet = works launchagent -> script -> macOS nc -> LAN = works launchagent -> script -> brew nc -> internet = works launchagent -> script -> brew nc -> LAN = fails How can I make that last case work?
14
0
464
Mar ’25
Creating another nw_endpoint_t/nw_connection_t from an existing one, to change port number
I'm able to discover a service with Bonjour, which gets me an nw_browse_result_t from which I can get an nw_endpoint_t and then an nw_connection_t. That's all fine. But this particular service runs on 3 ports. The port numbers of the other 2 ports are in the txt record (but they are well-known and stable anyway). How can I create 2 more nw_connection_t to the same host/IP but on a different port? I already have this working with NSNetService, but am trying to update to Network.framework. I've found nw_endpoint_get_address() but the docs say it returns null "if the endpoint is not of type nw_endpoint_type_address" and indeed nw_browse_result_t gives me an nw_endpoint_type_bonjour_service.
1
0
84
Mar ’25
On Host Names
For important background information, read Extra-ordinary Networking before reading this. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" On Host Names I commonly see questions like How do I get the device’s host name? This question doesn’t make sense without more context. Apple systems have a variety of things that you might consider to be the host name: The user-assigned device name — This is a user-visible value, for example, Guy Smiley. People set this in Settings > General > About > Name. The local host name — This is a DNS name used by Bonjour, for example, guy-smiley.local. By default this is algorithmically derived from the user-assigned device name. On macOS, people can override this in Settings > General > Sharing > Local hostname. The reverse DNS name associated with the various IP addresses assigned to the device’s various network interfaces That last one is pretty much useless. You can’t get a single host name because there isn’t a single IP address. For more on that, see Don’t Try to Get the Device’s IP Address. The other two have well-defined answers, although those answers vary by platform. I’ll talk more about that below. Before getting to that, however, let’s look at the big picture. Big Picture The use cases for the user-assigned device name are pretty clear. I rarely see folks confused about that. Another use case for this stuff is that you’ve started a server and you want to tell the user how to connect to it. I discuss this in detail in Showing Connection Information in an iOS Server. However, most folks who run into problems like this do so because they’re suffering from one of the following misconceptions: The device has a DNS name. Its DNS name is unique. Its DNS name doesn’t change. Its DNS name is in some way useful for networking. Some of these may be true in some specific circumstances, but none of them are true in all circumstances. These issues are not unique to Apple platforms — if you look at the Posix spec for gethostname, it says nothing about DNS! — but folks tend to notice these problems more on Apple platforms because Apple devices are often deployed to highly dynamic network environments. So, before you start using the APIs discussed in this post, think carefully about your assumptions. And if you actually do want to work with DNS, there are two cases to consider: If you’re looking for the local host name, use the APIs discussed above. In other cases, it’s likely that the APIs in this post will not be helpful and you’d be better off focusing on DNS APIs [1]. [1] The API I recommend for this is DNS-SD. See the DNS section in TN3151 Choosing the right networking API. macOS To get the user-assigned device name, call the SCDynamicStoreCopyComputerName(_:_:) function. For example: let userAssignedDeviceName = SCDynamicStoreCopyComputerName(nil, nil) as String? To get the local host name, call the SCDynamicStoreCopyLocalHostName(_:) function. For example: let localHostName = SCDynamicStoreCopyLocalHostName(nil) as String? IMPORTANT This returns just the name label. To form a local host name, append .local.. Both routines return an optional result; code defensively! If you’re displaying these values to the user, use the System Configuration framework dynamic store notification mechanism to keep your UI up to date. iOS and Friends On iOS, iPadOS, tvOS, and visionOS, get the user-assigned device name from the name property on UIDevice. IMPORTANT Access to this is now restricted. For more on that, see the documentation for the com.apple.developer.device-information.user-assigned-device-name entitlement. There is no direct mechanism to get the local host name. Other APIs There are a wide variety of other APIs that purport to return the host name. These include: gethostname The name property on NSHost [1] The hostName property on NSProcessInfo (ProcessInfo in Swift) These are problematic for a number of reasons: They have a complex implementation that makes it hard to predict what value you’ll get back. They might end up trying to infer the host name from the network environment. The existing behaviour is hard to change due to compatibility concerns. Some of them are marked as to-be-deprecated. IMPORTANT The second issue is particularly problematic, because it involves synchronous DNS requests [2]. That’s slow in general. Worse yet, if the network environment is restricted in some way, these calls can be very slow, taking about 30 seconds to time out. Given these problems, it’s generally best to avoid calling these routines at all. [1] It also has a names property, which is a little closer to reality but still not particularly useful. [2] Actually, that’s not true for gethostname. Rather, that call just returns whatever was last set by sethostname. This is always fast. The System Configuration framework infrastructure calls sethostname to update the host name as the system state changes.
0
0
236
Mar ’25