Hi
I'm building a React Native app and need to implement the functionality to connect/disconnect to a VPN using WireGuard configuration files (.conf).
I'm using Swift for the native integration on iOS. Does anyone know of any libraries or resources that could help with this?
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
Dear Apple Support Team,
I hope this message finds you well.
I am writing to seek clarification on a specific aspect of Wi-Fi connectivity related to the iPhone 16 series running iOS 18.0. We have encountered an issue where the iPhone 16 series devices fail to connect to Wi-Fi networks, and this failure subsequently affects other devices running iOS 18.0.
To better understand the root cause of this issue, I would like to inquire about the differences in the "authentication and encryption" processes between the iPhone 16 series running iOS 18.0 and other devices running iOS 18.0. Specifically, are there any changes or updates in the Wi-Fi authentication and encryption mechanisms that are unique to the iPhone 16 series?
Understanding these differences will greatly assist us in diagnosing and resolving the connectivity issues we are experiencing.
Thank you for your assistance. I look forward to your prompt response.
Best regards,
WJohn
iOS devices are failing to launch WebSheet (i.e. captive portal mini browser) when auto-join is used to connect to Hotspot 2.0 SSID with a captive portal. Logs captured from the device & RADIUS show that the device associates to the SSID, but does not launch the WebSheet due to the error, "Unable to launch WebSheet because this network has become captive". Afterwards the device may send an EAPOL Logoff request to the Access Point & disconnect from the network.
If manually selecting the SSID from Settings > Wi-Fi, then the same device will log It's a manual join so no further checks required, remain associated to the SSID & launch the captive portal browser which is able to load the captive browser.
info 17:28:35.298531-0500 configd device setup is completed
info 17:28:35.298566-0500 configd Unable to launch WebSheet because this network has become captive, blacklisting network [HS2_Captive_Test]
info 17:28:35.298604-0500 configd Removing FF981347-FDFA-45FD-82D9-88BA0426C0A3
default 17:28:35.298641-0500 configd __BUILTIN__: PresentUI result Temporary Failure (6)
default 17:28:35.298677-0500 configd CNPluginHandler en0: Failure (__BUILTIN__)
default 17:28:35.298716-0500 configd Temporarily disabling (blacklisting) HS2_Captive_Test
Websheet should only be launched when the device is captive. Why wouldWebSheet fail to launch when the device is captive?
We are checking for cellular mode using the code below.
When the code below is executed, is it correct to convey the status value of the actually connected cellular environment?
Sometimes HSDPA or WCDMA is output.
I would like to inquire under what conditions the value is output.
[Code]
func getCellularConnectionType() -> String {
if #available(iOS 14.1, *) {
if let radioAccessTechnology = networkInfo.serviceCurrentRadioAccessTechnology?.values.first {
Debug.log("Radio Access Technology: (radioAccessTechnology)")
switch radioAccessTechnology {
case CTRadioAccessTechnologyLTE:
return "LTE"
case CTRadioAccessTechnologyNRNSA:
return "5G-NSA"
case CTRadioAccessTechnologyNR:
return "5G-SA"
default:
return "ETC"
}
}
}
return "Cellular"
}
I developed a iOS App, this App need to visit a local url. It can visit the url on iPhone 13 (iOS 15.4) and iPhone 14 Plus (iOS 16.5.1), but it can not visit the same url on iPhone 6s(iOS 15.8.1).
The error message is 'NSURLErrorDomain Code=-1009'.
1). The url can be visited by Safari on iPhone 6s, so the network of iPhone 6s is fine.
2). The Local Network has enabled in the APP settings.
3). I notice that in iPhone Settings -> WLAN -> Apps Using WLAN & Cellular, my App information can be found on iPhone 13 and iPhone 14 Plus, and can not find my App information on iPhone 6s.
How should I troubleshoot this issue? Thanks you!
Follows are full error message.
2024-02-08 17:49:39.706240+0800 AstroeyeWiFi[1186:114419] Task .<8> finished with error [-1009] Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." UserInfo={_kCFStreamErrorCodeKey=50, NSUnderlyingError=0x280715c20 {Error Domain=kCFErrorDomainCFNetwork Code=-1009 "(null)" UserInfo={_NSURLErrorNWPathKey=unsatisfied (Denied over Wi-Fi interface), interface: en0, _kCFStreamErrorCodeKey=50, _kCFStreamErrorDomainKey=1}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask .<8>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask .<8>"
), NSLocalizedDescription=The Internet connection appears to be offline., NSErrorFailingURLStringKey=http://192.168.0.1:50628/form/getDeviceId, NSErrorFailingURLKey=http://192.168.0.1:50628/form/getDeviceId, _kCFStreamErrorDomainKey=1}
[DNO][getDeviceSysId][Error] underlying(Alamofire.AFError.sessionTaskFailed(error: Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." UserInfo={_kCFStreamErrorCodeKey=50, NSUnderlyingError=0x280715c20 {Error Domain=kCFErrorDomainCFNetwork Code=-1009 "(null)" UserInfo={_NSURLErrorNWPathKey=unsatisfied (Denied over Wi-Fi interface), interface: en0, _kCFStreamErrorCodeKey=50, _kCFStreamErrorDomainKey=1}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask .<8>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask .<8>"
), NSLocalizedDescription=The Internet connection appears to be offline., NSErrorFailingURLStringKey=http://192.168.0.1:50628/form/getDeviceId, NSErrorFailingURLKey=http://192.168.0.1:50628/form/getDeviceId, _kCFStreamErrorDomainKey=1}), nil)
In my case there are three interfaces. I had a mental model that I now believe is incorrect.
If any of the 3 interfaces is "satisfied", then I get one message telling me so. I guess if that one interface goes down, then I should get a second message that tells me that (this is hard to test as Xcode keeps disconnecting from my device when I switch to Settings to change things).
in my case, wifi and cellular are both on. I launch the app, get notified that wifi is satisfied, but nothing on cellular.
So my guess is there is a hierarchy: wired, wifi, and cellular. If the highest priority path is available, the others are assumed "off" since you have a path. Thus, you will never get "satisfied" for more than one path.
Correct?
We are trying to connect to Webdav.
The file server is in the same network.
So when we try to connect, the local network permission pop-up is displayed.
If the input information is incorrect in the first login attempt when this permission pop-up is displayed,
After that, even after fixing the normal connection, we cannot connect or log in with the message "NSURLErrorDomain Code=-1009", "Internet connection is offline."
This symptom seems to persist even after rebooting or deleting and deleting the app in the actual distributed app.
If you re-debug while debugging Xcode, you can connect normally.
(If you do not re-debug, it fails even if you enter the connection information normally.)
And it affects local connection, so you cannot connect to any local network server such as SMB or FTP.
Also, you cannot browse the server list within the local network. (SMB)
Is there a way to initialize the local network status within the app to improve this phenomenon?
I tried turning Airplane mode ON/OFF, turning Wi-Fi ON/OFF, and turning local network permissions ON/OFF, but it did not work.
Also, this phenomenon seems to be a Sandbox for each app.
When connecting to the same local server from an app installed on the same iPhone/iPad device, the above phenomenon does not occur if the first connection is successful.
** Summary **
If you fail to connect to a server on your local network,
then you will continue to fail to connect to the local server.
This happens even when local network permissions are allowed.
The error message is NSURLErrorDomain Code=-1009
The current device is an iPhone device running iOS 18.1.1.
Hi Team,
Looking for an answer, if it's just us or a widespread issue.
Since Sept, our clients Apple devices can't load a Captive Portal on Apple devices. Client wants the CNA to pop up and I can't get it to happen!
Android and Windows devices all work correctly with their respective popups, but CNA will not work.
No changes done on our side and after multiple tshoots and getting vendors to take multiple PCAPs found, Apple devices are not initiating a HTTP GET request as per Meraki >> https://documentation.meraki.com/MR/MR_Splash_Page/Splash_Page_Traffic_Flow_and_Troubleshooting
The work around is to force a HTTP GET request by manually going into the browser and initiate a http site (we tried 1.1.1.1, also tried other public HTTP sites and it works) and that redirects to our Captive Portal page.
Our company has a VPN client that we develop and it works on 14.x and it was working on 15.x but ever since I have upgraded to 15.1.1, I do not see any traffic being sent to the TUN interface even though I have it configured as the default route. Can anyone provide guidance or insight into what might have changed around the Network Extensions that could have caused this?
Unfortunately I cannot tell if this was happening on 15.0.1. Some things I have tried, to no avail, is disable the firewall and uninstalling/installing of the VPN client. I have no other filters installed that could be interfering. When I try and ping an address I should be able to reach, I get "no route to host"
I have also used Wireshark and have observed zero traffic going to the TUN interface.
NOTE, networking works fine when the VPN client is not connected.
Hi, all. We have a camera with only one WiFi module. It supports AP and STA modes coexisting, but the WiFi of AP and STA can only be in the same channel at the same time, that is, 2.4G or 5G. In the initial state, the App is connected to the camera through 5G WiFi, and the camera is in AP mode. When entering the network configuration mode, the camera will start the STA mode, and the AP and STA modes coexist. When the user selects 2.4G WiFi, the AP mode will switch from 5G to 2.4G. Android's WiFi and socket are not disconnected, iOS's socket will be disconnected 100%, and WiFi may be disconnected.
What is the reason for this? Is there any way to solve it?
I’ve encountered an issue with an app that includes a Local Push Connectivity extension. After a fresh install of the app, the Local Network Alert appears when calling NEAppPushManager.save(). The alert message is:
“This app would like to find and connect to devices on your local network. This app will be able to discover and connect to devices on the networks you use.”
Here is the relevant code:
` pushManager.providerConfiguration = NEAppPushManager.providerConfiguration(with: settings, system: system)
if settings.ssids.isEmpty {
fatalError("☠️ The PushManagerSettings.ssids should NEVER be empty!")
}
pushManager.matchSSIDs = !settings.ssids.isEmpty
? Array(settings.ssids)
: []
return pushManager.save()`
Questions:
1. Why does the Local Network Alert appear?
I suspect it is related to pushManager.matchSSIDs, which interacts with the local network to match specific SSIDs.
2. What happens if the user clicks “Don’t Allow”?
Based on my testing, everything seems to work fine even if the user denies the permission.
Would you happen to know why this is happening and if denying the alert could cause any issues down the line?
Topic:
App & System Services
SubTopic:
Networking
I have a command line app under active development in XCode. It is based on receiving multicast traffic and processing it. I generate this traffic with another app, and generally just leave it running.
When I do a build and run in XCode, I get a message asking me for Local Access. If I click yes, no network traffic will be received. I need to restart the command line tool multiple times until I get access.
I'm also getting a ton of repeated entries in my Setting->Privacy->Local Access.
If I configure xcode to launch with terminal, it does work, but that's not a great solution because of the external window (and the fact that I have terminal set "close if exit cleanly", so I lose my data. I can change that setting, but it is fairly inconvenient, and I don't get the console history in XCode.
Is there a way to allow my apps to run from xcode without the pop-up or with the delay in activating the network and creating new entries in the Settings?
Thanks!
Hi,
I've read a bunch of threads regarding the changes in Sonoma and later requiring Location permission for receiving SSIDs. However, as far as I can see, in Sequoia 15.1 SSIDs and BSSIDs are empty regardless.
In particular, this makes it not possible to use associate(withName:) and associate(withSSID:) because the network object returned by scanForNetwork(withSSID: "...") has its .ssid and .bssid set to nil.
Here is an example:
First we have a wrapper to call the code after the location permission is authorized:
import Foundation
import CoreLocation
class LocationDelegate: NSObject, CLLocationManagerDelegate {
var onAuthorized: (() -> Void)?
var onDenied: (() -> Void)?
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
let authStatus = manager.authorizationStatus
print("Location authorization status changed: \(authStatusToString(authStatus))")
if authStatus == .authorizedAlways {
onAuthorized?()
} else if authStatus == .denied || authStatus == .restricted {
onDenied?()
}
}
}
let locationManager = CLLocationManager()
let locationDelegate = LocationDelegate()
func authorizeLocation(onAuthorized: @escaping () -> Void, onDenied: @escaping () -> Void) {
let authStatus = locationManager.authorizationStatus
print("Location authorization status: \(authStatusToString(authStatus))")
if authStatus == .notDetermined {
print("Waiting for location authorization...")
locationDelegate.onAuthorized = onAuthorized
locationDelegate.onDenied = onDenied
locationManager.delegate = locationDelegate
locationManager.requestAlwaysAuthorization()
} else if authStatus == .authorizedAlways {
onAuthorized()
} else if authStatus == .denied || authStatus == .restricted {
onDenied()
}
RunLoop.main.run()
}
func authStatusToString(_ status: CLAuthorizationStatus) -> String {
switch status {
case .notDetermined:
return "Not Determined"
case .restricted:
return "Restricted"
case .denied:
return "Denied"
case .authorizedAlways:
return "Always Authorized"
case .authorizedWhenInUse:
return "Authorized When In Use"
@unknown default:
return "Unknown"
}
}
Then, a demo program itself:
import Foundation
import CoreWLAN
import Network
let client = CWWiFiClient.shared()
guard let interface = client.interface() else {
print("No wifi interface")
exit(1)
}
authorizeLocation(
onAuthorized: {
do {
print("Scanning for wifi networks...")
let scanResults = try interface.scanForNetworks(withSSID: nil)
let networks = scanResults.compactMap { network -> [String: Any]? in
return [
"ssid": network.ssid ?? "unknown",
"bssid": network.bssid ?? "unknown"
]
}
let jsonData = try JSONSerialization.data(withJSONObject: networks, options: .prettyPrinted)
if let jsonString = String(data: jsonData, encoding: .utf8) {
print(jsonString)
}
exit(0)
} catch {
print("Error: \(error)")
exit(1)
}
},
onDenied: {
print("Location access denied")
exit(1)
}
)
When launched, the program asks for permission, and after that, is shown as enabled in Privacy & Security Settings panel.
Here is the output where it can be seen that the scan is performed after location access was authorized, and regardless of that, all ssids are empty:
Location authorization status: Not Determined
Waiting for location authorization...
Location authorization status changed: Always Authorized
Scanning for wifi networks...
[
{
"ssid" : "unknown",
"bssid" : "unknown"
},
{
"ssid" : "unknown",
"bssid" : "unknown"
},
.... further omitted
Calling scanForNetworks() with explicitly specified network name does this as well, returns a CWNetwork object with .ssid / .bssid = nil.
I am setting up a fake VPN with proxy settings using NEPacketTunnelProvider. When I check proxy check sites, I can see the proxy is detected.
let settings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "10.0.0.1")
let proxySettings = NEProxySettings()
proxySettings.httpEnabled = true
proxySettings.httpsEnabled = true
proxySettings.httpServer = NEProxyServer(address: hostIP, port: portNumber)
proxySettings.httpsServer = NEProxyServer(address: hostIP2, port: portNumber2)
proxySettings.excludeSimpleHostnames = false
proxySettings.matchDomains = [""]
settings.proxySettings = proxySettings
How can I control whether other installed apps on the phone use or bypass this proxy? Can I do this with exceptionList? Since I am routing everything through a VPN, I assumed I could control this. The selection of which apps use the proxy should be up to the user.
Could you provide an explanation of how I can manage this? I am quite new to these types of tasks.
The content filtering functionality works perfectly when I install the app directly on my mobile device from Xcode. However, when the app is distributed via TestFlight, the app does not prompt users to save configurations, which causes the configuration-saving process to fail.
This app is meant for public use.
As per my understanding from TN3134, content filter apps can be shipped for devices running iOS 16 and later.
iOS app extension 9.0. supervised devices only
iOS app extension 15.0. apps using Screen Time API
iOS app extension 16.0. per app on managed devices
Topic:
App & System Services
SubTopic:
Networking
Hi,
I'm trying to set up automated backups on my machine using a combination of restic, a wrapper script, and a launchd agent, but I think I'm hitting a problem with the local network privacy dialogue.
Basically, the script sets up the environment variables for Restic, which then tries to backup to a local REST server. Problem is, when trying to do that, I get the following error:
Fatal: unable to open config file: Head "https://X:X@X.X.X.network:8000/X/X.X.X.network/config": dial tcp 192.168.50.229:8000: connect: no route to host
So it resolves DNS just fine, but can't connect to the local server. I tried a couple of things, tools such as ping work and can ping the local server, but nothing I do fixes the issue with restic itself. After reading about the network privacy feature, which I loved by the way, I believe it's the culprit here.
This is the .plist file I'm using, which lives in ~/Library/LaunchAgents/com.james.local-backup.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.james.local-backup</string>
<key>ProgramArguments</key>
<array>
<string>/Users/james/.local/bin/replicator</string>
<string>--backup</string>
<string>rest:https://X.X.X.network:8000/X/X.X.X.network</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/opt/homebrew/opt/coreutils/libexec/gnubin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
<key>XDG_CONFIG_HOME</key>
<string>/Users/james/.config</string>
</dict>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>13</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<key>StandardErrorPath</key>
<string>/tmp/com.user.backup.err</string>
<key>StandardOutPath</key>
<string>/tmp/com.user.backup.out</string>
<key>ProcessType</key>
<string>Background</string>
</dict>
</plist>
The local network dialogue never shows up, so I can't give the wrapper script or restic access to the local network, which I assume is why it can't connect to the local server.
Any way I can solve this? I could build a proper Swift CLI that calls restic, but I assume I'd hit the same issue. Plus, it seems overkill for my needs.
I'm attempting to use NWConnection as a websocket given a NWEndpoint returned by NWBrowser, setup like:
let tcpOptions = NWProtocolTCP.Options()
tcpOptions.enableKeepalive = true
tcpOptions.keepaliveIdle = 2
let parameters = NWParameters(tls: nil, tcp: tcpOptions)
parameters.allowLocalEndpointReuse = true
parameters.includePeerToPeer = true
let options = NWProtocolWebSocket.Options()
options.autoReplyPing = true
options.skipHandshake = true
parameters.defaultProtocolStack.applicationProtocols.insert(options, at: 0)
self.connection = NWConnection(to: endpoint, using: parameters)
The initial connection does make it to the ready state but when I first try to send a text message over the websocket, i get
nw_read_request_report [C1] Receive failed with error "Input/output error"
nw_flow_prepare_output_frames Failing the write requests [5: Input/output error]
nw_write_request_report [C1] Send failed with error "Input/output error"
immediately, and the websocket is closed.
Send code here:
let encoder = JSONEncoder()
let dataMessage = try encoder.encode(myMessage)
let messageMetadata = NWProtocolWebSocket.Metadata(opcode: .text)
let context = NWConnection.ContentContext(identifier: "send", metadata: [messageMetadata])
connection.send(content: dataMessage, contentContext: context, completion: .contentProcessed({ error in
if let error = error {
print (error)
}
}))
What would typically cause the Input/output error when writing? Am I doing something obviously wrong or is there something else I can do to get additional debug information?
Thanks in advance for any help.
When I was attempting to establish a TCP connection using NWConnection on a physical iPhone, the connection consistently fails with the error:
connection did change state, new: waiting(POSIXErrorCode(rawValue: 50): Network is down)
connection did change state, new: preparing
connection did change state, new: waiting(POSIXErrorCode(rawValue: 50): Network is down)
However, when running the same code in the iOS Simulator, the connection succeeds without issues.
I have already granted the app permission to access the local network by selecting "Allow [App Name] to find devices on the local network" when prompted.
The issue persists even after restarting the app, device, and server.
Additionally, I have configured the Info.plist file with the following keys:
NSAllowsLocalNetworking
NSLocalNetworkUsageDescription
Here is my code:
func start() -> NWConnection {
let myHost: NWEndpoint.Host = "192.168.1.154" // My MacBook
let myPort: NWEndpoint.Port = 1234
let connection = NWConnection(to: .hostPort(host: myHost, port: myPort), using: .tcp)
connection.stateUpdateHandler = { newState in
print("connection did change state, new: \(newState)")
}
connection.start(queue: .main)
return connection
}
Development environment:
Xcode 15.3
MacOS 14.4.1
Device OS: iOS 18.1
I used the SSH approach method in the post https://developer.apple.com/forums/thread/703234 to add TLS trust for the local accessory device with a self signed certificate.
In the Info.plist, I disabled App Transport Security for local networking by setting the NSAllowsLocalNetworking property, as mentioned in the post.
However, I am still encountering the following SSL error:
ATS failed system trust
Connection 3: system TLS Trust evaluation failed(-9802)
Connection 3: TLS Trust encountered error 3:-9802
Connection 3: encountered error(3:-9802)
Task <9432C2C5-C7A1-44E4-95CC-2AFA49D6C501>.<1> HTTP load failed, 0/0 bytes (error code: -1200 [3:-9802])
Task <9432C2C5-C7A1-44E4-95CC-2AFA49D6C501>.<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
In the code everything is working fine. The certificates are compared and
CFEqual(expected, actual), is returning true. Also in urlSession delegate method , the
return completionHandler(.useCredential, credential)
is returned.
When I disable ATS in Info.plist by setting NSAllowsArbitraryLoads, it works fine.
I have the following questions:
Should I disable ATS by setting NSAllowsArbitraryLoads along with setting ?
Instead of accepting the server certificate for the first time and saving it in the app, why can’t we embed the self-signed certificate in the app directly and use it for comparison?
Hi,
We have been granted the com.apple.managed.vpn.shared entitlement and are able to use it for builds/TestFlight builds. We can access the cert in a mobile config. and everything works fine.
However when we try to archive a build and distribute for App Store Connect it fails if the entitlement file contains this entry. If we take it out the upload succeeds but the app can't load the cert from the keychain.
The Distribution profile has the entry:
keychain-access-groups: [TEAM ID].*, com.apple.managed.vpn.shared
Is there an extra step for App Store Connect builds?
Thanks,
Dave