How will iOS enforce connections to use a secure connection exclusively? - ios

Starting 2017, Apple will require HTTPS connections for iOS apps. Apps will be forced to use ATS, based on TLS, to establish a connection successfully.
I'm currently developing a network measurement tool for a client. Using the low-level socket interfaces, the purpose is to transmit packets over TCP or UDP to a server in the network, in order to measure the speed of the WiFi connection.
As it is not clear how Apple will enforce their new rules, we find it hard to estimate how our application will be influenced by them. Is there any more information available on this? On which types of connections do they apply? Based on what characteristics will iOS label a connection as insecure?

Your app should be fine. See this thread with a response from an Apple staff: https://forums.developer.apple.com/thread/48979
The relevant part:
First up, there have been no changes to the technical behaviour of ATS (other than the addition of NSAllowsArbitraryLoadsInWebContent and NSRequiresCertificateTransparency). From a technical perspective, ATS exceptions in the newly seeded OS releases work the same way as they do in the current OS release.
What has changed is that App Review will require “reasonable justification” for most ATS exceptions. The goal here is to flush out those folks who, when ATS was first released, simply turned it off globally and moved on. That will no longer be allowed.

Related

What triggers the "would like to find and connect to devices on your local network" permission notification on iOS 14?

What actual method calls, excluding Bonjour, triggers the "would like to find and connect to devices on your local network" permission notification on iOS 14?
This is the screen shot from the WWDC session on this new permission. Which is only somewhat helpful as an overview. I'm more interested in figuring out what all method calls trigger this.
If you're using react native with a debug configuration, then you are including all the code responsible for communicating with your dev machine so you can probably ignore this message.
However it's best to check you have no other libs that require access too. To do this just build a Release version and see if the message persists.
In a nutshell, Bonjour. Its use is no longer "transparent". See https://developer.apple.com/videos/play/wwdc2020/10110/ for more information:
If your app interacts with devices using Bonjour or other local networking protocols, you must add support for local network privacy permissions in iOS 14.
Even an existing app is subject to this rule; the first attempt to use Bonjour triggers the authorization alert.
Apple (Eskimo on the Dev Forums) released a FAQ providing more details around this alert:
https://developer.apple.com/forums/thread/663858
Particularly, providing more info as to what triggers this alert is FAQ-2:
https://developer.apple.com/forums/thread/663874
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
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, NSURLSession and WKWebView, 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 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
One of my apps was triggering this prompt unexpectedly in our internet multiplayer mode. We use RakNet for our networking (which is a C++ lib that uses BSD sockets to send/receive UDP) and I was able to track the problem to the RNS2_Berkley::BindShared function here.
After creating a UDP socket, RakNet tests health/validity of the socket by having it send a little test packet to itself. iOS 14 was flagging this send-to-self behaviour as communication on the local network. I'm not sure if this send-to-self behaviour is a common pattern in socket programming, or a particular quirk of RakNet. Frustratingly, the OS prompt didn't actually appear until later when the socket was used for real which made the issue very hard to track.
I think that this is a false-positive from the OS and raised it with Apple (FB8802121). I won't be holding my breath though so I've just disabled that RakNet behaviour for iOS and am hoping that it wasn't too important.
Edit: To more directly answer the original question: sendto is a method call that can trigger this prompt.
I get rejected from apple app review for this alert. I'm using GCDWebServer which creates an embedded http server in my app.
I think I should provide a message in info.plist to tell user what my app want to do. Before I didn't set the text string in it.
And I would like to update if this will pass the app review.
<key>NSLocalNetworkUsageDescription</key>
<string>xxx uses the local network to connect with devices around you.</string>
Regarding iOS 14: permission request: would like to find and connect to devices on your local network and after numerous deploys to my physical device, I have figured out what causes this in my case.
I have a Xamarin.Forms app which
calls localhost:xxxx to do some local logging while I develop
I use a product thats called LiveSharp that does local hot reloading for XAML AND C# code changes.
So Livesharp actually communicates with a server on my localhost as well.
After disabling both of these and a fresh clean install on my physical device, the permission request has GONE .. Yay
Note: I had to completely remove LiveSharp nuget packages from my project.
Also I tried to re-enable my localhost logging, and for some reason the permission request does not appear.. :headscratch
So: remove any localhost communication that happens in your app. Or at least put an if statement around it allowing it if set to true in appsettings
I also have a Xamarin app and I used the package LiveXaml. After removing it the message was gone.

Framework for communicating between iOS and MacOS

I'm looking to build a pair of apps that work in a similar way to iTunes and the Remote app for iOS... Is there a framework for connecting iOS and MacOS over wifi?
Bluetooth is something I'd like to avoid and there's no need for a web service, I'm just looking to control my Mac app remotely from the phone.
Thanks in advance.
Id say the most ideal way to accomplish this is via the Bonjour protocol.
Here is a great article on the subject, http://mobileorchard.com/tutorial-networking-and-bonjour-on-iphone/.
Good thing with using Bonjour in iOS is it also works via Bluetooth.
Hope this helps !
here is an example project which exchange the data between iphone and iMAC with WiFi connectivity.
https://github.com/boobalaninfo/Bonjour-iOS-MAC-Apps
Use bonjour to search for devices. Then use CocoaAsyncSocket to send and receive data. It works like a charm.
Little info about AsyncSock:
GCDAsyncSocket and AsyncSocket are TCP/IP socket networking libraries.
Here are the key features available in both:
Native objective-c, fully self-contained in one class. No need to muck
around with sockets or streams. This class handles everything for you.
Full delegate support Errors, connections, read completions, write
completions, progress, and disconnections all result in a call to your
delegate method.
Queued non-blocking reads and writes, with optional timeouts. You tell
it what to read or write, and it handles everything for you. Queueing,
buffering, and searching for termination sequences within the stream -
all handled for you automatically.
Automatic socket acceptance. Spin up a server socket, tell it to
accept connections, and it will call you with new instances of itself
for each connection.
Support for TCP streams over IPv4 and IPv6. Automatically connect to
IPv4 or IPv6 hosts. Automatically accept incoming connections over
both IPv4 and IPv6 with a single instance of this class. No more
worrying about multiple sockets.
Support for TLS / SSL Secure your socket with ease using just a single
method call. Available for both client and server sockets.

