General:
TN3151 Choosing the right networking API
Networking Overview document — Despite the fact that this is in the archive, this is still really useful.
TLS for App Developers DevForums post
Choosing a Network Debugging Tool documentation
WWDC 2019 Session 712 Advances in Networking, Part 1 — This explains the concept of constrained networking, which is Apple’s preferred solution to questions like How do I check whether I’m on Wi-Fi?
TN3135 Low-level networking on watchOS
Adapt to changing network conditions tech talk
Foundation networking:
DevForums tags: Foundation, CFNetwork
URL Loading System documentation — NSURLSession, or URLSession in Swift, is the recommended API for HTTP[S] on Apple platforms.
Network framework:
DevForums tag: Network
Network framework documentation — Network framework is the recommended API for TCP, UDP, and QUIC on Apple platforms.
Network Extension (including Wi-Fi on iOS):
See Network Extension Resources
Wi-Fi Fundamentals
Wi-Fi on macOS:
DevForums tag: Core WLAN
Core WLAN framework documentation
Wi-Fi Fundamentals
Secure networking:
DevForums tags: Security
Apple Platform Security support document
Preventing Insecure Network Connections documentation — This is all about App Transport Security (ATS).
Available trusted root certificates for Apple operating systems support article
Requirements for trusted certificates in iOS 13 and macOS 10.15 support article
About upcoming limits on trusted certificates support article
Apple’s Certificate Transparency policy support article
Technote 2232 HTTPS Server Trust Evaluation
Technote 2326 Creating Certificates for TLS Testing
QA1948 HTTPS and Test Servers
Miscellaneous:
More network-related DevForums tags: 5G, QUIC, Bonjour
On FTP DevForums post
Using the Multicast Networking Additional Capability DevForums post
Investigating Network Latency Problems DevForums post
Local Network Privacy FAQ DevForums post
Extra-ordinary Networking DevForums post
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Network
RSS for tagNetwork connections send and receive data using transport and security protocols.
Posts under Network tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
I'm developing in Swift and working on parsing DNS queries. I'm considering using dns_parse_packet, but I noticed that dns_util is deprecated (although it still seems to work in my limited testing).
As far as I know, there isn’t a built-in replacement for this. Is that correct?
On a related note, are there any libraries available for parsing TLS packets—specifically the ClientHello message to extract the Server Name Indication (SNI)—instead of relying on my own implementation?
Related to this post.
Hi, I’ve encountered an issue with Safari’s behavior when Prevent Cross-Site Tracking is enabled in iOS, related to DNS filtering via an implemented NEDNSProxyProvider. Here’s a step-by-step breakdown:
In Safari, when attempting to query a blocked domain (according to the filtering policy of the NEDNSProxyProvider), the page is blocked as expected.
Closing Safari without closing the tab with the blocked domain.
Reopening Safari – Expected result: The page remains blocked; Actual result: The page loads and bypasses the NEDNSProxyProvider (no logs are received for this flow).
Tapping the refresh button causes the page to be blocked, as the DNS Proxy Provider intercepts the new request.
Note: This issue is only reproducible in general tabs in Safari. In private tabs, a fresh DNS query is generated each time, and the blocking behavior works as expected. I also tested Google Chrome, where the domain is blocked consistently.
I attempted to filter this issue via Content Filter, but the only connection received by NEFilterDataProvider is for com.apple.Safari.SearchHelper with ssl.gstatic.com.
Could you advise on how to handle this behaviour? Would be grateful to hear any ideas
Hello Everyone,
I'm currently working on a cross-platform application that uses IP-based multicast for device discovery across both Apple and non-Apple devices running the same app. All devices join a multicast group "X.X.X.X" on port Y.
For Apple devices, I am using NWConnectionGroup for multicast discovery, while for non-Apple devices, I am using BSD sockets.
The issue arises when I attempt to send a multicast message to the group using NWConnectionGroup. The message is sent from a separate ephemeral port rather than the multicast port Y. As a result, all Apple processes that are using NWConnectionGroup can successfully receive the multicast message. However, the processes running on the non-Apple devices (using BSD sockets) do not receive the message.
My Questions:
Is there a way to configure NWConnectionGroup to send multicast messages from the same multicast port Y rather than an ephemeral port?
Is there any known behavior or limitation in how NWConnectionGroup handles multicast that could explain why non-Apple devices using BSD sockets cannot receive the message?
How can I ensure cross-platform multicast compatibility between Apple devices using NWConnectionGroup and non-Apple devices using BSD sockets?
Any guidance or suggestions would be greatly appreciated!
Thanks,
Harshal
Hello,
I’m encountering a problem with WebSocket connections in Safari on iOS 18.1 and later when initiated from an iframe. The same implementation works perfectly in other browsers like Chrome but fails in Safari.
In Safari, the WebSocket connection fails with error message
"WebSocket connection to 'wss://MY_CONNECTION_URL' failed: The internet connection appears to be offline."
Has anyone else faced this? Is this a known limitation or bug in Safari? Any workarounds or solutions would be greatly appreciated.
Thank you!
Hello Everyone,
I’m working on a project that involves multicast communication between processes running on different devices within the same network. For all my Apple devices (macOS, iOS, etc.), I am using NWConnectionGroup, which listens on a multicast address "XX.XX.XX.XX" and a specific multicast port.
The issue occurs when a requestor (such as a non-Apple process) sends a multicast request, and the server, which is a process running on an Apple device using NWConnectionGroup (the responder), attempts to reply. The problem is that the response is sent from a different ephemeral port rather than the port on which the multicast request was received.
If the client is behind a firewall that blocks unsolicited traffic, the firewall only allows incoming packets on the same multicast port used for the initial request. Since the multicast response is sent from a different ephemeral port, the firewall blocks this response, preventing the requestor from receiving it.
Questions:
Is there a recommended approach within the NWConnectionGroup or Network.framework to ensure that responses to multicast requests are sent from the same port used for the request?
Are there any best practices for handling multicast responses in scenarios where the requestor is behind a restrictive firewall?
Any insights or suggestions on how to account for this behavior and ensure reliable multicast communication in such environments would be greatly appreciated.
Thanks,
Harshal
I am writing an app using Microsoft's MAUI platform. I am posting this here because that team wants me to make an xcode project to help determine an issue I am having.
My MAUI app sends a broadcast packet on a UDP socket using address 255.255.255.255. This worked fine in iOS version 17.x. After upgrading my phone to iOS 18.x it stopped working.
The error I get is "no route to host".
The exact same code works fine on MacOS. It does not work on iPadOs 18.
My question here is 3 fold:
Did something specific change between iOS 17 and 18 that would cause a 'no route to host' error when sending a UDP broadcast packet?
Can someone provide sample code to show me how to do this type of broadcast using Swift in Xcode for iOS?
I read an article that said my app would need the com.apple.developer.networking.multicast entitlement in order to use boradcast functionality. This was introduced in iOS 14. Why did my app work fine in iOS 17 then? Is this what changed? Did this requirement use to be optional and is now required? I did get this entitlement from Apple and applied it to my provisioning profile and my app gave the same "no route to host" error. Why?
Hi everyone,
is there any ways we can remove the weak ciphers as part of TLS handshake (TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256)
I checked here but still do not see anyways to print out and change the ciphers suite we want to use
https://forums.developer.apple.com/forums/thread/43230
https://forums.developer.apple.com/forums/thread/700406?answerId=706382022#706382022
I'm trying to detect the state of Local Network privacy on macOS Sequoia via NWBrowser, as recommended in https://developer.apple.com/documentation/technotes/tn3179-understanding-local-network-privacy
Regardless of the state of Local Network privacy - undetermined, allowed or denied, NWBrowser receives an update indicating that its in the ready state.
Scanning does not seem to trigger the Local Network privacy alert for me - I have to use the other recommended method to trigger the prompt. Enabling or disabling Local Network privacy does not seem to send any updates for NWBrowser.
https://developer.apple.com/forums/thread/666431 seems related, and implies that they did receive further updates to NWBrowser.
Filed as FB16077972
Hello everyone,
We have a use case where we need to disable the sending and receiving of fragmented packets on the network while using NWConnection.
However, even after setting the disableFragmentation flag to true, the connection still sends fragmented packets.We’ve tried setting the flag as follows, but the packets are still being fragmented:
var connection : NWConnection
var udp_options : NWProtocolUDP.Optionsudp_options = NWProtocolUDP.Options()
var connection_parameters = NWParameters(dtls: nil, udp: udp_options)
let ip_options = connection_parameters.defaultProtocolStack.internetProtocol! as! NWProtocolIP.Options
ip_options.disableFragmentation = true
connection = NWConnection (host: "XX.XX.XX.***", port: NWEndpoint.Port(25000), using: connection_parameters)
The issue we are encountering is that even though we’ve set disableFragmentation to true on the sender, the receiver still receives fragmented UDP packets. This can be observed using Wireshark, where we are sending a 10k byte data from the sender and receiving the fragmented datagram packets on the receiver end while both the devices are on the same WiFi network. Additionally, Wireshark shows that the packet has the "DF" bit set to '0', indicating that fragmentation is allowed.
What is exactly expected from the disableFragmentation flag? Are we misunderstanding how this flag works? Or is there something else we should be doing to ensure that fragmentation is completely disabled?
Looking forward to your insights!
Hello everyone,
I have a question regarding the behavior of network listeners in my application. Here's the scenario I'm seeing:
When I open a .v6 listener, it accepts both IPv4 and IPv6 traffic. However, when I run the netstat -tln command, the socket is shown as udp6.
When I open a NWListener with the IP version set to .any, I receive both IPv4 and IPv6 traffic on the listener. In this case, running netstat -tln shows a udp46 socket.
My understanding is that if I create a socket with .v6, it should only accept IPv6 connections, not both IPv4 and IPv6. However, the .v6 listener appears to be accepting both types of traffic, which is causing some confusion.
Additionally, I am seeking to understand the difference between a udp6 socket and a udp46 socket, and also the difference between sockets created using .v6 and .any. What exactly does udp46 represent, and how is it different from udp6 in terms of accepting traffic?
Is this expected behavior, or is there something I am missing in how the listeners are set up?
Looking forward to hearing your insights!
Hi,
We have an issue (https://github.com/actions/runner-images/issues/10924) raised by a user requesting to add 'local network access' permission for macOS 15 and macOS 15-arm64 image runners. Apple introduced a new LNP policy with macOS Sequoia that is not controlled by TCC or MDM. Could you please guide us on how to add 'local network access' permission for macOS 15 and macOS 15-arm64 image runners?
Thanks.
Hi, I am working on a banking app and as per compliance, we have to detect whether the sim is present in the device when using the App or not, also it has to be the same sim which is used when registering with the App/Bank. Currently I dont find any way to detect this. The CTCarrier is depricated and all methods I check returns dummy value and not useful
I'm working with an app that was developed with the CocoaAsyncSocket library, which uses <sys/socket.h> style socket programming. We have a customer where certain features are not working if iOS "adapts" to v3 IGMP but seems to work if v2 IGMP is used.
I can't say I understand all the low level aspects and am trying to inform myself. I've been searching online to find out about socket and IGMP but don't see anything coming up.
Is there a way to force iOS to use IGMP v2 for broadcast? Our company also makes a hardware communicator and their code forces v2 and we've been asked to see if we can do the same.
Thanks for any leads on where to go to inform myself. more or code snippets on how to do this.
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.
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.
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?
I am trying to create an app that lets the user send Wake On LAN calls to computers in the local network. I created a small package that uses BSD sockets (https://github.com/pultar/WakeOnLAN/blob/main/Sources/CWakeOnLAN/wol.c) to send the magic packet. For now, I select "en0" manually as the interface.
The app works in the simulator but fails on a real device. I also noticed that I can test the package when I only use the terminal and Swift Package Manager but not from a CLI within XCode. In either case, I observe:
"No route to host"
Following previous post in the forum (see below), I figured I require the multicast entitlement, which I was granted and could add in the Xcode project settings and on Apple Developer together with my App Bundle ID.
However, even after activating the entitlement for my app, I observe the same error.
I'm attempting to build an app the broadcasts on the local network and awaits responses to those broadcast requests. However, the app does not receive the responses. Essentially, the app broadcasts "DISCOVER:1000" to 10.11.21.255, and expects "ADDRESS:10.11.21.100", but never receives it. I built a test client in python, and it works as expected. Running tcpdump on the server shows the response being sent by the server. It just never reaches the ios app.
In case it matters, I have the multicast entitlement for the app and local network enabled in Info.plist.
import Foundation
import Network
class UDPClient: ObservableObject {
private var connection: NWConnection?
private let networkQueue = DispatchQueue(label: "com.example.udp")
@Published var isReady = false
private var isListening = false
func connect() {
let host = "10.11.21.255"
let port = UInt16(12345)
let endpoint = NWEndpoint.hostPort(host: NWEndpoint.Host(host), port: NWEndpoint.Port(integerLiteral: port))
connection = NWConnection(to: endpoint, using: .udp)
connection?.stateUpdateHandler = { [weak self] state in
switch state {
case .ready:
self?.networkQueue.async {
print("Connection ready")
self?.startReceiving()
DispatchQueue.main.async {
self?.isReady = true
}
}
case .failed(let error):
print("Connection failed: \(error)")
DispatchQueue.main.async {
self?.isReady = false
}
case .waiting(let error):
print("Connection waiting: \(error)")
DispatchQueue.main.async {
self?.isReady = false
}
default:
DispatchQueue.main.async {
self?.isReady = false
}
break
}
}
connection?.start(queue: networkQueue)
}
func send() {
let message = "DISCOVER:1000"
guard let data = message.data(using: .utf8) else {
print("Failed to convert message to data")
return
}
guard let connection = self.connection else {
return
}
networkQueue.async { [weak self] in
print("Attempting to send message...")
guard let self = self else { return }
if self.isReady {
// Ensure we're listening before sending
if !self.isListening {
self.startReceiving()
// Add a small delay to ensure the receiver is ready
self.networkQueue.asyncAfter(deadline: .now() + 0.1) {
self.performSend(data: data, connection: connection)
}
} else {
self.performSend(data: data, connection: connection)
}
} else {
print("Connection is not ready. Retrying in 100ms...")
self.networkQueue.asyncAfter(deadline: .now() + 0.1) {
self.send()
}
}
}
}
private func performSend(data: Data, connection: NWConnection) {
connection.send(content: data, completion: .contentProcessed { error in
if let error = error {
print("Failed to send: \(error)")
} else {
print("Send completed successfully")
}
})
}
private func startReceiving() {
print("Starting to receive messages...")
isListening = true
connection?.receiveMessage { [weak self] content, context, isComplete, error in
guard let self = self else { return }
if let error = error {
print("Receive error: \(error)")
return
}
if let data = content {
print("Received data: \(data)")
if let responseString = String(data: data, encoding: .utf8) {
print("Received response: \(responseString)")
} else {
print("Received data could not be converted to string.")
}
} else {
print("No data received.")
}
// Continue receiving
self.startReceiving()
}
}
func disconnect() {
networkQueue.async { [weak self] in
self?.connection?.cancel()
self?.isListening = false
DispatchQueue.main.async {
self?.isReady = false
}
print("Disconnected")
}
}
}
My main view:
import SwiftUI
struct ContentView: View {
@StateObject private var udpClient = UDPClient()
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
}
.padding()
.onAppear() {
udpClient.connect()
udpClient.send()
}
}
}
#Preview {
ContentView()
}