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
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.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I am trying to connect an iPhone 16 (iOS 18.3) to a Wi-Fi device with the SSID "DIRECT-DR_6930_KP201128", but every time, without being able to enter the Wi-Fi password, the message "Unable to join the network 'DIRECT-DR_6930_KP201128'" is displayed. Below are the system logs from the connection failure. Could you please tell me the cause of the connection failure?
By the way, an iPhone SE 2nd (iOS 18.2.1) can connect to the same Wi-Fi device without any issues.
System Logs:
・Jan 31 19:18:14 900-iPhone-16-docomo Preferences(WiFiKit)[351] : {ASSOC-} association finished for DIRECT-DR_6930_KP201128 - success 0
・Jan 31 19:18:14 900-iPhone-16-docomo runningboardd(RunningBoard)[33] : Assertion 33-351-4412 (target:[app<com.apple.Preferences(DE1AB487-615D-473C-A8D6-EAEF07337B18)>:351]) will be created as inactive as start-time-defining assertions exist
・Jan 31 19:18:14 900-iPhone-16-docomo Preferences(WiFiKit)[351] : association failure: (error Error Domain=com.apple.wifikit.error Code=12 "Unknown Error" UserInfo={NSDebugDescription=Unknown Error, NSUnderlyingError=0x303307660 {Error Domain=com.apple.corewifi.error.wifid Code=-3938 "(null)"}})
・Jan 31 19:18:14 900-iPhone-16-docomo Preferences(WiFiKit)[351] : dismissing credentials view controller for DIRECT-DR_6930_KP201128
We found there is a significant crash reports (most of them are from iOS 17, the rest are iOS 16 and 15) comes from network loader from CFNetwork. Apparently it seems there are two types of crashes if we checked from the stack trace, the one we found from both Xcode organizer and 3rd party crash reporter is referring to URLConnectionLoader::loadWithWhatToDo and the other one from our 3rd party crash reporter (didn’t found the report from Xcode organizer) referring to
_CFURLResponseCreateFromArchiveList (this one only happened on iOS 17.5 and later devices). It seems that they are both kinda similar which might point to the same root cause.
From what I’ve seen, we never touch the lower level API directly, we usually use the URLSession to manage our API request. The crashed stack trace also didn’t give any indication about which of our app code that triggered the crash, it only shows calls to Apple’s internal SDKs so we are unsure how to approach this issue meanwhile the crash event already reached 800+ in the last 30 days. Unfortunately, we cannot reproduce the issue as the stack trace itself seems unclear to us.
I have submitted a report through feedback assistant with number: FB14679252.
Would appreciate if anyone can give any advice on what we can do to avoid this in the future and probably any hint on why it could happened.
Hereby I attached the crash reports that we found each from Xcode crash report and our 3rd party crash reporter (the report said it crashed on com.apple.CFNetwork.LoaderQ) so you could get a glimpse of the similarity.
Xcode crash report
xcode crash report.crash
3rd party crash report
3rd party crash report.txt
Description :
Our app helps users connect to Wi-Fi hotspots. We are trying to adapt our code to iOS 26 Hotspot Authentication and Hotspot Evaluation application extensions.
When filtering hotspots in the filterScanList callback, we need to fetch support information from a remote server to determine which hotspots are supported. However, attempts to use URLSession or NWTCPConnection in the extension always fail.
When accessing a URL (e.g., https://www.example.com), the network log shows:
Error Domain=NSURLErrorDomain Code=-1003 "A server with the specified hostname could not be found."
When accessing a raw IP address, the log shows:
[1: Operation not permitted]
Interestingly, NWPathMonitor shows the network path as satisfied, indicating that the network is reachable.
Question:
Are there any missing permissions or misconfigurations on our side, or are we using the wrong approach? Is there an official recommended way to perform network requests from an NEHotspotEvaluationProvider extension?
This problem doesn’t appear to relate to the app as everything worked when using http (although an https setup issue may still be the problem). The problem appears to relate to the SSL server certificate on the Ubuntu server and the fact that apple does not accept that it is secure. However I have no problem with the equivalent Android app or web browser connections to the same rest API web services. There are numerous posts on these problems on Apple and other Forums, but none have helped me successfully address the issue.
I ran an SSL server test on https://www.ssllabs.com/ssltest/ which gives ratings for SSL sites. The test gave an A rating although a number of minor issues were shown that may be crucial to the iOS failure. Some Sectigo certificates said self signed, which I couldn't understand.
Error message from XCode log attached
2025-09-10 10:28:01.725091+0100 locateandclock[2291:1585213] ATS failed system trust
2025-09-10 10:28:01.725192+0100 locateandclock[2291:1585213] Connection 1: system TLS Trust evaluation failed(-9802)
2025-09-10 10:28:01.725291+0100 locateandclock[2291:1585213] Connection 1: TLS Trust encountered error 3:-9802
2025-09-10 10:28:01.725352+0100 locateandclock[2291:1585213] Connection 1: encountered error(3:-9802)
2025-09-10 10:28:01.726727+0100 locateandclock[2291:1585213] Task <4E41098F-6B71-4FB8-8753-78DD32961812>.<1> HTTP load failed, 0/0 bytes (error code: -1200 [3:-9802])
2025-09-10 10:28:01.736504+0100 locateandclock[2291:1585213] Task <4E41098F-6B71-4FB8-8753-78DD32961812>.<1> finished with error [-1200] Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, NSErrorPeerCertificateChainKey=(
"<cert(0x10681be00) s: *.xxxxxxxxxxx.co.uk i: Sectigo Public Server Authentication CA DV R36>",
"<cert(0x10681c800) s: Sectigo Public Server Authentication CA DV R36 i: Sectigo Public Server Authentication Root R46>",
"<cert(0x10681d200) s: Sectigo Public Server Authentication Root R46 i: Sectigo Public Server Authentication Root R46>"
), NSErrorClientCertificateStateKey=0, NSErrorFailingURLKey=https://xxxxxxxxxxxx.co.uk/insertclocking, NSErrorFailingURLStringKey=https://xxxxxxxxxxxx.co.uk/insertclocking, NSUnderlyingError=0x282361650 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x281cf4460>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=(
"<cert(0x10681be00) s: *.xxxxxxxxxxxxxco.uk i: Sectigo Public Server Authentication CA DV R36>",
"<cert(0x10681c800) s: Sectigo Public Server Authentication CA DV R36 i: Sectigo Public Server Authentication Root R46>",
"<cert(0x10681d200) s: Sectigo Public Server Authentication Root R46 i: Sectigo Public Server Authentication Root R46>"
)}}, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <4E41098F-6B71-4FB8-8753-78DD32961812>.<1>"
), _kCFStreamErrorCodeKey=-9802, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <4E41098F-6B71-4FB8-8753-78DD32961812>.<1>, NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x281cf4460>, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made.}
Topic:
App & System Services
SubTopic:
Networking
Hi,
I am trying to update an old prototype I made for tvOS using DNSServiceBrowse(). The target was tvOS 17.
My old build from September 2023 still works fine: It can discover computers on the same local network as the Apple TV (simulator).
However, now that I am using Xcode 16, the DNSServiceBrowse() callback (of type DNSServiceBrowseReply) receives the error code: -65570.
The call to DNSServiceBrowse() itself returns no error, neither does the following call to DNSServiceProcessResult() — which actually triggers the call of the callback.
I found nowhere in the Internet any list of possible error codes received by the callback, so I have no idea what it means.
So, my first question is: What does this error code mean? (And is there any list of the possible errors somewehere, with their meaning?)
Since it was a prototype, I have no provisioning profile defined for it. Could that be related to the issue? Since I will make a real app out that prototype (targeting tvOS 18), I will have to define a provisioning profile for it.
Would a provisioning profile for the app solve the issue?
If yes, are there any requirements for that profile that I should take into account to solve the issue?
Thank you in advance for any help,
Marc
Hi,
DNS resolution using libresolv (res_nquery) fails in 15.4 when connected to VPN. The same is working fine for 15.3 and lower and this happens for all the domains. The method returns -1 and res->res_h_errno is set to 2.
In wireshark we can see that the DNS request is sent and server also returns the response successfully.
The same works fine if we use TCP instead of UDP by setting the following option
res->options |= RES_USEVC;
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?
Recently, my application was having trouble sending udp messages after it was reinstalled. The cause of the problem was initially that I did not grant local network permissions when I reinstalled, I was aware of the problem, so udp worked fine after I granted permissions. However, the next time I repeat the previous operation, I also do not grant local network permissions, and then turn it back on in the Settings, and udp does not work properly (no messages can be sent, the system version and code have not changed).
Fortunately, udp worked after rebooting the phone, and more importantly, I was able to repeat the problem many times.
So I want to know if the process between when I re-uninstall the app and deny local network permissions, and when I turn it back on in Settings, is that permissions have been granted normally, and not fake, and not required a reboot to reset something for udp to take effect.
I'm not sure if it's the system, or if it's a similar situation as described here, hopefully that will help me find out
iOS 18.4 introduced some requirements on the Key Usage of 802.1x server certificates, as described here. https://support.apple.com/en-us/121158
When using TLS_ECDHE_RSA or TLS_DHE_RSA cipher suites, 802.1X server certificates containing a Key Usage extension must have Digital Signature key usage set.
When using the TLS_RSA cipher suite, 802.1X server certificates containing a Key Usage extension must have Key Encipherment key usage set.
It reads like the change is supposed to affect 802.1x only. However, we have found out that the new restrictions are actually imposed on all TLS connections using the Network framework, including in Safari.
Unlike other certificate errors which can be either ignored by users (as in Safari) or by code (via sec_protocol_options_set_verify_block), these new ones can't. Even if passing completion(true) in the TLS verification block, the connection still ends up in waiting state with error -9830: illegal parameter.
I understand that these requirements are valid ones but as a generic TLS library I also expect that Network framework could at least allow overriding the behavior. The current treatment is not consistent with those on other certificate errors.
Since I can't upload certificates, here is how to reproduce a certificate that fails.
Create a OpenSSL config file test.cnf
[ req ]
default_bits = 2048
distinguished_name = dn
x509_extensions = v3_ca
prompt = no
[ dn ]
CN = example.com
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = CA:TRUE
keyUsage = critical, keyCertSign, cRLSign
Generate certificate and private key
openssl req -x509 -new -nodes -keyout key.pem -out cert.pem -days 365 -config test.cnf
And here is the client code to test.
// Target server and port
let host = NWEndpoint.Host("example.com")
let port = NWEndpoint.Port("443")!
// Configure insecure TLS options
let tlsOptions = NWProtocolTLS.Options()
sec_protocol_options_set_verify_block(tlsOptions.securityProtocolOptions, { _, _, completion in
// Always trust
completion(true)
}, DispatchQueue.global())
let params = NWParameters(tls: tlsOptions)
let connection = NWConnection(host: .init(host), port: .init(rawValue: port)!, using: params)
connection.stateUpdateHandler = { newState in
switch newState {
case .ready:
print("TLS connection established")
case .failed(let error):
print("Connection failed: \(error)")
case .cancelled:
print("Connection canceled")
case .preparing:
print("Connection preparing")
case .waiting(let error):
print("Connection waiting: \(error)")
case .setup:
print("Connection setup")
default:
break
}
}
connection.start(queue: .global())
Output
Connection preparing
Connection waiting: -9830: illegal parameter
Previously reported as FB17099740
I have been battling this intermittent error for some time. It is generally random and has been difficult to reproduce until yesterday when I stumbled across a way to reproduce it each time. I can cause the code to throw this error:
Task <70E3909F-8C30-4F34-A8B0-4AF3B41DD81B>.<1> finished with error [-1001] Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={_kCFStreamErrorCodeKey=-2103, _NSURLErrorFailingURLSessionTaskErrorKey=BackgroundDownloadTask <70E3909F-8C30-4F34-A8B0-4AF3B41DD81B>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"BackgroundDownloadTask <70E3909F-8C30-4F34-A8B0-4AF3B41DD81B>.<1>",
"LocalDownloadTask <70E3909F-8C30-4F34-A8B0-4AF3B41DD81B>.<1>"
), NSLocalizedDescription=The request timed out., _kCFStreamErrorDomainKey=4, NSErrorFailingURLStringKey=https://redacted*, NSErrorFailingURLKey=https://redacted*}
*"redacted" is the backend URL, and it is the correct and same path for each
immediately after restarting an actual device. I have been over the following threads with no results:
What is kCFStreamErrorCodeKey=-4 (kCFStreamErrorDomainKey=4)
Request timed out with _kCFStreamErrorCodeKey=60
How to better diagnose -1001 "The request timed out." URLSession errors
Random timed out error on app start
Because I was able to reproduce it, I have been able to get the following logs:
Console Logs.txt
Last bit of information is that I had Network Instruments running, and when this error occurred, I found that the Connection ID was "No Connection" and it appears the request was never actually sent, though it waited the full time out for a backend response.
Any help would be appreciated. This data request is being used after sending a certain APNs to update necessary data in the background, and has been the source of many user complaints.
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.
Hey,
We also opened a feedback assistant request,
and also opened a ticket with Apple Developer Technical Support a while ago that notice the unmount problem also but it was before we pin point the problem to the Network Extension.
After a further investigation, we've found out that the root cause of this problem is cause by having a network filter from the NetworkExtension provider on (Specifically we have tested with the NEFilterDataProvider) while having a Xsan volume.
The NEFilterDataProvider causing problems for the Xsan, and is stalling the shutdown until we get a panic from watchdog timeout, and only then the mac is fully shutdown.
The problem from what we investigated and also talked with you, is that the Xsan process can't unmount the volume and stuck.
We have also noticed that if we install a network extension and allow the popup of the network filters, i.e enabled the NEFilterDataProvider the computer is stuck, and the finder is in a non responsive state until a reboot (Also probably due to the fact the Xsan is now in a problematic state).
This tests was done on latest versions of MacOs 13 & 14.
We have taken a sysdiagnose from the computer while we have tested.
Do you familiar with the problem (We got no answer on the feedback assistant)?
Thank you,
Idan
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?
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
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…
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.
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.
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!
Topic:
App & System Services
SubTopic:
Networking
When installing a new version the app while a tunnel is connected, seemingly the old packet tunnel process gets stopped but the new one does not come back up. Reportedly, a path monitor is reporting that the device has no connectivity. Is this the expected behavior?
When installing an update from TestFlight or the App store, the packet tunnel instance from the old tunnel is stopped, but, due to the profile being on-demand and incldueAllNetworks, the path monitoring believes the device has no connectivity - so the new app is never downloaded. Is this the expected behavior?
During development, the old packet tunnel gets stopped, the new app is installed, but the new packet tunnel is never started. To start it, the user has to toggle the VPN twice from the Settings app. The tunnel could be started from the VPN app too, if we chose to not take the path monitor into account, but then the user still needs to attempt to start the tunnel twice - it only works on the second try. As far as we can tell, the first time around, the packet tunnel never gets started, the app receives an update about NEVPNStatus being set to disconnecting yet NEVPNConnection does not throw.
The behavior I was naively expecting was that the packet tunnel process would be stopped only when the new app is fully downloaded and when the update is installed, Are we doing something horribly wrong here?