Hi all!
I’m having trouble distributing an iOS app with a DNS Proxy NetworkExtension via AdHoc. The app and extension work perfectly with development profiles, but when I export and install the AdHoc IPA, I get a “permission denied” error when trying to install/enable the DNS Proxy extension.
What I’ve done:
Both the app and the DNS Proxy extension have their own App IDs in the Apple Developer portal.
Both App IDs have the same App Group enabled: group.com.irakai.SafeLinkApp2.
The extension App ID has the NetworkExtension capability with dns-proxy enabled.
I created two AdHoc provisioning profiles (one for the app, one for the extension), both including the same devices and the correct entitlements.
I assigned the correct AdHoc profiles to each target in Xcode and exported the IPA via Organizer.
I install the IPA on a registered device using Apple Configurator.
Entitlements (extracted from the signed binaries on device):
App:
<key>application-identifier</key><string>6PBG234246.com.irakai.SafeLinkApp2</string>
<key>com.apple.developer.networking.networkextension</key><array>
<string>packet-tunnel-provider</string>
<string>dns-proxy</string>
</array>
<key>com.apple.developer.team-identifier</key><string>6PBG234246</string>
<key>com.apple.security.application-groups</key><array>
<string>group.com.irakai.SafeLinkApp2</string>
</array>
<key>get-task-allow</key><false/>
DNSProxy Extension:
<key>application-identifier</key><string>6PBG234246.com.irakai.SafeLinkApp2.DNSProxy</string>
<key>com.apple.developer.networking.networkextension</key><array>
<string>dns-proxy</string>
</array>
<key>com.apple.developer.team-identifier</key><string>6PBG234246</string>
<key>com.apple.security.application-groups</key><array>
<string>group.com.irakai.SafeLinkApp2</string>
</array>
<key>get-task-allow</key><false/>
Error message (from my app’s logs):
Error instalando DNS Proxy: permission denied
Usuario: Roberto
AppGroup: group.com.irakai.SafeLinkApp2
AppGroupPath: /private/var/mobile/Containers/Shared/AppGroup/D8AD2DED-AD96-4915-9B7A-648C9504679B
Entitlements:
BundleId: com.irakai.SafeLinkApp2
Debug info: Error Domain=NEDNSProxyErrorDomain Code=1 "permission denied" UserInfo={NSLocalizedDescription=permission denied}
Other details:
The device is included in both AdHoc profiles.
The App Group is present and identical in both entitlements.
The extension’s bundle identifier matches the App ID in the portal.
The extension is signed with the correct AdHoc profile.
I have tried rebooting the device and reinstalling the IPA.
The error only occurs with AdHoc; development builds work fine.
Questions:
Is there anything else I should check regarding AdHoc provisioning for NetworkExtension DNS Proxy?
Are there any known issues with AdHoc and NetworkExtension on recent iOS versions?
Is there a way to get more detailed diagnostics from the system about why the permission is denied?
Could this be a bug in iOS, or am I missing a subtle configuration step?
Any help or suggestions would be greatly appreciated.
Thank you!
How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here
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'm working on enabling a content filter in my iOS app using NEFilterManager and NEFilterProviderConfiguration. The setup works perfectly in debug builds when running via Xcode, but fails on TestFlight builds with the following error:
**Failed to save filter settings: permission denied
**
**Here is my current implementation:
**
(void)startContentFilter {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults synchronize];
[[NEFilterManager sharedManager] loadFromPreferencesWithCompletionHandler:^(NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
NSLog(@"Failed to load filter: %@", error.localizedDescription);
[self showAlertWithTitle:@"Error" message:[NSString stringWithFormat:@"Failed to load content filter: %@", error.localizedDescription]];
return;
}
NEFilterProviderConfiguration *filterConfig = [[NEFilterProviderConfiguration alloc] init];
filterConfig.filterSockets = YES;
filterConfig.filterBrowsers = YES;
NEFilterManager *manager = [NEFilterManager sharedManager];
manager.providerConfiguration = filterConfig;
manager.enabled = YES;
[manager saveToPreferencesWithCompletionHandler:^(NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
NSLog(@"Failed to save filter settings: %@", error.localizedDescription);
[self showAlertWithTitle:@"Error" message:[NSString stringWithFormat:@"Failed to save filter settings: %@", error.localizedDescription]];
} else {
NSLog(@"Content filter enabled successfully!");
[self showAlertWithTitle:@"Success" message:@"Content filter enabled successfully!"];
}
});
}];
});
}];
}
**What I've tried:
**
Ensured the com.apple.developer.networking.networkextension entitlement is set in both the app and system extension.
The Network extension target includes content-filter-provider.
Tested only on physical devices.
App works in development build, but not from TestFlight.
**My questions: **
Why does saveToPreferencesWithCompletionHandler fail with “permission denied” on TestFlight?
Are there special entitlements required for using NEFilterManager in production/TestFlight builds?
Is MDM (Mobile Device Management) required to deploy apps using content filters?
Has anyone successfully implemented NEFilterProviderConfiguration in production, and if so, how?
Topic:
App & System Services
SubTopic:
Networking
Tags:
Extensions
Swift
Network Extension
Objective-C
Hello, I have encountered an issue with an iPhone 15PM with iOS 18.5. The NSHTTPCookieStorage failed to clear cookies, but even after clearing them, I was still able to retrieve them. However, on the same system
It is normal on iPhone 14PM. I would like to know the specific reason and whether there are any adaptation related issues. Following code:
NSHTTPCookie *cookie;
NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (cookie in [storage cookies]) {
[storage deleteCookie:cookie];
}
(iOS 17.3)
I'm using the Apple supplied iOS sample project "ConfiguringAWiFiAccessoryToJoinTheUsersNetwork" as a base to write an App to configure an existing WiFi device using the NEHotspotConfiguration API's. I have almost everything working, and can join the network and send a packet to the device to configure it. I know that it is working as the device responds properly to what I send it. But I am not able to receive the response back from the device to the packet sent. (Only need 1 packet sent and 1 packet received)
However. If I run a packet sniffer on the phone before running my test App, then I do get a response. No packet sniffer running, no response.
When I do a debugDescription on the NWConnection after it reaches ".ready", I notice that when the sniffer is running I'm using loopback lo0:
[C1 connected 192.168.4.1:80 tcp, url: http://192.168.4.1:80, attribution: developer, path satisfied (Path is satisfied), viable, interface: lo0]
and I get a packet response in the NWConnection receiveMessage callback.
But with no sniffer running, I get interface en0:
[C1 connected 192.168.4.1:80 tcp, url: http://192.168.4.1:80, attribution: developer, path satisfied (Path is satisfied), viable, interface: en0[802.11], ipv4, dns, uses wifi]
and there is no callback to the receiveMessage handler and the NWconnection eventually times out.
The interface used seems to be the only difference that I can see when I have a sniffer running. Any ideas as to why I can't see a response in "normal" operation?
Hi!
I'm working on a solution (iOS 18) that uses Network Extensions PacketTunnelProvider and Content Filter. Currently I'm trying to integrate it with another extension – DNSProxyProvider. My goal is to process dns queries and use resolved ips and names for additional routing inside of the packet tunnel. I'm running into a major issue: whenever both VPN and DNS proxy are active simultaneously, the device completely loses internet connectivity — no traffic goes through, and DNS resolution seems to stop working entirely.
I know about the mdm supervision requirement to use DNSProxyProvider and that's covered as I work with a managed device and install a DNS proxy profile, here's how its .mobileconfig file looks like:
The DNS proxy itself works fine when working by itself (without VPN being turned on), as I implemented it that it successfully processes DNS packets flows while collecting information about domains etc, and everything works perfectly. Problems begin when using VPN at the same time. I'm aware that tunnel settings include dns related options that can affect this, but I haven't had much luck with tweaking them. Here's how they look right now for reference:
let settings: NEPacketTunnelNetworkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "240.0.0.1")
// let dnsSettings = NEDNSSettings(servers: "8.8.8.8,8.8.4.4".components(separatedBy: ","))
// dnsSettings.matchDomains = [""]
// settings.dnsSettings = dnsSettings
settings.proxySettings = nil
/* ipv4 settings */
let ipv4Settings = NEIPv4Settings(addresses: ["240.0.0.2"], subnetMasks: ["255.255.255.0"])
ipv4Settings.includedRoutes = [NEIPv4Route.default()]
settings.ipv4Settings = ipv4Settings
/* MTU */
settings.mtu = 1500
return settings
I've tried excluding some dns related ip routes and dns settings shenanigans but nothing.
I haven't found any information that might suggest that using both of these extensions at the same time doesn't work, on the contrary, this page in the official documentation about the expected use of packet tunnel provider the expected use of packet tunnel provider, as it talks about the fact that you should not use it for interception of all of DNS traffic, as the use of DNSPRoxyProvider (or dns settings) are built for that, which in my mind, suggests that there should be no problem with using them both and just splitting the dns traffic handling to the proxy.
Will be thankful for any help!
We are implementing a connection between iPad and iPhone devices using LocalPushConnectivity,
and have introduced SimplePushProvider into the project.
We will have it switch between roles of Server and Client within a single project.
※ iPad will be Server and the iPhone will be Client.
Communication between Server and Client is via TLS, with Server reading p12 file and Client setting public key.
Currently, a TLS error code of "-9836" (invalid protocol version) is occurring when communicating from Client's SimplePushProvider to Server.
I believe that Client is sending TLS1.3, and Server is set to accept TLS1.2 to 1.3.
Therefore, I believe that the actual error is not due to TLS protocol version, but is an error that is related to security policy or TLS communication setting.
Example:
P12 file does not meet some requirement
NWProtocolTLS.Options setting is insufficient
etc...
I'm not sure what the problem is, so please help.
For reference, I will attach you implementation of TLS communication settings.
P12 file is self-signed and was created by exporting it from Keychain Access.
Test environment:
iPad (OS: 16.6)
iPhone (OS: 18.3.2)
ConnectionOptions: TLS communication settings
public enum ConnectionOptions {
public enum TCP {
public static var options: NWProtocolTCP.Options {
let options = NWProtocolTCP.Options()
options.noDelay = true
options.enableFastOpen
return options
}
}
public enum TLS {
public enum Error: Swift.Error {
case invalidP12
case unableToExtractIdentity
case unknown
}
public class Server {
public let p12: URL
public let passphrase: String
public init(p12 url: URL, passphrase: String) {
self.p12 = url
self.passphrase = passphrase
}
public var options: NWProtocolTLS.Options? {
guard let data = try? Data(contentsOf: p12) else {
return nil
}
let pkcs12Options = [kSecImportExportPassphrase: passphrase]
var importItems: CFArray?
let status = SecPKCS12Import(data as CFData, pkcs12Options as CFDictionary, &importItems)
guard status == errSecSuccess,
let items = importItems as? [[String: Any]],
let importItemIdentity = items.first?[kSecImportItemIdentity as String],
let identity = sec_identity_create(importItemIdentity as! SecIdentity)
else {
return nil
}
let options = NWProtocolTLS.Options()
sec_protocol_options_set_min_tls_protocol_version(options.securityProtocolOptions, .TLSv12)
sec_protocol_options_set_max_tls_protocol_version(options.securityProtocolOptions, .TLSv13)
sec_protocol_options_set_local_identity(options.securityProtocolOptions, identity)
sec_protocol_options_append_tls_ciphersuite(options.securityProtocolOptions, tls_ciphersuite_t.RSA_WITH_AES_128_GCM_SHA256)
return options
}
}
public class Client {
public let publicKeyHash: String
private let dispatchQueue = DispatchQueue(label: "ConnectionParameters.TLS.Client.dispatchQueue")
public init(publicKeyHash: String) {
self.publicKeyHash = publicKeyHash
}
// Attempt to verify the pinned certificate.
public var options: NWProtocolTLS.Options {
let options = NWProtocolTLS.Options()
sec_protocol_options_set_min_tls_protocol_version(options.securityProtocolOptions, .TLSv12)
sec_protocol_options_set_max_tls_protocol_version(options.securityProtocolOptions, .TLSv13)
sec_protocol_options_set_verify_block(
options.securityProtocolOptions,
verifyClosure,
dispatchQueue
)
return options
}
private func verifyClosure(
secProtocolMetadata: sec_protocol_metadata_t,
secTrust: sec_trust_t,
secProtocolVerifyComplete: @escaping sec_protocol_verify_complete_t
) {
let trust = sec_trust_copy_ref(secTrust).takeRetainedValue()
guard let serverPublicKeyData = publicKey(from: trust) else {
secProtocolVerifyComplete(false)
return
}
let keyHash = cryptoKitSHA256(data: serverPublicKeyData)
guard keyHash == publicKeyHash else {
// Presented certificate doesn't match.
secProtocolVerifyComplete(false)
return
}
// Presented certificate matches the pinned cert.
secProtocolVerifyComplete(true)
}
private func cryptoKitSHA256(data: Data) -> String {
let rsa2048Asn1Header: [UInt8] = [
0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00
]
let data = Data(rsa2048Asn1Header) + data
let hash = SHA256.hash(data: data)
return Data(hash).base64EncodedString()
}
private func publicKey(from trust: SecTrust) -> Data? {
guard let certificateChain = SecTrustCopyCertificateChain(trust) as? [SecCertificate],
let serverCertificate = certificateChain.first else {
return nil
}
let publicKey = SecCertificateCopyKey(serverCertificate)
return SecKeyCopyExternalRepresentation(publicKey!, nil)! as Data
}
}
}
}
Hi!
I recently had an idea to build an iOS app that allows users to create a system-level block of specified web domains by curating a "blacklist" on their device.
If the user, for instance, inputs "*example.com" to their list, their iPhone would be blocked from relaying that network traffic to their ISP/DNS, and hence return an error message ("iPhone can't open the page because the address is invalid") instead of successfully fetching the response from example.com's servers.
The overarching goal of this app would be to allow users to time-block their use of specified websites/apps and grant them greater agency over their technology consumption, and I thought that an app that blocks traffic at the network level, combined with the ability to control when to/not to allow access, would be a powerful alternative to the existing implementations out there that work more on the browser-level (eg. via Safari extension, which is isolated to the scope of user's Safari browser) or via Screen Time (which can be easy to bypass by inputting one's passcode).
Another thing to mention is that since the app would serve as a local DNS proxy (instead of relying on a third party DNS resolver), none of their internet activity will be collected/transmitted off-device and be used for commercial purposes. I feel particularly driven to create a privacy-centered app in this way, since no user data needs to be harvested to implement this kind of filtering. I'd also love to get suggestions for a transparent privacy policy that respects users control over their device.
With all this said, I found that the Network Extension APIs may be the only way that an app like this could be built on iOS and, I wanted to ask if the above-mentioned use case of Network Extension would be eligible to be granted access to its entitlement before I go ahead and purchase the $99/year Apple Developer Program membership.
Happy to provide further information, and I'd also particularly be open to any mentions of existing solutions out there (since I might have missed some in my search). Maybe something like this already exists, in which case it'd be great to know in any case! :).
Thank you so much in advance!
As a third-party application on Apple Watch, can it be located in the same LAN httpServer? Currently, when testing to initiate an http request in the LAN, the connection timeout is returned, code: -1001
self.customSession.request("http://10.15.48.191:9000/hello").response { response in
switch response.result {
case .success(let data):
dlog("✅ 请求成功,收到数据:")
if let html = String(data: data ?? Data(), encoding: .utf8) {
dlog(html)
}
case .failure(let error):
dlog("❌ 请求失败:\(error.localizedDescription)")
}
}
执行后报错
Task <B71BE820-FD0E-4880-A6DD-1F8F6EAF98B0>.<1> finished with error [-1001] Error Domain=NSURLErrorDomain Code=-1001 "请求超时。" UserInfo={_kCFStreamErrorCodeKey=-2102, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <B71BE820-FD0E-4880-A6DD-1F8F6EAF98B0>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <B71BE820-FD0E-4880-A6DD-1F8F6EAF98B0>.<1>",
"LocalDataPDTask <B71BE820-FD0E-4880-A6DD-1F8F6EAF98B0>.<1>",
"LocalDataTask <B71BE820-FD0E-4880-A6DD-1F8F6EAF98B0>.<1>"
), NSLocalizedDescription=请求超时。, _kCFStreamErrorDomainKey=4, NSErrorFailingURLStringKey=http://10.15.48.191:9000/hello, NSErrorFailingURLKey=http://10.15.48.191:9000/hello}
On one test machine, our extension wouldn't load, because [NETransparentProxyManager loadAllFromPreferencesWithCompletionHandler] can't find a manager, saying Skipping configuration appname because it is of the wrong type. This is the first time I've seen this behaviour.
(The containing app tries to find a configuration, if it can't find it it creates one, then modifies whatever it found or created, then stores it. I don't have the right logging yet for that, so I can't see the error messages. [NSLog instead of os_log_error.])
Hello there,
Starting from iOS 18.4, support was included for QWAC Validation and QCStatements.
Using the official QWAC Validator at: https://eidas.ec.europa.eu/efda/qwac-validation-tool
I was able to check that the domain "eidas.ec.europa.eu" has a valid QWAC certificate. However, when trying to obtain the same result using the new API, I do not obtain the same result.
Here is my sample playground code:
import Foundation
import Security
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
@MainActor
class CertificateFetcher: NSObject, URLSessionDelegate {
private let url: URL
init(url: URL) {
self.url = url
super.init()
}
func start() {
let session = URLSession(configuration: .ephemeral, delegate: self, delegateQueue: nil)
let task = session.dataTask(with: url) { data, response, error in
if let error = error {
print("Error during request: \(error)")
} else {
print("Request completed.")
}
}
task.resume()
}
nonisolated func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard let trust = challenge.protectionSpace.serverTrust else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
if let certificates = SecTrustCopyCertificateChain(trust) as? [SecCertificate] {
self.checkQWAC(certificates: certificates)
}
let credential = URLCredential(trust: trust)
completionHandler(.useCredential, credential)
}
nonisolated func checkQWAC(certificates: [SecCertificate]) {
let policy = SecPolicyCreateSSL(true, nil)
var trust: SecTrust?
guard SecTrustCreateWithCertificates(certificates as CFArray, policy, &trust) == noErr, let trust else {
print("Unable to create SecTrust")
return
}
var error: CFError?
guard SecTrustEvaluateWithError(trust, &error) else {
print("Trust evaluation failed")
return
}
guard let result = SecTrustCopyResult(trust) as? [String : Any] else {
print("No result dictionary")
return
}
let qwacStatus = result[kSecTrustQWACValidation as String]
let qcStatements = result[kSecTrustQCStatements as String]
print("QWAC Status: \(String(describing: qwacStatus))")
print("QC Statements: \(String(describing: qcStatements))")
}
}
let url = URL(string: "https://eidas.ec.europa.eu/")!
let fetcher = CertificateFetcher(url: url)
fetcher.start()
Which prints:
QWAC Status: nil
QC Statements: nil
Request completed.
Am I making a mistake while using the Security framework? I would greatly appreciate any help or guidance you can provide.
Hello everyone,
I'm trying to figure out how to transmit a UIImage (png or tiff) securely to an application running in my desktop browser (Mac or PC). The desktop application and iOS app would potentially be running on the same local network (iOS hotspot or something) or have no internet connection at all.
I'm trying to securely send over an image that the running desktop app could ingest. I was thinking something like a local server securely accepting image data from an iPhone.
Any suggestions ideas or where to look for more info would be greatly appreciated!
Thank you for your help.
I have read all the information and forum posts about local network, such as TN3179, etc., and have added NSLocalNetworkUsageDescription, but it does not solve my problem.
The problem I encountered is described as follows:
Device: iOS18.1.1
Signing method: automatic
Xcode debug directly runs, and the app can access 17.25.11.128 normally. However, relase run or packaged into adhoc installation, this IP cannot be accessed. There is a phenomenon that the app package of the App Store can also be used.
Our test team has few iOS18+ devices, and internal testing is not possible. Please contact us as soon as possible, thank you.
=======
我已经了解了所有关于local network 相关的资料和论坛帖子,比如TN3179 等等, 已经添加了 NSLocalNetworkUsageDescription, 但是不解决我的问题。
我遇到的问题描述如下:
设备:iOS18.1.1
签名方式:自动
xcode debug 直接运行,app是可以正常访问17.25.11.128的。 但是 relase run 或者 打包成 adhoc 安装,就无法访问这个IP了。 有一个现象, App Store 的app包 也是可以的。
我们的测试团队,iOS18+的设备就没几个,还不能内部测试了。请尽快联系我们,谢谢。
Hi all,
We've been exploring the capabilities of the Network.framework for peer-to-peer communication and have run into some behavior that we haven't been able to fully explain with the existing documentation.
In our tests, we’re working with 12 iOS devices, all disconnected from Wi-Fi to force communication over Apple Wireless Direct Link (AWDL). While using the Network.framework to create peer-to-peer connections, we observed that the number of connected peers never exceeded 8, despite all 12 devices being active and configured identically.
Some questions we’re hoping to get clarification or discussion on:
Is there a known upper limit to the number of peer-to-peer connections supported via AWDL?
Are there conditions under which the framework or system limits or throttles visible peers?
Does AWDL behavior vary by hardware model, iOS version, or backgrounding state of the app?
Is there any official documentation or guidance around peer discovery or connection limits when using NWBrowser and NWConnection in a peer-to-peer context?
We’d appreciate any insights from the Apple engineering team or other developers who have worked with larger peer groups using Network.framework in peer-to-peer mode.
Question 1: After NetworkExtension is installed, when the software receives a pushed uninstall command, it needs to download the entire software but fails to uninstall this NetworkExtension. Are there any solutions?
Question 2: How can residual, uninstalled NetworkExtensions be cleaned up when SIP (System Integrity Protection) is enabled?
We have a setup where the system uses proxy settings configured via a PAC file. We are investigating how NWConnection behaves inside a Network Extension (NETransparentProxyProvider) with a transparent proxy configuration based on this PAC file.
Scenario:
The browser makes a connection which the PAC file resolves as "DIRECT" (bypassing the proxy)
Our Network Extension intercepts this traffic for analysis
The extension creates a new connection using NWConnection to the original remote address.
The issue: despite the PAC file’s "DIRECT" decision, NWConnection still respects the system proxy settings and routes the connection through the proxy.
Our questions:
Is it correct that NWConnection always uses the system proxy if configured ?
Does setting preferNoProxies = true guarantee bypassing the system proxy?
Additionally:
Whitelisting IPs in the Network Extension to avoid interception is not a viable solution because IPs may correspond to multiple services, and the extension only sees IP addresses, not domains (e.g., we want to skip scanning meet.google.com traffic but still scan other Google services on the same IP range).
Are there any recommended approaches or best practices to ensure that connections initiated from a Network Extension can truly bypass the proxy (for example, for specific IP ranges or domains)?
i unfortunatly upgraded to Sequoia since then I see when:
i select
XCode ->Product->run
i see
Error: No route to host
i cannot grant access to local network for XCode
i can no longer debug my program as i did with Sonora
Recently, while developing a network extension on macOS, I encountered a very interesting issue. When the App Sandbox entitlement is included, the NE (Network Extension) can be called and run normally. However, when the App Sandbox is removed, with everything else remaining unchanged, an error occurs. The logs are as follows:
Failed to find an app extension with identifier app.acmeVpnM.extension and extension point com.apple.networkextension.packet-tunnel: (null)
Found 0 registrations for app.acmeVpnM.extension (com.apple.networkextension.packet-tunnel)
If you add app sandbox, it will run normally.
this is my container app entitlement
this is my NE extension (without App SandBox)
I want to know the reason for this. App sandbox shouldn't be mandatory. How can I make my NE run in an environment without app sandbox?
Hi,
I’m trying to download a remote file in the background, but I keep getting a strange behaviour where URLSession download my file indefinitely during a few minutes, without calling urlSession(_:downloadTask:didFinishDownloadingTo:) until the download eventually times out.
To find out that it’s looping, I’ve observed the total bytes written on disk by implementing urlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:).
Note that I can't know the size of the file. The server is not able to calculate the size.
Below is my implementation.
I create an instance of URLSession like this:
private lazy var session: URLSession = {
let configuration = URLSessionConfiguration.background(withIdentifier: backgroundIdentifier)
configuration.isDiscretionary = false
configuration.sessionSendsLaunchEvents = true
return URLSession(configuration: configuration,
delegate: self,
delegateQueue: nil)
}()
My service is using async/await so I have implemented an AsyncThrowingStream :
private var downloadTask: URLSessionDownloadTask?
private var continuation: AsyncThrowingStream<(URL, URLResponse), Error>.Continuation?
private var stream: AsyncThrowingStream<(URL, URLResponse), Error> {
AsyncThrowingStream<(URL, URLResponse), Error> { continuation in
self.continuation = continuation
self.continuation?.onTermination = { @Sendable [weak self] data in
self?.downloadTask?.cancel()
}
downloadTask?.resume()
}
}
Then to start the download, I do :
private func download(with request: URLRequest) async throws -> (URL, URLResponse) {
do {
downloadTask = session.downloadTask(with: request)
for try await (url, response) in stream {
return (url, response)
}
throw NetworkingError.couldNotBuildRequest
} catch {
throw error
}
}
Then in the delegate :
public func urlSession(_ session: URLSession,
downloadTask: URLSessionDownloadTask,
didFinishDownloadingTo location: URL) {
guard let response = downloadTask.response,
downloadTask.error == nil,
(response as? HTTPURLResponse)?.statusCode == 200 else {
continuation?.finish(throwing: downloadTask.error)
return
}
do {
let documentsURL = try FileManager.default.url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: false)
let savedURL = documentsURL.appendingPathComponent(location.lastPathComponent)
try FileManager.default.moveItem(at: location, to: savedURL)
continuation?.yield((savedURL, response))
continuation?.finish()
} catch {
continuation?.finish(throwing: error)
}
}
I also tried to replace let configuration = URLSessionConfiguration.background(withIdentifier: backgroundIdentifier) by let configuration = URLSessionConfiguration.default and this time I get a different error at the end of the download:
Task <0457F755-9C52-4CFB-BDB2-F378D0C94912>.<1> failed strict content length check - expected: 0, received: 530692, received (uncompressed): 0
Task <0457F755-9C52-4CFB-BDB2-F378D0C94912>.<1> finished with error [-1005] Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={NSLocalizedDescription=The network connection was lost., NSErrorFailingURLStringKey=https:/<host>:8190/proxy?Func=downloadVideoByUrl&SessionId=slufzwrMadvyJad8Lkmi9RUNAeqeq, NSErrorFailingURLKey=https://<host>:8190/proxy?Func=downloadVideoByUrl&SessionId=slufzwrMadvyJad8Lkmi9RUNAeqeq, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDownloadTask <0457F755-9C52-4CFB-BDB2-F378D0C94912>.<1>"
), _NSURLErrorFailingURLSessionTaskErrorKey=LocalDownloadTask <0457F755-9C52-4CFB-BDB2-F378D0C94912>.<1>, NSUnderlyingError=0x300d9a7c0 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={NSErrorPeerAddressKey=<CFData 0x302139db0 [0x1fcb1f598]>{length = 16, capacity = 16, bytes = 0x10021ffe91e227500000000000000000}}}}
The log "failed strict content length check” made me look into the response header, which has the following:
content-length: 0
Content-Type: application/force-download
Transfer-encoding: chunked
Connection: KEEP-ALIVE
Content-Transfer-Encoding: binary
So it should be fine the way I setup my URLSession.
The download works fine in Chrome/Safari/Chrome or Postman.
My code used to work a couple of weeks before, so I expect something has changed on the server side, but I can’t find what, and I don’t get much help from the guys on the server side.
Has anyone an idea of what’s going on?
Topic:
App & System Services
SubTopic:
Networking
Tags:
Network
Background Tasks
CFNetwork
Foundation
Hello,
I'm running into an issue while developing an iOS app that requires local network access. I’m using the latest MacBook Air M4 with macOS sequoia 15.5 and Xcode 16.1. In the iOS Simulator, my app fails to discover devices connected to the same local network.
I’ve already added the necessary key to the Info.plist:
NSLocalNetworkUsageDescription
This app needs access to local network devices.
When I run the app on a real device and M2 Chip Macbook's simulators, it works fine for local network permission as expected. However, in the M4 Chip Macbook's Simulator:
The app can’t find any devices on the local network
Bonjour/mDNS seems not to be working as well
I’ve tried the following without success:
Restarting Simulator and Mac
Resetting network settings in Simulator
Confirming app permissions under System Settings > Privacy & Security
Has anyone else encountered this issue with the new Xcode/macOS combo? Is local network access just broken in the Simulator for now, or is there a workaround?
Thanks in advance!
We are a hardware manufacturer. Our devices are connected via Ethernet to Mac mini systems, where our custom macOS application is installed and communicates with the connected hardware. The application is signed and deployed as a standard application bundle.
Description
The application performs a UDP broadcast using the Universal Plug and Play (UPnP) discovery mechanism to locate devices connected to the same local network segment.
We have observed a reproducible issue with macOS 15.x (confirmed with 15.1 through 15.4), where the discovery fails under specific circumstances. The behavior is as follows:
If the application is launched via Finder (e.g., double-clicked by the user), no device is discovered.
If the same binary is launched from the Terminal, discovery works as expected and the connected device is found.
Downgrading the affected Mac mini to macOS 14.x (e.g., Sonoma 14.0 or 14.1) restores the expected behavior—discovery works via Finder as well.
The issue is observed only on Intel-based Mac minis.
On Apple Silicon (ARM-based) Mac minis, the discovery via Finder works correctly, even on macOS 15.4.
What we know
The problem is tied to how the network stack or sandboxing behaves when the application is launched via Finder.
There are no visible error messages.
It is unclear whether the broadcast packet is being blocked, or if the response from the device is dropped or filtered by the system.
Reproduction Steps
Install our signed application bundle on a Mac mini (Intel).
Connect our device via Ethernet to the Mac mini.
Launch the application via Finder – the device is not found.
Quit the application.
Launch the same binary from Terminal – the device is correctly discovered.
Downgrade the same system to macOS 14.x – discovery works in both cases (Finder and Terminal).
Upgrade to macOS 15.x – the issue reappears.
Technical Details
macOS Version(s) Affected: 15.x (confirmed with 15.1 through 15.4),
Mac mini Model: Intel-based Mac minis
Type of Communication: UDP broadcast using UPnP
Reproducibility: 100% reproducible with affected macOS versions.
Software Environment: Custom application developed by us, running as a user-space application under standard macOS network APIs.
No Issues: When the same setup is used on earlier macOS versions.
Request
Can you confirm whether this is expected behavior due to changes in macOS 15 (e.g., sandboxing, entitlements, network permissions)?
What steps or configuration changes are required to ensure UDP discovery works again when the application is launched via Finder?
Are there relevant macOS logs (e.g., Console, system logs) we can inspect for network-related blocks or errors?
We would appreciate any guidance or clarification on how to adapt our application or system configuration to restore expected network discovery behavior.
Thank you in advance for your support!