please consider this code:
[NEHotspotNetwork fetchCurrentWithCompletionHandler:^(NEHotspotNetwork *network) {
if (network) {
DebugLog(@"Network ssid: %@, bssid: %@", network.SSID, network.BSSID);
} else {
DebugLog(@"No available network");
}
}];
For me, I have a strange situation - say that the BSSID of my network is "01:34:56:78:90"
the string in the property is missing the first character! what is contains (and is printed) is "1:34:56:78:90" - the leading "0" is missing.
So, I was wondering if this is a know thing, or if perhaps it's only Asus (my router)? Or, am I doing something wrong?
Pointers would be much appreciated.
Network Extension
RSS for tagCustomize and extend the core networking features of iOS, iPad OS, and macOS using Network Extension.
Posts under Network Extension tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
We have an app that connects to an IoT device to configure it; we're connecting to an access point and we have inconsistent results with the iOS solution (we're using MAUI for both iOS and Android); the Android experience is consistently successful. We've narrowed the error in the logs to the following section - and the question is what do the error values mean? We can't quite figure out what is happening or why. Our guess is the SSID of the target network is getting set to null at some point, but that is only a guess. We've found only a couple of other similar issues at these posts, but no solution that is apparent https://developer.apple.com/forums/thread/690602
https://developer.apple.com/forums/thread/665011
https://developer.apple.com/forums/thread/665324
Can you see what we're missing?
Here is the log section we believe is the critical point and is what shows an error when there is a failure to connect:
09/25/2023 15:32:03.403 __WiFiDeviceManagerEvaluateAPEnvironment: no known BSS for this network. Learning environment.
09/25/2023 15:32:03.405 WiFiNetworkSetProperty: null network
09/25/2023 15:32:03.405 __WiFiDeviceManagerReleaseWakeAssertionForAutoJoin: PM assertion not held.
09/25/2023 15:32:03.405 __WiFiDeviceManagerUserForcedAssociationCallback: error -3936 reqInfo (null)
09/25/2023 15:32:03.406 __WiFiDeviceManagerUserForcedAssociationCallback: enabling device manager
09/25/2023 15:32:03.406 WiFiBatteryMgmt : -[WiFiBatteryManager requestPowerResource::]: Power resource request for AutoJoin added. Pending=1.
09/25/2023 15:32:03.406 -[WiFiBatteryManager isPowerResourceAvailable:]: WiFiBatteryMgmt : resource is unavailable for type AutoJoin. claimedResource is 0
09/25/2023 15:32:03.407 __WiFiDeviceManagerUserForcedAssociationCallback: failed forced association
09/25/2023 15:32:03.407 __WiFiDeviceManagerDispatchUserForcedAssociationCallback: result 2
09/25/2023 15:32:03.410 __WiFiDeviceManagerForcedAssociationCallback: failed to association error 2
09/25/2023 15:32:03.410 __GetNetworkWithSameSsid: network (null) not found
09/25/2023 15:32:03.410 __WiFiDeviceManagerForcedAssociationCallback: removing password for (null)
09/25/2023 15:32:03.410 WiFiSecurityRemovePassword: Removing password for (null)
09/25/2023 15:32:03.411 __WiFiSecurityRemovePassword: null account
09/25/2023 15:32:03.411 WiFiLocalizationGetLocalizedString: lang='English' key='WIFI_JOIN_NETWORK_FAILURE_TITLE' value='Unable to join the network
“%@”'
09/25/2023 15:32:03.412 WiFiLocalizationGetLocalizedString: lang='English' key='WIFI_FAILURE_OK' value='OK'
Hi,
We run a PacketTunnelProvider VPN on our macbooks. When we updated the Mac to MacOS Sonoma, we see strange behavior with regards to the Wi-Fi menu in system settings.
After we connect a VPN, the Wi-Fi switch gets blanked out, and it doesn't detect any other networks. This is in contrast to the wifi task-bar, where we can see it functioning normally. Wi-Fi and the VPN also function normally. Switching Wi-Fi networks does not work, and after, the Mac will not connect to any Wi-Fi networks until it restarts.
After disconnecting the VPN, this problem remains. The only way to fix this is to restart the Mac.
I've filed FB13205010.
I'm wondering if anyone has seen anything like this, because it makes having a VPN unusable on this version of macOS.
All of the following screenshots were taken at the same time.
We have a Developer Id signed VPN application using both NEPacketTunnelProvider and NEAppProxyProvider packaged as a single system extension.
The requirement is for the application to implement a full tunnel VPN (has default route 0.0.0.0 on the utun interface) with the exception of another specific Developer Id signed application which needs its connections to bypass the tunnel.
Originally, we attempted to use NETransparentProxyProvider to bypass the tunnel (for the single application) with the idea being to intercept the flows for the desired application in the transparent proxy and proxy these flows via a new NWConnection forced via the direct interface to bypass the tunnel. The problem we ran into was that the NEPacketTunnelProvider always get the packets before the NETranparentProxyProvider even though the proxy is started before the packet tunnel.
So next attempt was to use NEAppProxyProvider with an NEAppRule set to capture flows for the specific application of interest. The good news is we get the application flows prior to the packet tunnel but the problem is the NEAppRule only seems to work for App Store signed applications, for example Safari. For Developer Id signed applications (for example Chrome) flows are actually blocked when an NEAppRule is added to the proxy configuration. This seems like a bug to me. The system log will show some messages about the http flow being blocked by policy. For the Safari case, when the NEAppRule is added we can see socket redirect policies added (system log). In the Developer Id signed apps there appears to be an error when OS is checking the apps certificate.
What is the recommended way to implement our apps requirement? We have a full packet tunnel with the exception of a single, Developer Id signed, application.
On iOS we are trying to log energy use by our network extension to help us isolate troubled areas. task_info with TASK_POWER_INFO_V2 does return task_energy value and it's growing over time, but it's not clear what exactly it means and how it supposed to correlate to battery usage screen from iOS settings.
Does anybody know anything about this?
As I mentioned elsewhere, I am trying to add a packet filter to our app. I can load load the extension, but I am getting permission denied when I try to save the preferences with it.
I am building for release, using a Developer ID Application certificate (macOS, if that wasn't clear).
I am starting to worry that I can't do this except on an MDM-managed system.
We have a PacketTunnelProvider in a SystemExtension with split tunneling. We are configuring a private IP address range of 240.0.0.1/10 as included routes and specifying a few matching domains using NEPacketTunnelNetworkSettings.
Once TunnelNetworkSettings has been applied successfully, a new utunx interface is created, and it includes routes for the 240.0.0.1/10 IP range. In our case, the interface name is utun3, where 'x' represents an integer value.
According to our business logic, we need to establish connections with some IPs from this range. To achieve this, we are utilizing the NWConnection class API to create connections with IP addresses
Like this
func establishConnection() {
// Specify the destination host and port
let host = "240.0.0.19"
let port = 80
// Create an NWHostEndpoint
let endpoint = NWHostEndpoint(hostname: host, port: "\(port)")
// Create an NWConnection
let connection = NWConnection(to: endpoint, using: .tcp)
connection.start(queue: .global())
}
For the above code, we have observed different behaviour for IP packets when creating connections from different targets.
In the first case, when we create a connection to the IP address 240.0.0.19 from the Main app target using the provided code, the IP packets correctly go through the utun3 interface because this address falls within the 240.0.0/10 range, which is part of the included routes.
However, in the second case, when we use the same code to create a connection to 240.0.0.19 from the Extension target, the IP packets go through the primary interface en0 rather than the utun3 interface.
**Question : **
Why do we have different behaviour for the same code?
How can we achieve the same behaviour as the Main app target in the System Extension target?
--
Thanks
I had dealt with this in cmake, and then forgotten about it -- now trying my Xcode-only test project, and it won't work, because the profile has -systemextension as a suffix, while the one Xcode generates doesn't.
Am I missing something in how to get Xcode to deal with this?
I'm using this code to get the path of an executable from the audit token provided in NEFilterDataProvider.handleNewFlow(_:), forwarded from the Network Extension to the main app via IPC:
private func securePathFromAuditToken(_ auditToken: Data) throws -> String {
let secFlags = SecCSFlags()
var secCode: SecCode?
var status = SecCodeCopyGuestWithAttributes(nil, [kSecGuestAttributeAudit: auditToken] as CFDictionary, secFlags, &secCode)
guard let secCode = secCode else {
throw NSError(domain: NSOSStatusErrorDomain, code: Int(status))
}
var secStaticCode: SecStaticCode?
status = SecCodeCopyStaticCode(secCode, secFlags, &secStaticCode)
guard let secStaticCode = secStaticCode else {
throw NSError(domain: NSOSStatusErrorDomain, code: Int(status))
}
var url: CFURL?
status = SecCodeCopyPath(secStaticCode, secFlags, &url)
guard let url = url as URL? else {
throw NSError(domain: NSOSStatusErrorDomain, code: Int(status))
}
return url.path
}
This code sometimes returns paths like /System/Library/PrivateFrameworks/HelpData.framework/Versions/A/Resources/helpd or /Library/Developer/CoreSimulator/Volumes/iOS_21A328/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 17.0.simruntime/Contents/Resources/RuntimeRoot/usr/libexec/mobileassetd.
But sometimes the SecCodeCopyGuestWithAttributes fails with status 100001 which is defined in MacErrors.h as kPOSIXErrorEPERM = 100001, /* Operation not permitted */. In these cases I resort to this code, which I have read is not as secure:
private func insecurePathFromAuditToken(_ auditToken: Data) throws -> String? {
if auditToken.count == MemoryLayout<audit_token_t>.size {
let pid = auditToken.withUnsafeBytes { buffer in
audit_token_to_pid(buffer.baseAddress!.assumingMemoryBound(to: audit_token_t.self).pointee)
}
let pathbuf = UnsafeMutablePointer<Int8>.allocate(capacity: Int(PROC_PIDPATHINFO_SIZE))
defer {
pathbuf.deallocate()
}
let ret = proc_pidpath(pid, pathbuf, UInt32(PROC_PIDPATHINFO_SIZE))
if ret <= 0 {
throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno))
}
return String(cString: pathbuf)
}
return nil
}
This insecure code then returns paths like /usr/libexec/trustd, /usr/libexec/rapportd, /usr/libexec/nsurlsessiond and /usr/libexec/timed.
From what I can see, SecCodeCopyGuestWithAttributes fails for all processes in /usr/libexec. Some of these processes have executables with the same name placed in another directory, like /Library/Developer/CoreSimulator/Volumes/iOS_21A328/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 17.0.simruntime/Contents/Resources/RuntimeRoot/usr/libexec/mobileassetd for which it succeeds, while for /usr/libexec/mobileassetd it fails.
Occasionally, both the secure and the insecure methods fail and in these cases the secure one returns status code 100003, which is defined as kPOSIXErrorESRCH = 100003, /* No such process */. When can this happen?
This seems to happen with both NEFilterFlow.sourceAppAuditToken and sourceProcessAuditToken. What is the problem?
We applied months ago for the NEAppPushProvider entitlement to do air gapped push notifications. The enterprise SA's we work with have been pushing the issue internally—but nothing has happened.
How do you actually get entitlements added to your profile? I could see a week time, but 3 or so months now is a bit crazy.
We have an Enterprise Apple developer account “Cisco System, Inc. “STBU” - JBF29L28EJ”. We use it to make in-house distribution for QE testing. I found that development provisioning profile in this account includes new “relay” capability in the entitlement, but in-house distribution provisioning profile doesn’t have it.
Below is the entitlement list in in-house distribution provisioning profile that doesn't include "relay":
Entitlements
&lt;dict&gt;
&lt;key&gt;com.apple.developer.networking.networkextension&lt;/key&gt;
&lt;array&gt;
&lt;string&gt;app-proxy-provider&lt;/string&gt;
&lt;string&gt;content-filter-provider&lt;/string&gt;
&lt;string&gt;packet-tunnel-provider&lt;/string&gt;
&lt;string&gt;dns-proxy&lt;/string&gt;
&lt;string&gt;dns-settings&lt;/string&gt;
&lt;/array&gt;
&lt;key&gt;aps-environment&lt;/key&gt;
&lt;string&gt;production&lt;/string&gt;
We now cannot make in-house distribution build without this entitlement.
I'm using a Distribution-ready Family Controls Entitlement and it seems like I'm unable to save Content Filter configurations in my individual-use Screen Time app when I download a production build from TestFlight. For development builds, everything works fine.
From nehelper:
slowdown trying to create a content filter configuration through an app. Creating a content filter configuration is only allowed through profile in production version of slowdown.
From the app:
Failed to save configuration Slowdown: Error Domain=NEConfigurationErrorDomain Code=10 "permission denied" UserInfo={NSLocalizedDescription=permission denied}
-[NEFilterManager saveToPreferencesWithCompletionHandler:]_block_invoke_3: failed to save the new configuration: Error Domain=NEFilterErrorDomain Code=5 "permission denied" UserInfo={NSLocalizedDescription=permission denied}
TN3134 seems to suggest that Content Filters are allowed for Screen Time apps
Platform: iOS, Packaged as: app extension, Minimum OS: 15.0, Restrictions: Screen Time apps
TN3120 suggest the same:
There are two ways to deploy a content filter on iOS. In a managed environment, use MDM to deploy a content filter to supervised devices. In an unmanaged environment, deploy your content filter as part of a Screen Time app.
These technotes lead me to assume that this should be a supported use case. Any idea how to progress from here?
I cannot find in the documentation if using NEFilterDataProvider.apply(_:) has any advantage over manually inspecting incoming flows in handleNewFlow(_:) other than being a shortcut. Or are those rules guaranteed to be applied even if the network extension crashes or similar? If it has no practical advantages, then manually inspecting each flow allows to set up more flexible dynamic rules.
We are currently testing the idea of using an iPhone instead of a Raspberry Pi for our IoT project. We are part of the Apple Enterprise program, and the app is intended for internal use within the company. The only challenge we've encountered while porting the software to iOS is that there isn't an obvious way to switch between WiFi networks in unattended mode.
Is there a way to switch between WiFi networks without requiring manual confirmation from the user? Does MDM or the Apple Enterprise program enable this feature?
Our desired outcome is:
To be able to scan nearby WiFi networks and connect to any of them programmatically using the SSID and password.
Thank you.
We're seeing nessionmanager problems caused by having a configuration present on the system which.
Has includeAllNetworks set in the protocol
Was previously connected & then disconnected
After VPN disconnection we sometimes see that DNS and other things are not working. The VPN extension is no longer running, so I'd expect that settings would have been cleaned up, but they aren't in some cases.
The system won't recover on its own, and when we delete the VPN configuration we see a set of messages from VPN session manager. There are two I've seen, on different systems. One shows the utun interface being cleaned up, and various network settings being removed.
The other refers to deregistering an Enterprise VPN Session, [NESMVPNSession unsetDefaultDropAll], and IP Drop-All disabled.
In both of these cases the cleanup is being done hours after the session was disconnected and the extension unloaded from memory.
Does anyone know what exactly is happening there, and why the OS isn't cleaning up on disconnect?
Hey,
I need the information about the access-points/devices of the connected Wifi network, I repeat only of the **connected Wifi network **
My use caes is about the indoor positioning of a user connect the network and for that I need the information of all the access points (e.g. ssid, bssid, rssi etc.) but till now I am unable to find any starting point/solution for this.
Any help regarding this will be highly appreciated.
Regards,
Aqeel Ahmed
I need to get all devices names which are connected to same wifi.
I tried NetServiceBrowser, in netServiceBrowser(_ browser: NetServiceBrowser, didFind service: NetService, moreComing: Bool) function I get some devices name like Macbook or iPad with search service type of browser.searchForServices(ofType: "_services._dns-sd._udp.", inDomain: "local.") But in this service type I cant get iPhones.
I'm not sure if this is the right way, which framework should I use to accomplish this? Am I on the right track? What permits do I need to get?
I need your help. Best regards.
I am trying to set includeAllNetworks flags right now and I see some wield behaviors from macOS system:
default 13:32:50.825941+0800 ***** <debug> newStatus = Connecting...
default 13:32:51.816353+0800 ***** <debug> newStatus = Disconnected
default 13:32:52.222371+0800 ***** <debug> newStatus = Connected
The app which is observing VPN status gets notified with disconnected status between connecting and connected. And in some cases I find that app will never gets connected notification after disconnected. In that case tunnel interface and all tunnel network settings are well set. But our UI logic will just handle the disconnected case.
If I just clear the includeAllNetwork flag, then everything is fine.
default 14:13:50.075947+0800 *****<debug> newStatus = Connecting...
default 14:13:50.829195+0800 *****<debug> newStatus = Connected
The test environment is macOS 14.0 and I am using network extension framework for the status KVO.
So I am just wondering if this is expected behavior or not. If this is expected, then is there any suggestion that I should use to work around it?
Hi,
AFAIK Safari or any macOS apps which uses WKWebview, uses com.apple.WebKit.Networking.xpc to do actual networking.
I am working on a packet tunnel, where I am able to get process id associated with packet read. Based on process id, i am using libproc to get process name.
I am facing below problem:
For Safari or any other apps which uses WKWebview having same process name: com.apple.WebKit.Networking
Any ways to distinguish wether it is from safari or other xyz wkwebview apps?
Related Problem: https://developer.apple.com/forums/thread/693528 In this thread, app proxy can help but in packet tunnel no such options exposed.
I'm setting up an app that will need to intercept all traffic on the device. Configuration is:
let manager = NETunnelProviderManager()
let protocolConfiguration = NETunnelProviderProtocol()
protocolConfiguration.providerBundleIdentifier = "com.***.PacketTunnelProvider"
protocolConfiguration.serverAddress = "VPN Server"
protocolConfiguration.providerConfiguration = ["key": "value"]
manager.protocolConfiguration = protocolConfiguration
manager.localizedDescription = "VPN Server"
The configuration is correctly saved but in the settings, the profile comes out with "Update required" and "must be updated by the developer before VPN Server can be connected"
Looking around the forums, I already checked the entitlements on the binary and everything comes out good:
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>app-proxy-provider</string>
<string>packet-tunnel-provider</string>
</array>
on the main bundle and
[Key] com.apple.developer.networking.networkextension
[Value]
[Array]
[String] app-proxy-provider
[String] packet-tunnel-provider
on packettunnelprovider.appex
When I try to start the tunnel with
func startProxyServer() {
NETunnelProviderManager.loadAllFromPreferences { (managers, error) in
if let error = error {
print("Error loading preferences: \(error)")
return
}
let manager = managers?.first(where: { $0.localizedDescription == "VPN Server" })
manager!.loadFromPreferences { error in
if let error = error {
print("Error loading preferences: \(error)")
} else {
do {
try manager!.connection.startVPNTunnel(options: nil)
print("Started tunnel.")
} catch {
print("Failed to start tunnel: \(error)")
}
}
}
}
putting a breakpoint will show that the profile gets loaded but it lacks completely the protocol configuration. Funnily enough, I don't get an error so I get to the "Started tunnel" code branch. Of course without the protocol configuration, even if the manager is "loaded" and connection.startVPNtunnel is called, the packettunnelprovider is never initialized and nothing actually starts.
Build targets are the same on both the main app and the packet tunnel provider target, and I tried lowering or raising them to no effect.
How to further debug this?