Networking

RSS for tag

Explore the networking protocols and technologies used by the device to connect to Wi-Fi networks, Bluetooth devices, and cellular data services.

Networking Documentation

Post

Replies

Boosts

Views

Activity

TLS for App Developers
Transport Layer Security (TLS) is the most important security protocol on the Internet today. Most notably, TLS puts the S into HTTPS, adding security to the otherwise insecure HTTP protocol. IMPORTANT TLS is the successor to the Secure Sockets Layer (SSL) protocol. SSL is no longer considered secure and it’s now rarely used in practice, although many folks still say SSL when they mean TLS. TLS is a complex protocol. Much of that complexity is hidden from app developers but there are places where it’s important to understand specific details of the protocol in order to meet your requirements. This post explains the fundamentals of TLS, concentrating on the issues that most often confuse app developers. Note If you’re working on TLS in the local environment, for example, to talk to a Wi-Fi based accessory, see TLS For Accessory Developers. Server Certificates For standard TLS to work the server must have a digital identity, that is, the combination of a certificate and the private key matching the public key embedded in that certificate. TLS Crypto Magic™ ensures that: The client gets a copy of the server’s certificate. The client knows that the server holds the private key matching the public key in that certificate. In a typical TLS handshake the server passes the client a list of certificates, where item 0 is the server’s certificate (the leaf certificate), item N is (optionally) the certificate of the certificate authority that ultimately issued that certificate (the root certificate), and items 1 through N-1 are any intermediate certificates required to build a cryptographic chain of trust from 0 to N. Note The cryptographic chain of trust is established by means of digital signatures. Certificate X in the chain is issued by certificate X+1. The owner of certificate X+1 uses their private key to digitally sign certificate X. The client verifies this signature using the public key embedded in certificate X+1. Eventually this chain terminates in a trusted anchor, that is, a certificate that the client trusts by default. Typically this anchor is a self-signed root certificate from a certificate authority. Note Item N is optional for reasons I’ll explain below. Also, the list of intermediate certificates may be empty (in the case where the root certificate directly issued the leaf certificate) but that’s uncommon for servers in the real world. Once the client gets the server’s certificate, it evaluates trust on that certificate to confirm that it’s talking to the right server. There are three levels of trust evaluation here: Basic X.509 trust evaluation checks that there’s a cryptographic chain of trust from the leaf through the intermediates to a trusted root certificate. The client has a set of trusted root certificates built in (these are from well-known certificate authorities, or CAs), and a site admin can add more via a configuration profile. This step also checks that none of the certificates have expired, and various other more technical criteria (like the Basic Constraints extension). Note This explains why the server does not have to include the root certificate in the list of certificates it passes to the client; the client has to have the root certificate installed if trust evaluation is to succeed. In addition, TLS trust evaluation (per RFC 2818) checks that the DNS name that you connected to matches the DNS name in the certificate. Specifically, the DNS name must be listed in the Subject Alternative Name extension. Note The Subject Alternative Name extension can also contain IP addresses, although that’s a much less well-trodden path. Also, historically it was common to accept DNS names in the Common Name element of the Subject but that is no longer the case on Apple platforms. App Transport Security (ATS) adds its own security checks. Basic X.509 and TLS trust evaluation are done for all TLS connections. ATS is only done on TLS connections made by URLSession and things layered on top URLSession (like WKWebView). In many situations you can override trust evaluation; for details, see Technote 2232 HTTPS Server Trust Evaluation). Such overrides can either tighten or loosen security. For example: You might tighten security by checking that the server certificate was issued by a specific CA. That way, if someone manages to convince a poorly-managed CA to issue them a certificate for your server, you can detect that and fail. You might loosen security by adding your own CA’s root certificate as a trusted anchor. IMPORTANT If you rely on loosened security you have to disable ATS. If you leave ATS enabled, it requires that the default server trust evaluation succeeds regardless of any customisations you do. Mutual TLS The previous section discusses server trust evaluation, which is required for all standard TLS connections. That process describes how the client decides whether to trust the server. Mutual TLS (mTLS) is the opposite of that, that is, it’s the process by which the server decides whether to trust the client. Note mTLS is commonly called client certificate authentication. I avoid that term because of the ongoing confusion between certificates and digital identities. While it’s true that, in mTLS, the server authenticates the client certificate, to set this up on the client you need a digital identity, not a certificate. mTLS authentication is optional. The server must request a certificate from the client and the client may choose to supply one or not (although if the server requests a certificate and the client doesn’t supply one it’s likely that the server will then fail the connection). At the TLS protocol level this works much like it does with the server certificate. For the client to provide this certificate it must apply a digital identity, known as the client identity, to the connection. TLS Crypto Magic™ assures the server that, if it gets a certificate from the client, the client holds the private key associated with that certificate. Where things diverge is in trust evaluation. Trust evaluation of the client certificate is done on the server, and the server uses its own rules to decided whether to trust a specific client certificate. For example: Some servers do basic X.509 trust evaluation and then check that the chain of trust leads to one specific root certificate; that is, a client is trusted if it holds a digital identity whose certificate was issued by a specific CA. Some servers just check the certificate against a list of known trusted client certificates. When the client sends its certificate to the server it actually sends a list of certificates, much as I’ve described above for the server’s certificates. In many cases the client only needs to send item 0, that is, its leaf certificate. That’s because: The server already has the intermediate certificates required to build a chain of trust from that leaf to its root. There’s no point sending the root, as I discussed above in the context of server trust evaluation. However, there are no hard and fast rules here; the server does its client trust evaluation using its own internal logic, and it’s possible that this logic might require the client to present intermediates, or indeed present the root certificate even though it’s typically redundant. If you have problems with this, you’ll have to ask the folks running the server to explain its requirements. Note If you need to send additional certificates to the server, pass them to the certificates parameter of the method you use to create your URLCredential (typically init(identity:certificates:persistence:)). One thing that bears repeating is that trust evaluation of the client certificate is done on the server, not the client. The client doesn’t care whether the client certificate is trusted or not. Rather, it simply passes that certificate the server and it’s up to the server to make that decision. When a server requests a certificate from the client, it may supply a list of acceptable certificate authorities [1]. Safari uses this to filter the list of client identities it presents to the user. If you are building an HTTPS server and find that Safari doesn’t show the expected client identity, make sure you have this configured correctly. If you’re building an iOS app and want to implement a filter like Safari’s, get this list using: The distinguishedNames property, if you’re using URLSession The sec_protocol_metadata_access_distinguished_names routine, if you’re using Network framework [1] See the certificate_authorities field in Section 7.4.4 of RFC 5246, and equivalent features in other TLS versions. Self-Signed Certificates Self-signed certificates are an ongoing source of problems with TLS. There’s only one unequivocally correct place to use a self-signed certificate: the trusted anchor provided by a certificate authority. One place where a self-signed certificate might make sense is in a local environment, that is, securing a connection between peers without any centralised infrastructure. However, depending on the specific circumstances there may be a better option. TLS For Accessory Developers discusses this topic in detail. Finally, it’s common for folks to use self-signed certificates for testing. I’m not a fan of that approach. Rather, I recommend the approach described in QA1948 HTTPS and Test Servers. For advice on how to set that up using just your Mac, see TN2326 Creating Certificates for TLS Testing. TLS Standards RFC 6101 The Secure Sockets Layer (SSL) Protocol Version 3.0 (historic) RFC 2246 The TLS Protocol Version 1.0 RFC 4346 The Transport Layer Security (TLS) Protocol Version 1.1 RFC 5246 The Transport Layer Security (TLS) Protocol Version 1.2 RFC 8446 The Transport Layer Security (TLS) Protocol Version 1.3 RFC 4347 Datagram Transport Layer Security RFC 6347 Datagram Transport Layer Security Version 1.2 RFC 9147 The Datagram Transport Layer Security (DTLS) Protocol Version 1.3 Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Revision History: 2024-03-19 Adopted the term mutual TLS in preference to client certificate authentication throughout, because the latter feeds into the ongoing certificate versus digital identity confusion. Defined the term client identity. Added the Self-Signed Certificates section. Made other minor editorial changes. 2023-02-28 Added an explanation mTLS acceptable certificate authorities. 2022-12-02 Added links to the DTLS RFCs. 2022-08-24 Added links to the TLS RFCs. Made other minor editorial changes. 2022-06-03 Added a link to TLS For Accessory Developers. 2021-02-26 Fixed the formatting. Clarified that ATS only applies to URLSession. Minor editorial changes. 2020-04-17 Updated the discussion of Subject Alternative Name to account for changes in the 2019 OS releases. Minor editorial updates. 2018-10-29 Minor editorial updates. 2016-11-11 First posted.
0
0
7.2k
Nov ’16
Packet Tunnel Provider - sleep
I've implemented a VPN app with Packet Tunnel Provider for MacOS and iOS.I have two questions regarding the Extension's sleep/wake functions:1. If the VPN configuration is set with disconnectOnSleep = false, and at the extension I'm sending keep-alives every X seconds, What would happen when the device enters sleep mode? Will it keep sending keep-alive (because the VPN is configured with disconnectOnSleep=false) ?2. If the VPN configuration is set with disconnectOnSleep = true, and also isOnDemandEnabled = true. When the device enters sleep mode, do I need to disconnect the VPN myself? Or the OS would take care of it? And if I should disconnect it myself, the on-demand won't try to turn it on again (because the on-demand) ?
4
1
4.9k
Jan ’18
Join Wi-Fi Network from QR Code
I was wondering if anybody knows if it's possible for an app to use a QR code to join a Wi-Fi network - the same functionality as the iOS 11 Camera app?I have some code reading a QR Code that looks something like - "WIFI:S:name-of-network;T:WPA;P:password;;"This QR code works perfectly in the native camera app - asking the user if they'd like to join the Wi-Fi network and successfully joining if they do.When I scan the QR code in my own code, I get the following error: canOpenURL: failed for URL: "WIFI:S:name-of-network;T:WPA;P:password;;" - error: "The operation couldn’t be completed. (OSStatus error -10814.)"In my app, I've got URL Schemes for "prefs" and have added "wifi" in LSApplicationQueriesSchemes.Am I doing something wrong, or is this simply not possible?If it's not possible, is there anyway to use the iOS native camera functionality within an app?
7
0
28k
Feb ’18
On FTP
Questions about FTP crop up from time-to-time here on DevForums. In most cases I write a general “don’t use FTP” response, but I don’t have time to go into all the details. I’ve created this post as a place to collect all of those details, so I can reference them in other threads. IMPORTANT Apple’s official position on FTP is: All our FTP APIs have been deprecated, and you should avoid using deprecated APIs. Apple has been slowly removing FTP support from the user-facing parts of our system. The most recent example of this is that we removed the ftp command-line tool in macOS 10.13. You should avoid the FTP protocol and look to adopt more modern alternatives. The rest of this post is an informational explanation of the overall FTP picture. This post is locked so I can keep it focused. If you have questions or comments, please do create a new thread with the Network tag and I’ll respond there. Don’t Use FTP FTP is a very old and very crufty protocol. Certain things that seem obvious to us now — like being able to create a GUI client that reliably shows a directory listing in a platform-independent manner — are not possible to do in FTP. However, by far the biggest problem with FTP is that it provides no security [1]. Specifically, the FTP protocol: Provides no on-the-wire privacy, so anyone can see the data you transfer Provides no client-authenticates-server authentication, so you have no idea whether you’re talking to the right server Provides no data integrity, allowing an attacker to munge your data in transit Transfers user names and passwords in the clear Using FTP for anonymous downloads may be acceptable (see the note below) but most other uses of FTP are completely inappropriate for the modern Internet. IMPORTANT You should only use FTP for anonymous downloads if you have an independent way to check the integrity of the data you’ve downloaded. For example, if you’re downloading a software update, you could use code signing to check its integrity. If you don’t check the integrity of the data you’ve downloaded, an attacker could substitute a malicious download instead. This would be especially bad in, say, the software update case. These fundamental problems with the FTP protocol mean that it’s not a priority for Apple. This is reflected in the available APIs, which is the subject of the next section. FTP APIs Apple provides two FTP APIs: All Apple platforms provide FTP downloads via NSURLSession Most Apple platforms (everything except watchOS) support CFFTPStream, which allows for directory listings, downloads, uploads, and directory creation. All of these FTP APIs are now deprecated: NSURLSession was deprecated for the purposes of FTP in the 2022 SDKs (macOS 13, {i{,Pad},tv}OS 16, watchOS 9) [2]. CFFTPStream was deprecated in the 2016 SDKs (macOS 10.11, {i{,Pad},tv}OS 9). CFFTPStream still works about as well as it ever did, which is not particularly well. Specifically: There is at least one known crashing bug (r. 35745763), albeit one that occurs quite infrequently. There are clear implementation limitations — like the fact that CFFTPCreateParsedResourceListing assumes a MacRoman text encoding (r. 7420589) — that will not be fixed. If you’re looking for an example of how to use these APIs, check out SimpleFTPSample. Note This sample has not been updated since 2013 and is unlikely to ever be updated given Apple’s position on FTP. The FTP support in NSURLSession has significant limitations: NSURLSession only supports FTP downloads; there is no support for uploads or any other FTP operations NSURLSession does not support resumable FTP downloads [3] NSURLSession background sessions only support HTTP and HTTPS, so you can’t run FTP downloads in the background on iOS If Apple’s FTP APIs are insufficient for your needs, you’ll need to write or acquire your own FTP library. Before you do that, however, consider switching to an alternative protocol. After all, if you’re going to go to the trouble of importing a large FTP library into your code base, you might as well import a library for a better protocol. The next section discusses some options in this space. Alternative Protocols There are numerous better alternatives to FTP: HTTPS is by far the best alternative to FTP, offering good security, good APIs on Apple platforms, good server support, and good network compatibility. Implementing traditional FTP operations over HTTPS can be a bit tricky. One possible way forward is to enable DAV extensions on the server. FTPS is FTP over TLS (aka SSL). While FTPS adds security to the protocol, which is very important, it still inherits many of FTP’s other problems. Personally I try to avoid this protocol. SFTP is a file transfer protocol that’s completely unrelated to FTP. It runs over SSH, making it a great alternative in many of the ad hoc setups that traditionally use FTP. Apple does not have an API for either FTPS or SFTP, although on macOS you may be able to make some headway by invoking the sftp command-line tool. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" [1] In another thread someone asked me about FTP’s other problems, those not related to security, so let’s talk about that. One of FTP’s implicit design goals was to provide cross-platform support that exposes the target platform. You can think of FTP as being kinda like telnet. When you telnet from Unix to VMS, it doesn’t aim to abstract away VMS commands, so that you can type Unix commands at the VMS prompt. Rather, you’re expected to run VMS commands. FTP is (a bit) like that. This choice made sense back when the FTP protocol was invented. Folks were expecting to use FTP via a command-line client, so there was a human in the loop. If they ran a command and it produced VMS-like output, that was fine because they knew that they were FTPing into a VMS machine. However, most users today are using GUI clients, and this design choice makes it very hard to create a general GUI client for FTP. Let’s consider the simple problem of getting the contents of a directory. When you send an FTP LIST command, the server would historically run the platform native directory list command and pipe the results back to you. To create a GUI client you have to parse that data to extract the file names. Doing that is a serious challenge. Indeed, just the first step, working out the text encoding, is a challenge. Many FTP servers use UTF-8, but some use ISO-Latin-1, some use other standard encodings, some use Windows code pages, and so on. I say “historically” above because there have been various efforts to standardise this stuff, both in the RFCs and in individual server implementations. However, if you’re building a general client you can’t rely on these efforts. After all, the reason why folks continue to use FTP is because of it widespread support. [2] To quote the macOS 13 Ventura Release Notes: FTP is deprecated for URLSession and related APIs. Please adopt modern secure networking protocols such as HTTPS. (92623659) [3] Although you can implement resumable downloads using the lower-level CFFTPStream API, courtesy of the kCFStreamPropertyFTPFileTransferOffset property. Revision History 2024-04-15 Added a footnote about FTP’s other problems. Made other minor editorial changes. 2022-08-09 Noted that the FTP support in NSURLSession is now deprecated. Made other minor editorial changes. 2021-04-06 Fixed the formatting. Fixed some links. 2018-02-23 First posted.
0
0
5.1k
Feb ’18
Battery statistical issue for Packet Tunnel Provider
Hi guys,I'm developing a custom VPN client with NEPacketTunnelProvider which tunnels all device traffic. All is going well so far but I've noticed that iOS battery statistics (Settings -> Battery) is claiming that our client has consumed a significant amount of energy (10%~30%). I though it was true for a while, but then I conducted some basic testing which suggested this is more likely a statistical issue.I set up my device (rebooted with clean battery cosumption statistics) with ~80% battery capacity and started to watch "NASA Live" channel in Youtube app with 1080p60 quality, for 3 hours, and taking notes every hour. I cross referenced the data of the same scenario (same device as well) collected with our custom VPN provider enabled and disabled. I made sure when the VPN client is enabled, I can actually see the Youtube traffic tunneled. Actually the video feed can generate ~1GiB traffic per hour pretty stably. I can provide detailed numbers if necessary, but generally, after 3 hours, both scenarios showed an overal of ~50% battery consumption (from the battery indicator on the status bar on top of the phone screen), there was no significant difference in the battery consumption. However when I looked at the statistics in Settings -> Battery, the scenario without our VPN client was showing 100% battery consumption from Youtube app (which is expected), and the scenario with VPN was showing 68% for Youtube, and 32% for our VPN client app!32% battery consumption in statistics is scaring. But what confuses me is that the actual device battery consumption didn't increase. My theory is that without the VPN client, individual apps are sending out their traffic on their own so the battery consumption are calculated on their head. But now with our VPN client, we are actually sending out traffic for every applications so iOS will blame us for that part of energy consumption. I'm not sure if the theory is true but it certainly explains the behavior.I'm wondering if Apple can look at the issue at if proved to be a statistical issue then fix it. Because 10%+ battery consumption on our app would be enough to scare away our customers. We can explain to them there is no actual extra energy consumption but customers will be suspicious. Whenever they feel their phone's having a shortened battery life they'll come to see the list and they will blame us.Thanks in advance!
12
0
2.7k
Mar ’18
iOS 12 VPN "Update Required"
Hi Guys,we have developed an VPN application for iOS 10, that basically just installs a VPN profile (developed using NETunnelProviderManager) that sets a special DNS for evey request to block malicious websites system-wide, that's it.Out can worked great under iOS 10 and even under iOS 11. But since updating the OS of the device to iOS 12, there is a "Update required" directly on the VPN profile:My question now is, did anybody else faced that problem?Because we already updated XCode, compiled the app for Deployment Target iOS 12, updated the application through the App Store, we already talked to the Apple Supported, that saif we should try using the develop forums so, can anybody htell us WHAT we should update to get rid off this message? The VPN profile itself still works, meaning the malicious websites still get blocked. But the label "Update Required" should vanish, but what should we do?Kind Regards,Mario
10
1
8.8k
Oct ’18
Get Process ID (pid) from NEFilterFlow & sourceAppAuditToken
Dear all,In macOS Catalina we have the new NetworkExtension framework that can filter network trafic on a computer.In my usecase I need the PID of the process that is the originator of the network flow. I'm aware that PID are not a reliable way to identify a process (since PIDs can be reused), but in my usecase only PID can identify what I need.In handleNewFlow(_ flow: NEFilterFlow) we can get the sourceAppAuditToken (flow.sourceAppAuditToken), where sourceAppAuditToken is a Data type. Is there a way to convert this sourceAppAuditToken to a PID value?I'm also aware of getting the signature of the process (eventually the Bundle ID) with SecCodeCopySigningInformation / kSecCSDynamicInformation, but again in my usecase it does not help.A way to do this is to call "netstat" and look for the local port in the output and get the PID from there, but sometimes this is not very reliable.Any ideas how to do this?Regards,Alex
9
1
5.0k
Dec ’19
Triggering the Local Network Privacy Alert
IMPORTANT The approach used by this code no longer works. See TN3179 Understanding local network privacy for a replacement. Currently there is no way to explicitly trigger the local network privacy alert (r. 69157424). However, you can bring it up implicitly by sending dummy traffic to a local network address. The code below shows one way to do this. It finds all IPv4 and IPv6 addresses associated with broadcast-capable network interfaces and sends a UDP datagram to each one. This should trigger the local network privacy alert, assuming the alert hasn’t already been displayed for your app. Oh, and if Objective-C is more your style, use this code instead. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@apple.com" import Foundation /// Does a best effort attempt to trigger the local network privacy alert. /// /// It works by sending a UDP datagram to the discard service (port 9) of every /// IP address associated with a broadcast-capable interface. This should /// trigger the local network privacy alert, assuming the alert hasn’t already /// been displayed for this app. /// /// This code takes a ‘best effort’. It handles errors by ignoring them. As /// such, there’s guarantee that it’ll actually trigger the alert. /// /// - note: iOS devices don’t actually run the discard service. I’m using it /// here because I need a port to send the UDP datagram to and port 9 is /// always going to be safe (either the discard service is running, in which /// case it will discard the datagram, or it’s not, in which case the TCP/IP /// stack will discard it). /// /// There should be a proper API for this (r. 69157424). /// /// For more background on this, see [Triggering the Local Network Privacy Alert](https://developer.apple.com/forums/thread/663768). func triggerLocalNetworkPrivacyAlert() { let sock4 = socket(AF_INET, SOCK_DGRAM, 0) guard sock4 >= 0 else { return } defer { close(sock4) } let sock6 = socket(AF_INET6, SOCK_DGRAM, 0) guard sock6 >= 0 else { return } defer { close(sock6) } let addresses = addressesOfDiscardServiceOnBroadcastCapableInterfaces() var message = [UInt8]("!".utf8) for address in addresses { address.withUnsafeBytes { buf in let sa = buf.baseAddress!.assumingMemoryBound(to: sockaddr.self) let saLen = socklen_t(buf.count) let sock = sa.pointee.sa_family == AF_INET ? sock4 : sock6 _ = sendto(sock, &message, message.count, MSG_DONTWAIT, sa, saLen) } } } /// Returns the addresses of the discard service (port 9) on every /// broadcast-capable interface. /// /// Each array entry is contains either a `sockaddr_in` or `sockaddr_in6`. private func addressesOfDiscardServiceOnBroadcastCapableInterfaces() -> [Data] { var addrList: UnsafeMutablePointer<ifaddrs>? = nil let err = getifaddrs(&addrList) guard err == 0, let start = addrList else { return [] } defer { freeifaddrs(start) } return sequence(first: start, next: { $0.pointee.ifa_next }) .compactMap { i -> Data? in guard (i.pointee.ifa_flags & UInt32(bitPattern: IFF_BROADCAST)) != 0, let sa = i.pointee.ifa_addr else { return nil } var result = Data(UnsafeRawBufferPointer(start: sa, count: Int(sa.pointee.sa_len))) switch CInt(sa.pointee.sa_family) { case AF_INET: result.withUnsafeMutableBytes { buf in let sin = buf.baseAddress!.assumingMemoryBound(to: sockaddr_in.self) sin.pointee.sin_port = UInt16(9).bigEndian } case AF_INET6: result.withUnsafeMutableBytes { buf in let sin6 = buf.baseAddress!.assumingMemoryBound(to: sockaddr_in6.self) sin6.pointee.sin6_port = UInt16(9).bigEndian } default: return nil } return result } }
0
0
7.3k
Oct ’20
Local Network Privacy FAQ
IMPORTANT This FAQ has been replaced by TN3179 Understanding local network privacy. I’m leaving this post in place as a historical curiosity, but please consult the technote going forward. I regularly get asked questions about local network privacy. This is my attempt to collect together the answers for the benefit of all. Before you delve into the details, familiarise yourself with the basics by watching WWDC 2020 Session 10110 Support local network privacy in your app. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Local Network Privacy FAQ With local network privacy, any app that wants to interact with devices on your network must ask for permission the first time that it attempts that access. Local network privacy is implemented on iOS, iPadOS, visionOS, and macOS. It’s not implemented on other platforms, most notably tvOS. IMPORTANT macOS 15 (currently in beta) introduced local network privacy support to the Mac. WWDC 2024 Session 10123 What’s new in privacy is the official announcement. This works much like it does on iOS, but there are some subtle differences. I’ll update this FAQ as I gain more experience with this change. Some common questions about local network privacy are: FAQ-1 What is a local network? FAQ-2 What operations require local network access? FAQ-3 What operations require the multicast entitlement? FAQ-4 Do I need the multicast entitlement? FAQ-5 I’ve been granted the multicast entitlement; how do I enable it? FAQ-6 Can App Clips access the local network? FAQ-7 How does local network privacy work with app extensions? FAQ-8 How do I explicitly trigger the local network privacy alert? FAQ-9 How do I tell whether I’ve been granted local network access? FAQ-10 How do I use the unsatisfied reason property? FAQ-11 Do I need a local network usage description property? FAQ-12 Can I test on the simulator? FAQ-13 Once my app has displayed the local network privacy alert, how can I reset its state so that it shows again? FAQ-14 How do I map my Multipeer Connectivity service type to an entry in the Bonjour services property? FAQ-15 My app presents the local network privacy alert unexpectedly. Is there a way to track down the cause? FAQ-16 On a small fraction of devices my app fails to present the local network privacy alert. What’s going on? FAQ-17 Why does local network privacy get confused when I install two variants of my app? FAQ-18 Can my app trigger the local network privacy alert when the device is on WWAN? Revision History 2024-10-31 Added a link to this FAQ’s replacement, TN3179 Understanding local network privacy. 2024-07-22 Added a callout explaining that local network privacy is now an issue on macOS. 2023-10-31 Fixed a bug in the top-level FAQ that mistakenly removed some recent changes. Added FAQ-18. 2023-10-19 Added a preamble to clarify that local network privacy is only relevant on specific platforms. 2023-09-14 Added FAQ-17. 2023-08-29 Added FAQ-16. 2023-03-13 Added connecting a UDP socket to FAQ-2. 2022-10-04 Added screen shots to FAQ-11. 2022-09-22 Fixed the pointer from FAQ-9 to FAQ-10. 2022-09-19 Updated FAQ-3 to cover iOS 16 changes. Made other minor editorial changes. 2020-11-12 Made a minor tweak to FAQ-9. 2020-10-17 Added FAQ-15. Added a second suggestion to FAQ-13. 2020-10-16 First posted.
0
0
19k
Oct ’20
Local Network Privacy FAQ-2
This post is part of the Local Network Privacy FAQ. What operations require local network access? The general rule is that outgoing traffic to a local network address requires that the user grant your app local network access. Common scenarios include: Making an outgoing TCP connection — yes Listening for and accepting incoming TCP connections — no Sending a UDP unicast — yes Sending a UDP multicast — yes Sending a UDP broadcast — yes Connecting a UDP socket — yes Receiving an incoming UDP unicast — no Receiving an incoming UDP multicast — yes Receiving an incoming UDP broadcast — yes These TCP and UDP checks are done at the lowest levels of the system and thus apply to all networking APIs. This includes Network framework, BSD Sockets, NSStream, and NSURLSession, and any other protocols that you layer on top of those. IMPORTANT Receiving an incoming UDP multicast or broadcast does not currently require local network access but, because we hope to change that in a future update, our advice right now is that you write your code as if did (r. 69792887, 70017649). Resolving link-local DNS names (those ending with local, per RFC 6762) requires local network access. Again, this check applies to a wide variety of APIs including <dns_sd.h>, <net_db.h>, Network framework, NSStream, and NSURLSession. Finally, all Bonjour operations require local network access: Registering a service with Bonjour — yes Browsing for Bonjour services — yes Resolving a Bonjour service — yes Again, these checks apply to all APIs that use Bonjour, including <dns_sd.h>, Network framework, NSNetService, and Multipeer Connectivity. Note You must declare the Bonjour service types you use in your Info.plist. See FAQ-14 How do I map my Multipeer Connectivity service type to an entry in the Bonjour services property? for details. Bonjour-based services where you don’t see any details of the network do not require local network access. These include: AirPlay — no Printing via UIKit — no Back to the FAQ
0
0
6.9k
Oct ’20
Bonjour for discovering a specific device's ip
Hi, I'm new to swift programming and right now writing an app for esp8266-controlled lamp device. My lamp is broadcasting it's own IP through bonjour. So all I want is to discover any lamps in my network (http.tcp) and to read name and value. Is there any example of such implementation? All I found so far is old or a lit bit complicated for such simple question. Thanks in advance!
26
0
14k
Feb ’21
NESMVPNSession disconnected
Hi, I have a problem with my OpenVPN connection on my app with iOS 14.4. I perform my VPN configuration from an oven file, with a NETunnelProviderManager protocol, but when I perform the startVPNTunnel, it starts connecting and immediately disconnects. The error I see in the logs is the following: NESMVPNSession[Primary Tunnel:OpenVPN Client: -----(null)]: status changed to disconnected, last stop reason Plugin was disabled This happens to me when running my app on a physical iPad. Regards import NetworkExtension import OpenVPNAdapter class VPNConnection {          var connectionStatus = "Disconnected"              var myProviderManager: NETunnelProviderManager?          func manageConnectionChanges( manager:NETunnelProviderManager ) - String {         NSLog("Waiting for changes");         var status = "Disconnected"                  NotificationCenter.default.addObserver(forName: NSNotification.Name.NEVPNStatusDidChange, object: manager.connection, queue: OperationQueue.main, using: { notification in                          let baseText = "VPN Status is "                          switch manager.connection.status {             case .connected:                 status = "Connected"             case .connecting:                 status = "Connecting"             case .disconnected:                 status = "Disconnected"             case .disconnecting:                 status = "Disconnecting"             case .invalid:                 status = "Invalid"             case .reasserting:                 status = "Reasserting"             default:                 status = "Connected"             }                          self.connectionStatus = status                          NSLog(baseText+status)                      });         return status     }          func createProtocolConfiguration() - NETunnelProviderProtocol {         guard             let configurationFileURL = Bundle.main.url(forResource: "app-vpn", withExtension: "ovpn"),             let configurationFileContent = try? Data(contentsOf: configurationFileURL)         else {             fatalError()         }                  let tunnelProtocol = NETunnelProviderProtocol()         tunnelProtocol.serverAddress = ""         tunnelProtocol.providerBundleIdentifier = "com.app.ios"                  tunnelProtocol.providerConfiguration = ["ovpn": String(data: configurationFileContent, encoding: .utf8)! as Any]         tunnelProtocol.disconnectOnSleep = false                  return tunnelProtocol     }          func startConnection(completion:@escaping () - Void){         self.myProviderManager?.loadFromPreferences(completionHandler: { (error) in             guard error == nil else {                 // Handle an occurred error                 return             }                          do {                 try self.myProviderManager?.connection.startVPNTunnel()                 print("Tunnel started")             } catch {                 fatalError()             }         })     }          func loadProviderManager(completion:@escaping () - Void) {                           NETunnelProviderManager.loadAllFromPreferences { (managers, error) in             guard error == nil else {                 fatalError()                 return             }                          self.myProviderManager = managers?.first ?? NETunnelProviderManager()             self.manageConnectionChanges(manager: self.myProviderManager!)                          self.myProviderManager?.loadFromPreferences(completionHandler: { (error) in                 guard error == nil else {                     fatalError()                     return                 }                                  let tunnelProtocol = self.createProtocolConfiguration()                                  self.myProviderManager?.protocolConfiguration = tunnelProtocol                 self.myProviderManager?.localizedDescription = "OpenVPN Client Ubic"                                  self.myProviderManager?.isEnabled = true                                  self.myProviderManager?.isOnDemandEnabled = false                                  self.myProviderManager?.saveToPreferences(completionHandler: { (error) in                     if error != nil  {                         // Handle an occurred error                         fatalError()                     }                     self.startConnection {                         print("VPN loaded")                     }                 })             })         }     } }
14
0
2.9k
Feb ’21
URLSession.uploadTask withFile When can file be deleted
Since I am uploading in the background, I need to save the request body off in a file. The documentation says this gets copied to a temporary storage area and uploaded from there. When can I delete the temporary file I generated? Deleting it just after the call to session.uploadTask(with: request, fromFile: filePath) seems to be a race condition where I will occasionally get a sharing violation deleting the file. Do I have to keep my temporary file around until DidCompleteWithError or DidReceiveData is called? I ask because I'm uploading an existing photo, so I have to generate a multi-part form file with the photo embedded, then iOS makes a copy of that file. This results in having the photo in storage on the device three times. We are uploading photos from an Event so there will be several hundred, so Im worried about device storage running out. Todd
5
0
1.3k
Dec ’21
UpdateApplicationContext not working simulator
I am having problems on Xcode13.3.1, Monterey 12.2.1, Apple M1 Max. Sending an UpdateApplicationContext update from a paired iPhone simulator is not received on the paired Apple Watch Simulator in the didRecieveApplicationContext. However, sendMessage from the apple watch simulator does update the iphone simulator app properly. It is however, not possible to send anything from the paired iPhone simulator to the paired Apple Watch Simulator. When working with actual devices everything works properly with WatchConnectivity with passing information back and forth via updateapplicationcontext and sendmessage calls. Can anyone confirm this is a bug or if there is something wrong with my setup?
2
0
1.6k
Apr ’22
Start An NEPacketTunnelProvider Fail
My App is a VPN APP, use [com.apple.networkextension.packet-tunnel] extension app to provider a VPN service. A problem puzzled me for a long time: Sometimes the VPN doesn't start successfully, until the user restart the iOS System or reinstall my APP. The detail is : The user use the app normally for many times, and suddenly can't start the vpn service, the APP log show API "startVPNTunnelWithOptions" call success, and return success. but the VPN extension status(NEVPNStatus) change from Disconnect to Connecting and then nothing happen, the VPN process not started, and not any log of the VPN extension created, my VPN log is start from the init function of the class inherit from PacketTunnelProvider, so can see that the vpn process not started. My NETunnelProviderProtocol is : NETunnelProviderProtocol *tunnel = [[NETunnelProviderProtocol alloc] init]; tunnel.providerBundleIdentifier = kTunBundleId; tunnel.serverAddress = @""; tunnel.disconnectOnSleep = NO; [self.providerManager setEnabled:YES]; [self.providerManager setProtocolConfiguration:tunnel]; self.providerManager.localizedDescription = kAppName; very simple, because my app use openvpn3 to provide the vpn service,so no need to set the serverAddress. Because when this problem happened, I can't get any useful log (because APP can't get the iOS system log), so this is a really trouble for me. Could any body help !
5
0
1.7k
Aug ’22
NWListener, P2P and awdl interfaces
I'm attempting to create a service that: Listens on iOS device A using NWListener Broadcasts the NWService ( using NWListener(service:using:)) ) on Bonjour Allows a separate device, iOS device B, to receive information about that service via an NWBrowser Connect to that service using the information contained in NWBrowser.Result 's NWEndpoint I've been able to successfully do this using a SwiftNIO service, in the following environments: iOS device A and iOS device B are physical iOS devices on the same WiFi network. This works. iOS device A and iOS device B are iOS simulators on the same machine. This works. iOS device A is a physical device, and iOS device B is a simulator. iOS device A is not connected to a WiFi network, iOS device B is connected to a WiFi network. This works. However, when iOS device A and iOS device B are physical devices that are not connected to a WiFi network, I encounter the following behavior: The Bonjour service is correctly advertised, and iOS device A and iOS device B are able to observe the advertisement of the service. In both cases, iOS device A and iOS device B, while able to resolve an NWEndpoint for the Bonjour service, are not able to connect to each other, and the connection attempt hangs. My setup for the listener side of things looks roughly like: let opts: NWParameters = .tcp opts.includePeerToPeer = true opts.allowLocalEndpointReuse = true let service = NWListener.Service(name: "aux", type: BONJOUR_SERVICE_TYPE, domain: "") try bootstrap.withNWListener(NWListener(service: service, using: opts)).wait() // bootstrap is an artifact of using SwiftNIO Similarly, my setup on the discovery side of things looks like: let params: NWParameters = .tcp params.includePeerToPeer = true let browser = NWBrowser(for: .bonjour(type: BONJOUR_SERVICE_TYPE, domain: BONJOUR_SERVICE_DOMAIN), using: params) browser.browseResultsChangedHandler =  { (searchResults, changed) in // save the result to pass on its NWEndpoint later } and finally, where I have an NWEndpoint, I use SwiftNIO's NIOTSConnectionBootstrap.connect(endpoint:) to initialize a connection to my TCP service ( a web socket server ). The fact that I am able to get P2P networking (presumably over an awdl interface?) between the simulator and the iOS device suggests to me that I haven't done anything obviously wrong in my setup. Similarly, the fact that it works over the same WiFi network and that, in P2P, I am able to at least observe the Bonjour advertisement, strikes me that I'm somewhere in the right neighborhood of getting this to work. I've also ensured that my Info.plist for the app has a NSLocalNetworkUsageDescription and NSBonjourServices for the Bonjour service type I'm browsing for. I've even attempted to exercise the "Local Network Permission" dialog by using a hacky attempt that sends data to a local IP in order to trigger a permissions dialog, though the hack does not appear to actually force the dialog to appear. Is there some trick or other piece of knowledge regarding allowing the use of P2P w/ Network.framework and TCP connections to services?
7
0
1.8k
Oct ’22
Matter.framework does not work properly in iOS 16.1.1
On iOS 16.0, I added accessories via the MTRDeviceController class in the Matter.framework, and it worked fine. But when I will phone upgrade to the latest version of the iOS (iOS 16.1.1), after I call "MTRDeviceController" class "pairDevice: onboardingPayload: error:" method. I get an error like this: CHIP: [BLE] BLE:Error writing Characteristics in Chip service on the device: [The specified UUID is not allowed for this operation.] According to the error message, I guess that the characteristics of a certain Bluetooth cannot be read and written. After trying to verify it, I find that the characteristics uuid of the Matter accessory: "18EE2EF5-263D-4559-959F-4F9C429F9D12" cannot be read. So, my question is what can I do in iOS 16.1.1 to make my app work as well as it does on iOS 16.0.
10
0
3.3k
Dec ’22
SimpleFirewall sample application not working
I can build the SimpleFirewall application (https://developer.apple.com/documentation/networkextension/filtering_network_traffic ) using xcode: After I run the application, seems can't block any traffic. I find there is some logs from network extension process: networkd_settings_read_from_file Sandbox is preventing this process from reading networkd settings file at "/Library/Preferences/com.apple.networkd.plist", please add an exception. Any step I am missing ?
3
0
774
Dec ’22