I have an application that uses Bonjour to communicate with other instances of the app on other devices.
If I start an NWBrowser and the user has "Local Network" turned off for my app, the stateUpdateHandler for the browser gets .waiting with an error containing the string "PolicyDenied." This lets me show an alert to the user explaining what's happening, with a link to the app's Settings screen.
But if I use NWListener (the counterpart of NWBrowser) and have "Local Network" turned off, there's no indication of any problem. After I start the listener, stateUpdateHandler is called with .ready as the state - even though it's not really ready to listen at all.
The FAQ for Local Network Privacy suggests that any Bonjour operation will raise kDNSServiceErr_PolicyDenied if Local Network is off. However, in my application, that only seems to be true for browsing, not listening.
Is there a way to detect a missing Local Network entitlement for NWListener? I know there are solutions involving sending a message to localhost, etc, but ideally there would be something simpler.
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
Due to some challenging corporate network firewall, security filters and certificate management, I would like to implement a TLS server where it initiates the TCP connection to the client side so that once TCP is connected, the client side sends its Client Hello message. Everything then continues as expected.
The connection would use Bonjour to locate the TLS client endpoint that is hosted on iOS. The TLS server will be hosted on MacOS.
Swapping the normal tcp listener as TLS server will help with certificate management as the Mac will have the server cert installed and the iOS device will have the client cert installed.
Forward posting from the Swift Forums.
Within my iOS project (thesis project) I have set up a MITM server that is being sent data from a Packet Tunnel Provider. I am currently seeing that all IPv6 requests aren't able to have their IP address resolved when passed to Swift NIO that uses the default system DNS resolver.
On the Packet Tunnel Provider, I have set it to use the DNS's 8.8.8.8 and 8.8.4.4 that are also the system defaults. I have also attempted to use my routers DNS routing to no avail. Both v4 and v6 traffic are proxied to the MITM server that uses Swift NIO, with v4 traffic successfully being processed on ingress and egress as intended. IPv6 traffic is failing to resolve with the following error:
dev.thesis.apps.LocalProxyServer.ConnectHandler : [LocalPacketTunnelProvider] Connect failed: NIOConnectionError(host: "ipv6.mythic-beasts.com", port: 443, dnsAError: Optional(NIOCore.SocketAddressError.unknown(host: "ipv6.mythic-beasts.com", port: 443)), dnsAAAAError: Optional(NIOCore.SocketAddressError.unknown(host: "ipv6.mythic-beasts.com", port: 443)), connectionErrors: [])
ipv6.mythic-beasts.com for the purposes of this is just a test website I am using that only has a AAAA record associated with it:
When not connected to the Packet Tunnel Provider, the website is successfully resolved and can be viewed within the browser - so I have narrowed it down to either the server or tunnel configuration.
The server uses the GetaddrinfoResolver, that utilises the iOS's system default DNS resolver. This should conform to necessary RFC.
Could anyone provide me with a reason why this could be happening and if possible a link to a resource that could assist with remediating the issue? I'll be the first to admit this isn't my forte so would appreciate some support if possible.
I am aware that this isn't an expected use cases for Network Extension packet tunnel providers (as per TN3120). I'm just concerned as IPv4 DNS records are resolving but IPv6 aren't so wondering if this is a wider issue. would expect the system DNS resolver to still work as intended though.
Hi! I have been working on one idea for a while but can't figure out the proper way to do that. My app includes Content Filter and DNSProxy providers for filtering logic. And for the NEFilterSocketFlow everything works well, because the connection is first handled from DNSProxy and if it's blocked, NEFilterDataProvider returns datagrams that I wrote from DNSProxy (I return nxdomain). However, for NEFilterBrowserFlow it doesn't work, because webkit generated flows are for some reason intercepted by Content Filter first and at the time when the flow is checked for rules, there're none yet as DNSProxy didn't handle connection yet.
So the app returns the following behaviour:
In case the requested domain is not filtered by DNSProxy, the user is able to visit requested page, but if it's filtered, the flow just freezes and the page will never load for user. But I wanted to add proper handling and display block page.
In case I am using some third-party apps for testing like ICS Dig, filtered domains return nxdomain properly.
Not sure if there's a way to achieve desired result, but would be very grateful for any suggestions
Hey,
I'm currently developing an app that uses NEHotspotConfigurationManager to connect to and disconnect from a WiFi network based on user actions. I'm using the following code to connect and disconnect:
Connect
let configuration = NEHotspotConfiguration(ssid: ssid, passphrase: password, isWEP: false)
configuration.joinOnce = true
NEHotspotConfigurationManager.shared.apply(configuration) { (error) in
if let error = error {
print("Error connecting to WiFi network: \(error.localizedDescription)")
} else {
self.lastSSID = ssid
}
}
Disconnect
NEHotspotConfigurationManager.shared.removeConfiguration(forSSID: self.lastSSID)
The issue I'm encountering is that the app successfully connects to the WiFi network and disconnects properly the first time. However, after connecting again, the second disconnect attempt fails to disconnect from the WiFi network.
I found a similar bug report from 2020 that mentioned this issue. The suggested workaround involved setting joinOnce = false, which is not suitable for my app's requirements.
We are using CoreTelephony's CTTelephonyNetworkInfo to access Carrier information such as carrierName, mobileNetworkCode, mobileCountryCode and CTTelephonyNetworkInfo().subscriberCellularProviderDidUpdateNotifier to know whether any event has occurred in the sim. We are using these above data for the Sim Binding process of UPI for our Financial App as per the requirement from NPCI(RBI). Now that these are deprecated, what is the appropriate or alternative way to get these details?
Our app uses NEVPNManager with IPsec to create VPN. Full tunnel is working fine both with NEVPNManager API and profile created using Apple Configurator.
Now, we are trying to create split tunnel using the same. Apple Configurator created profile is working when DNS Supplemental Match domains is set to empty string. But we couldn't find the equivalent to the DNS Supplemental Match domains in the NEVPNManager API. In NEVPNManager config, all DNS is routing to the default route instead of VPN.
Can you please help us on this?
iOS 18 beta, iPhone 14 plus. Doesn't work mac address rotation in Wi-Fi network settings. It does nothing, when I toggle on-off the switch
I was developing an electron based app, and I want to embed a system extension in it, everything works fine with SIP disabled.
But for normal cases, I found out:
Notarization require hardened runtime enabled.
The container is an electron based app, which has JIT related feature, so it requires hardened runtime relaxation entitlements (some exception)
But System extension disallow these entitlements, this error message is captured from the log system: Hardened Runtime relaxation entitlements disallowed on System Extensions
So does this mean we can't embed a system extension in an Electron-based app?
OS: MacOS 14.3 (23D56)
I have PacketTunnelProvider VPN running with MTU on utun interface as 1300.
% ifconfig utun4
utun4: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1300
options=6460<TSO4,TSO6,CHANNEL_IO,PARTIAL_CSUM,ZEROINVERT_CSUM>
inet 192.166.54.1 --> 192.166.54.1 netmask 0xffffff00
nd6 options=201<PERFORMNUD,DAD>
When I am sending Jumbo size packets using ICMP and it is working fine till 4068 bytes packet size, after that ICMP responses are not accepted by the utun interface.
Working till 4068 packets:
% ping 13.71.68.85 -s 4068
PING 13.71.68.85 (13.71.68.85): 4068 data bytes
4076 bytes from 13.71.68.85: icmp_seq=0 ttl=56 time=46.040 ms
4076 bytes from 13.71.68.85: icmp_seq=1 ttl=56 time=25.353 ms
Not Working after sending 4069 packets:
% ping 13.71.68.85 -s 4069
PING 13.71.68.85 (13.71.68.85): 4069 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
In System logs I could see below errors:
% log stream | grep utun4
2024-06-19 17:22:34.666286+0530 0x7ee9e2 Error 0x0 0 0 kernel: utun_netif_sync_rx utun4: legacy packet length 4097 > 4096
2024-06-19 17:22:35.637723+0530 0x7ee9e2 Error 0x0 0 0 kernel: utun_netif_sync_rx utun4: legacy packet length 4097 > 4096
Note: Same works fine on en0 interface when packet is not routed via utun interface.
Working till 8184 packets on en0 interface:
% ping 13.71.68.85 -s 8184
PING 13.71.68.85 (13.71.68.85): 8184 data bytes
8192 bytes from 13.71.68.85: icmp_seq=0 ttl=51 time=198.928 ms
8192 bytes from 13.71.68.85: icmp_seq=1 ttl=51 time=46.139 ms
% ping 13.71.68.85 -s 8185
PING 13.71.68.85 (13.71.68.85): 8185 data bytes
ping: sendto: Message too long
ping: sendto: Message too long
Does this mean, on utun interface we do not support packet inception of more than 4096 size?
When I initiate the following request in the app delegate, it is good in iOS 17, but it will crash in iOS 18.
The code is as below:
NSString *url = @"https://www.baidu.com";
NSString * restr = [NSString stringWithContentsOfURL:[NSURL URLWithString:url] encoding:NSUTF8StringEncoding error:nil];
The stack is as below:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSFileManager createDirectoryAtURL:withIntermediateDirectories:attributes:error:]: URL is nil'
*** First throw call stack:
(
0 CoreFoundation 0x00007ff8004c14d5 __exceptionPreprocess + 242
1 libobjc.A.dylib 0x00007ff800084116 objc_exception_throw + 62
2 Foundation 0x00007ff800f00861 -[NSFileManager contentsOfDirectoryAtPath:error:] + 0
3 CFNetwork 0x00007ff804c66bfd -[_NSHTTPAlternativeServicesStorage _onqueue_initializeDatabaseIfNotEmpty:] + 488
4 CFNetwork 0x00007ff804c69350 __66-[_NSHTTPAlternativeServicesStorage HTTPServiceEntriesWithFilter:]_block_invoke + 48
5 libdispatch.dylib 0x0000000115349f32 _dispatch_client_callout + 8
6 libdispatch.dylib 0x000000011535ad86 _dispatch_lane_barrier_sync_invoke_and_complete + 133
7 CFNetwork 0x00007ff804c65bf7 -[_NSHTTPAlternativeServicesStorage HTTPServiceEntriesWithFilter:] + 211
8 CFNetwork 0x00007ff804cd5ccc _ZN11TubeManager34_onqueue_enqueueRequestForProtocolEP25MetaConnectionCacheClientPK18HTTPRequestMessage21MetaConnectionOptionsP16BaseAwaitingTube + 264
9 CFNetwork 0x00007ff804bf8b0c ___ZN12XTubeManager25enqueueRequestForProtocolEP25MetaConnectionCacheClientPK18HTTPRequestMessage21MetaConnectionOptionsPK17CoreSchedulingSet_block_invoke + 328
10 CFNetwork 0x00007ff804bf8832 _ZN12XTubeManager15withTubeManagerEPK17CoreSchedulingSetU13block_pointerFvP15GlueTubeManagerE + 516
11 CFNetwork 0x00007ff804d27823 _ZN12HTTPProtocol81asynchronouslyCreateAndOpenStream_WithMessage_AfterCookiesAndAuthenticatorHeadersEP15__CFHTTPMessage + 6077
12 CFNetwork 0x00007ff804d25ea3 _ZN12HTTPProtocol48asynchronouslyAddAuthenticatorHeadersAndContinueEP15__CFHTTPMessage + 103
13 CFNetwork 0x00007ff804d295b3 ___ZN12HTTPProtocol35asynchronouslyAddCookiesAndContinueEP15__CFHTTPMessage_block_invoke_3 + 26
14 CFNetwork 0x00007ff804e0fdb7 ___ZNK18QCoreSchedulingSet12performAsyncEU13block_pointerFvvE_block_invoke + 41
15 libclang_rt.asan_iossim_dynamic.dyl 0x0000000115d0fa4c __wrap_dispatch_async_block_invoke + 204
16 libdispatch.dylib 0x0000000115348ba9 _dispatch_call_block_and_release + 12
17 libdispatch.dylib 0x0000000115349f32 _dispatch_client_callout + 8
18 libdispatch.dylib 0x0000000115351e3b _dispatch_lane_serial_drain + 1078
19 libdispatch.dylib 0x0000000115352bbc _dispatch_lane_invoke + 448
20 libdispatch.dylib 0x0000000115353be7 _dispatch_workloop_invoke + 876
21 libdispatch.dylib 0x000000011535fcc6 _dispatch_root_queue_drain_deferred_wlh + 318
22 libdispatch.dylib 0x000000011535f205 _dispatch_workloop_worker_thread + 853
23 libsystem_pthread.dylib 0x000000011521db84 _pthread_wqthread + 327
24 libsystem_pthread.dylib 0x000000011521cacf start_wqthread + 15
)
libc++abi: terminating due to uncaught exception of type NSException
Hi,
When running my iOS app in Xcode, I got the following message in the console multiple times:
[connection] nw_read_request_report [C1] Receive failed with error "Operation timed out"
It seems not critical as my app still works, but how can I find out more details of the connection that printed this message? For example, the network request the caused this, or the URL?
Xcode: 15.3
iOS 17
SwiftUI app
Hi all, I had previously posted this on the Media Technologies section but didn't receive any replies so thought I would try my luck here. Apologies if re-posting questions on the forum in a short-ish time span is against the rules, but would greatly appreciate some assistance with the following situation regarding GroupSessionJournal and loading attachments.
I'm currently working on a shareplay feature that allows users to pull 3d models from icloud and view it via volumes/immersive space on the vision pro. Was able to get the sharing working with multiple windows recently so now all that's left is to be able to sync/share the model in the SharePlay session.
As I understand it, we should generally use GroupSessionMessenger for commands and light data like model positioning/syncing properties. Whereas for bigger pieces of data (images/videos/models), we should send these through GroupSessionJournal which the group session manages and syncs it for all users in the call.
I have a button to get the current user's model data and add it to the journal via
/// modelData is type `Data`
try await journal.add(modelData)
I have also set up a task to observe/receive updates to the journal's attachments in when receiving a group session.
for await groupSession in MyModelActivity.sessions() {
...
tasks.insert {
Task {
for await attachments in journal.attachments {
for attachment in attachments {
do {
let modelData = try await attachment.load(Data.self) // throws error here - `notSupported`
let modelUrl = writeModelDataToTempDirectory(modelData: modelData)
self.modelUrlToLoadForGroupSession = modelUrl
} catch let error {
print("Error: \(error)")
}
}
}
}
}
}
Not quite sure why I'm running into an error being thrown when attempting to load the attachment data on the other devices, any thoughts? The documentation for add(_:) and load(_:) say that the attachment should conform to Transferable but Data.Type should already conform to Transferable
My company uses a VPN to provide access to cloud services for development purposes. I am unable to reach these services from VMs or devices using Internet Sharing. In both cases, those instances can reach the Internet just fine.
Here is what the routing table looks like for the VPN:
100.20.x.x 100.65.0.1 UGHS utun1
100.21.x.x 100.65.0.1 UGHS utun1
100.64/10 utun0 Uc utun0
100.65/16 100.65.0.1 UGSc utun1
If I add a custom pf rule, I can get the VM packets routed to the VPN:
nat from 192.168.66.0/24 to 100.65.0.0/16 -&gt; (utun1)
But, inexplicably, a similar rule for 192.168.2.0/24 does nothing. Using Wireshark, I still see packets sent out the default interface, instead of being sent through utun1.
Two questions:
Why doesn't the routing "just work" in this case? I expected that, after the NAT rules installed by the system are applied, the packets destined for 100.64.0.0/15 would be properly routed without the need for any custom rules.
What else should I try, either to gather more data or attempt to fix the routing?
I have a project with some legacy networking code that uses the Stream (formerly NSStream) family of classes, including Stream, InputStream, OutputStream, and StreamDelegate.
None of these are sendable, so I get a lot of warnings when implementing delegate methods in a @MainActor class.
These classes seem like they could be sendable. Is this something that will happen soon? Is it a bug I should report?
The networking code that uses these classes runs great, and hasn't needed changes for years, so my current solution is to just mark these unchecked:
extension Stream: @unchecked Sendable { }
extension InputStream: @unchecked Sendable { }
extension OutputStream: @unchecked Sendable { }
This makes the compiler happy, but makes me feel kind of bad. Is there something else I could do?
Hi,
I am trying to download multiple files in background (using multiple background urlsession). I initiate the download on click of a button and push the app to background where the download should happen.
I am getting the following error:
Error Domain=NSCocoaErrorDomain Code=4 "“CFNetworkDownload_EYp3BT.tmp” couldn’t be moved to “Documents” because either the former doesn’t exist, or the folder containing the latter doesn’t exist." UserInfo={NSSourceFilePathErrorKey=/private/var/mobile/Containers/Data/Application/85AEEB4F-1512-4C0C-8B04-C9C73634CC49/Library/Caches/com.apple.nsurlsessiond/Downloads/com.mycompany.DownloadMultipleFilesTestApp/CFNetworkDownload_EYp3BT.tmp, NSUserStringVariant=(\n Move\n), NSDestinationFilePath=/var/mobile/Containers/Data/Application/85AEEB4F-1512-4C0C-8B04-C9C73634CC49/Documents/file-441966.pdf, NSFilePath=/private/var/mobile/Containers/Data/Application/85AEEB4F-1512-4C0C-8B04-C9C73634CC49/Library/Caches/com.apple.nsurlsessiond/Downloads/com.mycompany.DownloadMultipleFilesTestApp/CFNetworkDownload_EYp3BT.tmp, NSUnderlyingError=0x28155f900 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
In my sample code attached here i am trying with 500 background urlsession (one download task per each url session)
I have implemented the required methods:
application(_:handleEventsForBackgroundURLSession:completionHandler)
and
urlSessionDidFinishEvents forBackgroundURLSession:)
I have found that the error happens because of two callbacks to
urlSession(_:downloadTask:didFinishDownloadingTo:)
where i move the file from temporary location to a location in my app's documents directory.
The first time the file is present at the location, but for the second callback (with same urlsession id, task id and location values) to urlSession(_:downloadTask:didFinishDownloadingTo:) the file isnt present there and so the move fails.
Can someone please explain this erratic behaviour ? Is this a known issue with URLSession ?
For a repro, you can use the code attached above, test on a physical device without running app from xcode ie launch the app from phone's home screen, click on the download button and send the app to background. Check logs in the console app on mac
Test environment:
iPhone 8plus with iOS 16.7.8
We're encountering an issue with our Network Extension (utilizing NEPacketTunnelProvider and NETransparentProxy) on macOS 14.5 (23F79).
On some systems, the VPN fails to automatically start after a reboot despite calling startVPNTunnel(). There are no error messages.
Our code attempts to start the tunnel:
.......
do {
try manager.connection.startVPNTunnel()
Logger.default("Started tunnel successfully")
} catch {
Logger.error("Failed to launch tunnel")
}
......
System log analysis reveals the tunnel stopping due to userLogout (NEProviderStopReason(rawValue: 12)) during reboot.
However, the Transparent Proxy stops due to userInitiated (NEProviderStopReason(rawValue: 1)) for the same reboot.
We need to understand:
Why the VPNTunnel isn't starting automatically.
Why the userLogout reason is triggered during reboot.
Additional Context:
We have manually started the VPN from System Settings before reboot.
This doesn't particularly surprise me, but I am curious about it, and whether we can change it: our TPP won't start if the only IP address available is in 169.254.0.0/16. I can see (from our logs) that the preferences are loaded & saved, and the extension is loaded, but until it gets a real address, the startProxy method is not invoked.
Hi,
I'm having headaches with the debugging of my Unwanted Communication Reporting extension.
iPhone log says:
com.apple.IdentityLookup.MessageFilter[1774] <Error>: Extension's containing app (appID <private>) unauthorized to defer requests to host <private>
So I guess I have something wrong with my apple-app-site-association.
The AASA file I get with swcutil dl -d services.mydomain.com
{
classificationreport = {
apps = (
"<MYTEAMID>.com.mydomain.myapp",
"<MYTEAMID>.com.mydomain.myapp.unwanted"
);
};
}
where .com.mydomain.myapp is my containing app (bundle id).
and .com.mydomain.myapp.unwanted is my extension
The AASA file on the server is obviously in JSON format and correctly served from the server : services.mydomain.com
In the extension Info.plist I've set the following :
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>ILClassificationExtensionNetworkReportDestination</key>
<string>https://services.mydomain.com/path/unwanted/report</string>
</dict>
<key>NSExtensionMainStoryboard</key>
<string>MainInterface</string>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.identitylookup.classification-ui</string>
</dict>
I suppose the reply from classificationResponse method is correct since MessageFilter "tries" to send the request.
Where am I mistakening ?
Difficult to debug... MessageFilter's log keeps interesting data as private (so there is no way to check what it's actually doing). And I've found no way to go deeper in the debug process.
Many thanks
Emmanuel
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