iOS Bonjour local service discovery

I have an issue in my app where if a client is running my app but does not have wifi enabled, the app does not find my service and returns an "Unknown error" CFNetServiceError code 72000. The client enables wifi, connects, and my app is clueless.
The obvious fix is to add a notification for when a local wifi network is connected and reinitiate the NSNetServiceBrowser's search.
I don't know how to do that in C, so I was hoping to use Reachability. To my dismay, the solution I seek has recently been removed.
This is from the Reachability ReadMe file.
Removal of reachabilityForLocalWiFi
Older versions of this sample included the method reachabilityForLocalWiFi. As originally designed, this method allowed
apps using Bonjour to check the status of "local only" Wi-Fi (Wi-Fi
without a connection to the larger internet) to determine whether or
not they should advertise or browse. However, the additional
peer-to-peer APIs that have since been added to iOS and OS X have
rendered it largely obsolete. Because of the narrow use case for this
API and the large potential for misuse, reachabilityForLocalWiFi has
been removed from Reachability.
Ok, fine. But what the hell are these additional APIs? I need a method. :(

Knowing status of a bonjour service

I'm using NSNetService and NSNetServiceBrowser to publish and scan for Bonjour services on the network. The implementation is working fine, the services are found on the network and they are capable of communicating. I'm currently trying to understand the framework's lifecycle and this what I've got so far:
// Scanning
netServiceBrowserWillSearch:
netServiceBrowser:didFindService:moreComing: // The device finds itself
// Advertising
netServiceWillPublish:
netServiceDidPublish:
This happens if I start the services with the adapter on. Now I need to know, at all times, whether the service is being actively advertised on the network; that is, if other devices are capable of finding it. So I test it with turning the Wi-Fi adapter off:
netServiceBrowser:didRemoveService:moreComing:
netServiceBrowser:didFindService:moreComing: // The device finds itself again, even after the adapter is turned off
Then I turn the adapter back on:
netServiceBrowser:didRemoveService:moreComing:
netServiceBrowser:didFindService:moreComing: // Yet again
The problem is that there is absolutely no difference in turning the adapter on or off, so I can't look for a pattern. Is there any other way that I can catch these events?
Edit: It gets worst. Even if I start the services with both adapters off (airplane mode) netServiceDidPublish: still gets called. So far it seems that netServiceDidNotPublish: is called only when I try to register the same service twice. This is very counter intuitive to me; maybe the service got published to the adapter, but not the network, and as such these callbacks are very misleading. At this point there is no way I can know whether the service is visible on the network.
For future reference, I needed to use workarounds to solve this. The problem is that Bonjour publishes its services to the protocol stack, so the adapter never gets queried for state. This makes sense, as Bonjour is a multi-transport protocol. In order to solve this I used an adaptation of Apple's reachability framework to listen to adapter state changes for Infrastructural Wi-Fi, at which point I query the adapter for the presence of the adwl0 interface for Wi-Fi direct support. Important note: that article claims to find support for general Wi-Fi connectivity which is not true; the awdl0 interface is the Wi-Fi Direct interface, which is why this will fail in devices such as the iPhone 4/4S. This is OK, because those devices do not support Wi-Fi Direct. As Bonjour also works with Bluetooth, I use CoreBluetooth to listen to Bluetooth adapter state changes. Although this framework is meant for Bluetooth Low Energy, I believe the Bluetooth adapter being on is a strong assurance that the Bonjour services are visible on the network. It's a bit unfortunate that Apple doesn't allow doing this without workarounds, but that's what we get, I guess.

iOS Long Running Background service listening for multicast packets

Our company has a requirement to build an app that needs to have a service constantly running on the background listening for multicast packets and cache its content into variable size files to enhance user experience, the background service needs to run regardless of the app being running. The suggested approaches I saw here and in the docs such as working with notifications wouldn't work as it is mandatory that these contents arrive over multicast which requires the socket to be constantly opened, also fetching using TCP would not be an option as it would increase network load which we're trying to avoid by using multicast. Another approach would be to register the app as VoIP so the app would be awake by the OS when new data arrives in that socket (which would be the multicast socket), but I'm not sure if that fits what apple considers to be a VoIP application, so I'm concerned we would have problems getting the app approved.
Any suggestions on how to implement this solution would be greatly appreciated!
Edit:
This is not an enterprise app, it is intended to be used on a dedicated WiFi and rely on our servers (deployed on the same WiFi) for multicast. It also needs to be public on the store for our customers to download.
According to Apple:
1. Re: Long Running Background listening for multicast packets.
In response to Daniel Inc. on Oct 17, 2014 1:16 AM
Our company has a requirement to build an app that needs to have a
service constantly running on the background listening for multicast
packets [...]
AFAIK there's no supported way to do this on iOS.
Another approach would be to register the app as VoIP so the app would
be awake by the OS when new data arrives in that socket (which would
be the multicast socket), but I'm not sure if that fits what Apple
considers to be a VoIP application, so I'm concerned we would have
problems getting the app approved.
Regardless of the approval issues, the VoIP infrastructure only supports TCP data sockets.
Share and Enjoy
Quinn "The Eskimo!" >
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

Resources