Hi,
I'm troubleshooting an iOS network connectivity issue when my app is running 'in' a per-app VPN and would like some clarification about the ordering of some of the logging generated after installing various debugging profiles on the device (VPN (Network Extension), Network Diagnostics, mDNSResponder).
Context
The connectivity issue is between two vendors my app is involved with. One supplies an app proxy provider extension to provide per-app VPN capability for my app. The other vendor provides an SDK framework that's attempting to make network connections which normally work when the VPN is not involved. We have confirmed with the VPN vendor that it is not a configuration (whitelisting, etc) type issue.
I am trying to understand from the logs what component caused/initiated the network connection termination. Was it the kernel, was it the App Proxy Provider Network Extension code or was it the app (SDK framework) code ?
Log entries
I've attached a short log file and number the lines for reference, and have redacted a few commercially sensitive parts.
NetworkLogExcerpt.txt
Questions
Can this log help determine who caused the network connection failure, and if not, is there any more instrumentation I could enable that might help?
Do the log entries (and their timestamps) reflect the actual order/timing of events reported on, or is there some jumbling occurring due to my app, the kernel and iOSAppProxyProvider running in different processes/threads?
After the app initiates the network connection (line 1), it appears that the kernel flow diversion code in netinet/flow_divert.c establishes the flow and closes it (lines 2 - 6) before iOSAppProxyProvider even starts to establish the flow (lines 7 - 10).
Then the app somehow seems to detects a network error (line 8), before the iOSAppProxyProvider has even matched the VPN extension (line 12) to it and then finally the iOSAppProxyProvider closes the flow (lines 13-17).
I'd have expected an interleaving of kernel and iOSAppProxyProvider log entries, with the app's own logging just occurring at the start and end, bracketing the whole interaction...
I am new to this area of iOS, so apologies if I am missing some important foundational concepts about how these components all work together.
Thanks in advance,
Rob
Networking
RSS for tagExplore the networking protocols and technologies used by the device to connect to Wi-Fi networks, Bluetooth devices, and cellular data services.
Post
Replies
Boosts
Views
Activity
Let's say you want to stop a server.
https://developer.apple.com/forums/thread/75997
From searching apparently, there's an automatic cooldown. Don't know whether it's true or not.
That thread mentions socket variables, that I don't believe can be used with the NW stuff.
NWListener "cancel" doesn't seem to stop a server? Eitherways, doing that and trying to use .start and something like
self.listener = try NWListener(using: self.cfg_nwParameters, on: self.port)
self.listener?.start(queue: .main)
this will trigger Address already in use if you "stopped" a server, because apparently you can't stop a server with NWListener. Because the socket isn't actually closing apparently.
Our app is developed for iOS, but some users also run it on macOS (as an iOS app via Apple Silicon). The app requires local network permission, which works perfectly on iOS. Previously, the connection also worked fine on macOS, but since the recent macOS update, the app can no longer connect to our device.
Additionally, our app on macOS doesn't prompt for local network permission at all, whereas it does on iOS. Is this a known issue with iOS apps running on macOS? Has anyone else experienced this problem, or is there a workaround?
Any help would be appreciated!
Hello,
I'm working with the Network framework in Swift and have encountered an issue when attempting to create multiple NWListener instances on the same port. I am specifically trying to set the allowLocalEndpointReuse property on the NWParameters used for both listeners, but it seems that even with this property set, the second listener fails to start.
Here’s a simplified version of my implementation:
import Foundation
import Network
class UDPServer {
private var listener1: NWListener?
private var listener2: NWListener?
private let port: NWEndpoint.Port
init(port: UInt16) {
self.port = NWEndpoint.Port(rawValue: port) ?? NWEndpoint.Port(45000)
startListeners()
}
private func startListeners() {
let udpOptions = NWProtocolUDP.Options()
let params = NWParameters(udp: udpOptions)
params.allowLocalEndpointReuse = true
// Create first listener
do {
listener1 = try NWListener(using: params, on: port)
listener1?.start(queue: .global())
} catch {
print("Failed to create Listener 1: \(error)")
}
// Create second listener
do {
listener2 = try NWListener(using: params, on: port)
listener2?.start(queue: .global())
} catch {
print("Failed to create Listener 2: \(error)")
}
}
}
// Usage example
let udpServer = UDPServer(port: 45000)
RunLoop.main.run()
Observations:
I expect both listeners to operate without issues since I set allowLocalEndpointReuse to true.
However, when I attempt to start the second listener on the same port, it fails with an error.
output
nw_path_evaluator_evaluate NECP_CLIENT_ACTION_ADD error [48: Address already in use]
nw_path_create_evaluator_for_listener nw_path_evaluator_evaluate failed
nw_listener_start_on_queue [L2] nw_path_create_evaluator_for_listener failed
Listener 1 ready on port 45000
Listener 2 failed: POSIXErrorCode(rawValue: 48): Address already in use
Listener 2 cancelled
Questions:
Is there a limitation in the Network framework regarding multiple listeners on the same port even with allowLocalEndpointReuse?
Should I be using separate NWParameters for each listener, or is it acceptable to reuse them?
Even when trying to initialize NWParameters with NWProtocolUDP.Options, it doesn't seem to change anything. What steps should I take to modify these properties effectively?
If I wanted to set the noDelay option for TCP, how would I do that? Even when initializing NWParameters with init(.tls: , .tcp:), it doesn't seem to have any effect.
Any insights or recommendations would be greatly appreciated!
Thank you!
Hi Team,
The Messages app is not working in the latest macOS Sequoia 15.0.1. We are unable to send messages or sync them when the VPN/TransparentAppProxy is connected.
It was working fine in macOS 15.0 and earlier.
A few users have reported the issue here: https://discussions.apple.com/thread/255802764?sortBy=rank
I have implemented SSL pinning by following this article https://developer.apple.com/news/?id=g9ejcf8y , however pen testing team was able to bypass SSL pinning using Objection & Frida tools.
I am using URLSession for API calls. I used Xcode 16. My app's minimum iOS deployment version is 16 onwards.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSPinnedDomains</key>
<dict>
<key>*.mydomain.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSPinnedCAIdentities</key>
<array>
<dict>
<key>SPKI-SHA256-BASE64</key>
<string>my SHA256 key</string>
</dict>
</array>
</dict>
</dict>
</dict>
Could anyone suggest how to mitigate this bypass mechanism?
Hello,
As a developer, I'm experiencing a problem with WebSocket connections since upgrading to MacOS 15.0 Sequoia.
When using a JSON RPC API from my workstation using tools such as Postman and/or Docker, I encounter the following problem: At the start of communications, messages received on the WS channel are fine. But after a while (indefinite) the messages become corrupted, truncated or jumbled.
For debugging purposes, I used the WireShark utility to confirm that the problem was not with the server itself. I was thus able to confirm that incoming WebSockets messages are not corrupted, whereas they are when received by Postman and/or Docker.
To confirm my hypothesis that the problem appeared with the latest version of MacOS, we tested on 6 different workstations.
3 MacBook Pro 13” running MacOS 14.6
3 MacBook Pro 13” running MacOS 15.0
The results were clear: the 3 MacOS 14.6 workstations never encountered the problem of corrupted data on the WebSocket channel, whereas the 3 MacOS 15.0 workstations did.
Should you require any further information, please do not hesitate to contact me.
Yours faithfully
Paul BESRET, R&D Engineer.
Hello, I have a question about sending data in QUIC DATAGRAM.
Regarding sending data in QUIC DATAGRAM, when I create a NWConnectionGroup and then use the send method of that group to send data in sequence, quite often I get an Optional(POSIXErrorCode(rawValue: 89): Operation canceled) error.
A little Thread.sleep between sends improves the situation somewhat, but the above error still occurs.
Also, since I want to send the frame data of the video in this communication process, adding a wait will drastically reduce performance and make the speed impractical.
However, if send is executed continuously without adding weights, the above error will occur 80% of the time or more.
Is it necessary to send while monitoring some status when sending?
In communication using QUIC Stream, when connecting to the server with NWConnection and sending with its send method, the above error does not occur even if send is executed without wait, and data can be transferred with good performance.
I am trying to use DATAGRAM communication to further increase throughput, but I am not having much success, and there is not much information on DATAGRAM communication.
Thank you in advance for your help.
While I was starting App Proxy without errors from my application, the AppProxyProvider could not receive new flows in the function handleNewFlow. I just encounter this issue on macOS 15 beta (24A5309e). Everything is fine on the earlier macOS versions.
I am creating a VoIP application. The VoIP application needs to send and receive RTP packets at 20 ms intervals.
The application calls sendto() of the Socket API at 20 ms intervals, but the iPhone buffers the send data inside iOS and then sends RTP packets in batches at 1 second intervals.
(I captured the sned packets of iPhone with rvctl and confirmed this. please reffer "Sending at 1 second intervals.png" for detail)
Similarly, other devices send RTP packets to the iPhone at 20 millisecond intervals,
but the iPhone only receives them at 1 second intervals.
(please reffer "Receiving at 1 second intervals.png" for detail)
Why is this?
If the cause of the delay is in the Wi-Fi protocol and the cause can be found from sysdiagnose,
please tell me the search key for sysdiagnose that shows the cause of the delay and the meaning of the corresponding log.
I uploaded sysdiagnose and result of lan capture to below.
[sysdiagnose and lan capture]
https://drive.google.com/file/d/149OPmePAF4hnZj6NeSnKc5NizfitPQDS/view?usp=sharing
And, the start and end times, packet number in the lan capture of the call shown in the png example are below
Start time; 13:57:22.349608/packet number; 948
End time; 13:57:37.482874/packet number; 2583
In the development environment, if I disable and then enable the Network Connection permission to my app in the Setting on my device, my app is denied the network connection permission permanently. The error message is The Internet connection appears to be offline.
Please advise me what to do.
NEAppProxyProvider MacOS Sequoia 15 never called “handleNewFlow” although it works well in the macOS Ventura/ Sonoma
System extensions on iOS have very low limits on allowed memory. For instance the DNS proxy extensions seem to be limited to 15MB. When I try to monitor the extension with instruments it quickly runs out of memory, most likely due to the way instruments tracks memory usage.
I did find that there are two entitlements related to memory usage but it is unclear if these would work for extensions or only for applications.
What are the best techniques for debugging extensions that run out of memory?
Is there a way to temporarily increase the limit while debugging?
I need to connect to a JMS that publishes data that I need to collect.
I am trying one solution: RabbitMQ with the JMS plugin. I succeeded to install RabbitMQ and send messages from one process to another. However, I need to consume a JMS that an external party publishes.
Can anybody tell me how I should configure the Host, Port, Username, Password and Queue name for RabbitMQ/JMS so that I can consume (or subscribe to) that JMS?
Or does anybody know another way to consume (or subscribe to) a JMS from Swift?
I have no idea which of the provided Tags I should select.
Thanks!
Wouter
Hello. Wanted to ask about the right way, or the intended way to leverage NWConnectionGroup for a QUIC based streaming solution.
The use case is, we are making a request from the client in order to play a movie, and we want to send as much video frames as possible (and as fast as possible) from the streaming server, which also uses the Network framework.
Our understanding is, NWConnectionGroup will open a QUIC tunnel between both parties so we can multiplex different streams to the client and we are already doing that.
We see a throughput of approx. 20-35MB/s (client device is an iPad and server is an M2 macbook pro running a server app) and we would like to understand if we can improve these results way more.
For example:
1.- Is it a good practice to create a second tunnel (NWConnectionGroup), or is not needed here?. We tried that, but the second one is also coming with id 0 on the metadata object, just as the first group we instantiated, not sure why this is the case.
2.- We are using a pool of several NWConnection (initialized with the group object) already instantiated, that way we send a video buffer in chunks as a stream on each connection. We use one connection for a buffer and when we need to send another buffer we use a different NWConnection pulled from the pool.
We maybe just want a confirmation/validation of what we are doing, or to see if we are missing something on our implementation...
Thanks in advance.
I am developing an iOS application based on Objective-C, and I have encountered a requirement where I need to determine if the password for the currently connected Wi-Fi is empty. If it is empty, the user is allowed to proceed to the next step. If it is not empty, they must enter a password. This will be used in the next process, which is the network configuration of a physical device.
After researching documentation, I found two possible approaches to determine if the Wi-Fi password is empty. The first approach is to directly check the encryption type of the current Wi-Fi. If there is no encryption type, the Wi-Fi password is empty. The second approach is to use Apple's NEHotspotConfiguration class to attempt connecting to the Wi-Fi and determine if the password is empty. However, both approaches have encountered issues.
For the first approach, there seems to be no public API available to directly retrieve the Wi-Fi encryption type.
For the second approach, when using NEHotspotConfiguration to connect, I first get the Wi-Fi's SSID and then attempt to connect with an empty password. I am using [NEHotspotConfiguration alloc] initWithSSID:ssid] to create a configuration, and then I call [NEHotspotConfigurationManager sharedManager] applyConfiguration: to connect. However, regardless of whether the Wi-Fi is actually encrypted or unencrypted, no error is returned. The code is as follows:
NSString *ssid = [NetInterface getCurrent_SSID]; // The Wi-Fi SSID that needs to be checked
NEHotspotConfiguration *configuration = [[NEHotspotConfiguration alloc] initWithSSID:ssid];
configuration.joinOnce = YES;
// Remove previous configuration (optional)
[[NEHotspotConfigurationManager sharedManager] removeConfigurationForSSID:ssid];
self.isWiFiEmptyOperateState = 1;
// Attempt to apply the new configuration
[[NEHotspotConfigurationManager sharedManager] applyConfiguration:configuration completionHandler:^(NSError * _Nullable error) {
self.isWiFiEmptyOperateState = 2;
if (error) {
if (error.code == NEHotspotConfigurationErrorInvalid) {
NSLog(@"Wi-Fi %@ is encrypted, a password is required", ssid);
} else if (error.code == NEHotspotConfigurationErrorUserDenied) {
NSLog(@"User denied the Wi-Fi configuration");
} else {
NSLog(@"Other error: %@", error.localizedDescription);
}
} else {
NSLog(@"Successfully connected to Wi-Fi %@, this network might be open", ssid);
}
}];
In the code above, it always ends up logging "Successfully connected to Wi-Fi." Is there any other approach that can fulfill my functional requirement? I noticed that some apps on the App Store have implemented this functionality, but all my attempts so far have failed.
macOS 15 has added a new "Local Network" permission under Security & Privacy.
I had a bug in my app that led to a crash when the user denied this permission. Now I've fixed it and would like to verify that it all works fine.
The problem is: I need to remove my app from the settings so that macOS will show the prompt again (e.g. to verify that my custom message appears correctly).
Usually, sudo tccutil reset All would do the trick. But not for this permission! The apps do not get cleared with this command.
So, there's two issues:
tccutil should remove it but doesn't.
How can I remove this settings?
Update
I had a look at the "TCC.db" (see https://www.rainforestqa.com/blog/macos-tcc-db-deep-dive), and it seems to me that the Local Network permission isn't even managed by the TCC system, as it doesn't appear in it. This is odd.
When our app makes an API call to our backend service, we want the app to provide a client certificate in the call.
What API and mechanism we can use so that our app (iOS app store, and Mac with Developer ID) to read a client certificate present in the Keychain.
Please note that the client certificate will be put in the Keychain by an external MDM process. Not sure if an iOS or Mac app can read client certificates from Keychain which they have not put it there in the first place.
Hello,
I'm wondering if a NEDNSProxyProvider should supports TCP DNS query or not ?
DNS UDP datagrams are limited to 512 bytes and sometimes, a DNS resolver should fallback to TCP to handle large queries.
But I don't see anything about supporting TCP flow in the DNS Proxy provider reference.
Is there a guarantee that it will only receive UDP flow ? How is the system handling large DNS queries in that case ?
Hello,
I am planning to create an app that can transfer files to hardware devices via WiFi. With devices like GoPro, I believe the typical setup involves the GoPro creating a WiFi hotspot to which the iOS app connects, allowing file transfers. But this setup establishes a 1:1 connection between the app and the hardware.
To support multiple hardware devices simultaneously, I am considering reversing this setup: the iOS device would create a personal hotspot, and the hardware devices would connect to it. However, I have concerns about this approach:
Reliability: I have read that the personal hotspot feature on iOS devices can be unreliable, especially with non-Apple devices, which tend to disconnect frequently.
Manual Setup: There is no API to programmatically create the personal hotspot, so users would have to enable it manually in the Settings.
I can use isIdleTimerDisabled to prevent the iOS screen from going to sleep, which might help with disconnection issues. Aside from this, are there other things I can do to ensure a stable connection?
Given my limited experience with hardware connections, I am uncertain if having the iOS device act as the WiFi access point is a good design. Any advice or alternative solutions would be greatly appreciated.
Thank you in advance!