iOS app sandbox for accepting connections on TCP sockets - ios

I'm making use of the library GCDWebServer(https://github.com/swisspol/GCDWebServer) in a project of mine, that requires me to accept connections originating only from my application's process, for security reasons. I was hoping this is something that the iOS app sandbox would provide out of the box, but that doesn't appear to be the case. The sandbox appears to be enforced for UNIX domain sockets(AF_UNIX), by means of file-system permissions. But for TCP/IP sockets(AF_INET), used by GCDWebServer, there appears to be no sandboxing in place.
I was able to write two sample applications - a client and a server(signed with different developer certificates) and could have them communicate with each other, without any issues.
I was wondering if there was some way of enforcing the same on iOS, essentially spin up a HTTP server on a TCP socket but only accept connections from the same process. I can't make use of UNIX domain sockets, because the client which is going to request the content from the HTTP server is an AVPlayer and it wouldn't know how to connect to my application's UNIX domain socket.

I'm about 99% certain that what you're asking for is impossible. I don't even think it is possible in OS X without writing a network kernel extension (and even then, it would be challenging).
By the time a network request reaches another process, it has passed through the networking stack and has lost any notion of what process originated the connection (unless this has improved fairly recently).
Realistically, the closest you can get is binding to a random port on the localhost interface and tearing it down as soon as your app gets put into the background.
Pedantically, if you managed to somehow convince Apple that you planned to build a VPN, it is theoretically possible to abuse the VPN API in such a way that would let you provide a private network that worked only within your app. It would not, however, ever be allowed in the app store.
But why would you ever want to do this? AVPlayer is more than capable of playing from a file URL.

There are many ways you could do that: you can inspect the incoming request in GCDWebServer and decide if you want to respond to it or return an error.
You could add a secret header other apps wouldn't know about, sign the entire request with a secret key, etc...

Related

How do you determine if a device is behind China's great firewall with the iOS SDK?

Because of issues reaching our normal endpoints hosted outside of China reliably when the user is behind the great firewall, we're looking for a way to reliably determine if the user is currently behind the great firewall and use a different set of endpoint urls hosted within China.
What we would like to do is some kind of check that the client can make, like accessing a url that we know will always be blocked by the firewall forever (or is only accessible from within) or checking some property of the network configuration.
Things currently being considered:
Checking the device's IP against a list of netblocks assigned to China
Won't work if the device is behind a NAT firewall
Doing a traceroute from the device to a host known to be outside of china. If packets are being routed through hosts that are in China (see above) then the device must be in China.
Might work, but will introduce delays before the app can make calls while it.
Just ask the user
Worst case, this may be the best option.
IP address ranges or you can check a key few of the top blocked websites... maybe Facebook, Google, Wall Street Journal? Choose a variety.
I suspect that any method which attempts to check the great firewall directly will be unreliable, probably in the short term and definitely in the longer term. However since your goal is to select servers either within China or outside of the country, I suggest using the device time zone as a quick and dirty "where am I?" check. If the time zone name is Asia/Chungking, for example, use the Chinese server. If it's Europe/Amsterdam, for example, do not use the Chinese server. Check for every time zone in mainland China and you'll probably be fine.
You can get the time zone name as TimeZone.current.identifier.
A more technical approach may be to analyze the TCP RST packet begin sent by the firewall. This (page 5) white paper shows how researchers were able to differentiate a TCP RST from the firewall from their server by fixing the TTL value and noticing when it is different (61 vs 42 in the paper).
When a customer is possibly in China (determined by other info) you could force a RST on the first connection, save the TTL value and then notice when you get a RST of a different value.
My suggestion is based on a few assumptions and some prior experience validating traffic sources.
Assumptions
Any URL you continually check will eventually be noticed by GFWOC admins.
a. this traffic pattern will result in a permanent block,
b. and/or used to track devices attempting to hit this url (perhaps as a honeypot),
c. and/or redirected to an internal state sponsored and monitored end point of some sort.
you have the ability to push updates to your iOS app through the firewall.
Options
Create an endpoint outside of China with a ppk authenticated login, and include the ppk file in your iOS application. The endpoint returns a message encrypted with the ppk such that only the calling instance of the iOS app can decrypt the response, which may simply be something like "ext_endpoint_reached" or some other known confirmation message.
If this ever fails to properly decrypt or provide the expected message, fail over to the internally hosted endpoints. If it succeeds, proceed as normal.
If outbound encrypted traffic is not permitted, and inbound encrypted traffic is blocked, a two part handshake could take its place. In this scenario, call one registers an outbound connection on external endpoint A. The device then connects to endpoint B, which is just another face of the same service backend, to see if it has a message waiting that fits certain parameters known only to the iOS application instance.
If the message it finds at B matches what is expected, and this could be a simple keyword based on the time or date or some other unique factor, you have succeeded in reaching the outside endpoint, whereas if you don't received the expected response or no response, you know you are being blocked or redirected.
Both of these options provide a fail over that confirms you are hitting the firewall, and both rely upon nothing terribly exotic to provide external, probably non-spoofable, confirmation that you are outside the firewall.

How to have a FlashAir Access Point over WiFi while still reach out internet via Cellular Data on an iOS app that uses AFNetworking?

IMPORTANT: I don’t need simultaneous transfers, I mean, I don’t need to transfer over WiFi while still transferring over 4G at the same time, I just want to be connected over Wifi to my Access Point, transfer some files and finally not having to turn off the WiFi for the iPhone to use 4G.
The problem:
As long as I’m connected to the Access Point (FlashAir technology), my iPhone doesn’t care to use 4G to reach out for internet, it is like it says: Oh, I have a WiFi connection I’ll direct all HTTP GET Requests over this network, which is bad for me as this Access Point is used to read/write files from/to it.
What I’ve done so far without success is the following two things:
Add the nogatewaymode=1 variable to the conf file of my FlashAir device which makes the iOS platform to know that this Access Point is not intended to provide internet, so, when I connect via WiFi to the FlashAir, the iPhone uses 4G to reach internet, which is cool, the problem here is that in this mode I cannot read/write files to the FlashAir device, which makes a useless WiFi connection.
Configure the FlashAir device to Internet Pass-Thru mode which allows it to behave as an Access Point and as Router basically, this requieres to add an APPMODE=6 to the conf file and also add a couple of variables to give a secondary or parent network (SSID and Pass). This actually works, but on a WiFi only scenario, I don’t have to switch between WiFi connections to get files from the Access Point and then upload them using internet as in the latter it just uses its secondary network to reach internet. The problem is that if we are away from the secondary network, you get the Access Point functionality but when trying to get internet the iPhone only cares to try to reach the internet over this WiFi connection which is not possible because we are away from the secondary network, and it just reports a No Internet Connection error, it doesn't even try to use 4G which is there ON all the time.
Some additional information is that I’m supporting iOS 8+, I’m using Obj-C for this project and I’m using AFNetworking to perform requests to either internet web services and the FlashAir device as is supports it, it has a built-in web server which listens for HTTP GET requests (cgi) with parameters.
Any ideas?
Thanks in advance
My app requires that the Flashair deliver a webpage to the phone using Wifi. That page requires internet (4G) to upload data from the Flashair to my site.
Flashair claimed it wasn't possible, this config works for me. That "NOGATEWAYMODE=1" is critical. And I have to access the Flashair via the browser using 192.168.0.1, you can't use the Netbios/Bonjour name.
[Vendor]
CIPATH=/SD_WLAN/WifiStatus.jpg
APPMODE=4
APPNETWORKKEY=********
VERSION=FA9CAW3AW3.00.01
CID=02544d535731364740d36e0a79010b01
PRODUCT=FlashAir
VENDOR=TOSHIBA
MASTERCODE=A1234567890Z
APPSSID=F751ENG4
APPNAME=F751ENG4
LOCK=1
WEBDAV=2
TIMEZONE=-28
DNSMODE=1
APPAUTOTIME=0
REDIRECT=1
NOGATEWAYMODE=1

How to select specific network interface for NSURLSession connections?

I’m not talking about Reachability.
What I’m talking about is figuring out how to create a network connection from an iOS device across the cellular interface.
Why? Because I have conditions where the device connects to a WiFi access point so it chooses WiFi… but that access point is not internet connected and goes nowhere. I have data which I must make every effort to deliver and it some cases it’s getting lost in the WiFi gateway to purgatory. In both cases of using Reachability and relying on MPTCP, Apple has already given priority to WiFi in the stack.
I know NSURLSessionConfiguration can set allowsCellularAccess to allow cellular access — I’m looking to require cellular for the routing.
Even at the CFNetwork level I’m looking at kCFStreamPropertyConnectionIsCellular for status, kCFStreamPropertyNoCellular to disable cellular.
I can’t find anyway to give preference to the cellular radio. I realize Apple has gone to great lengths to prefer WiFi and I’m going against that — which is why I’m having such difficulty finding an answer to this.
I'd like to keep this up in the Cocoa level, but not opposed to going into Foundation or deeper levels. I would like to avoid trying to parse an interface table (if it's even accessible) to figure out which is the cellular interface.
Has anyone successfully created a network connection across the cellular link despite WiFi appearing to be present?
Is some configuration of Multipath TCP the answer here?
To bind to a particular interface, as far as I'm aware, you'd have to drop all the way down to the raw socket level, and there's no way to provide a custom socket for NSURLSession purposes, so you'd basically be rewriting it from scratch. You should file a bug asking for support for binding an NSURLSession to a source IP.
The behavior you're experiencing is a known problem with iOS and disconnected networks. iOS 9 and later do a better job, but even then, they can be highly problematic; the devices sometimes refuse to talk to the Wi-Fi network, and sometimes refuse to talk to the cellular network. Specifically, it seems to fail spectacularly if either signal is weak. Just this morning, I actually had to force my iPhone (iOS 10) to talk to a disconnected Wi-Fi network by putting it in Airplane mode and enabling only Wi-Fi.
I'm told that you can fix this by configuring the network's DHCP server to not provide a router advertisement; that said, every time I've tried that, the iOS device would just keep asking for an offer repeatedly. Maybe that bug got fixed at some point. If so, it might be worth a shot, but don't expect it to work in older versions of iOS.
Failing that, assuming you don't need to support web browsers in iOS 3 and earlier, you might try eliminating the DHCP server on that Wi-Fi network entirely, and just rely on DNS service discovery with zero-conf IPs. That way, the device won't see a router, and it won't try to send data out that interface except to those link-local IPs.
If that isn't possible for some reason, ordinarily I would suggest using a customized copy of libcurl, except that I doubt this will work in your case, because POSIX networking doesn't wake the cellular hardware.
In iOS 12 and later you can use the Network Framework. Sample code is here.

For my task how should you communicate between iphone devices over the 3G network?

I have a situation where I would like to communicate between 2-4 devices over the 3G network (it should also work over WLAN, but 3G solution is critical).
Every device (except one) asks for a GPS-location every ~5 seconds, but when this process is cancelled by the user of that device, one device needs to be informed of this event.
I was thinking that one device could act as a server, and the rest as clients that should connect to the server. Is this possible over the 3G network?
I've also read about push-notifications, is this relevant here? Can you receive notifications without disturbing the user with a popups etc?
Are there other ways?
Basically I would like to use apple "standard" solutions (if there are any) before diving into eventual socket-programming or anything similar...
What I would like to avoid is to have a webserver or some similar "3rd-party" solution, because I don't want many users to simultaniously connect and "pull" from the same external server in a final solution...
UPDATE:
Basically my application will have thousands of users that will need to be informed if an even occurs. Also this happens simultanously ~5 second, what would be the best solution to reduce load and avoid spamming?
I was thinking that one device could act as a server, and the rest as
clients that should connect to the server. Is this possible over the
3G network?
It could work, but having a dedicated server would be a better choice
I've also read about push-notifications, is this relevant here? Can
you receive notifications without disturbing the user with a popups
etc?
In your case no, since you will need a server to communicate with apple
Basically I would like to use apple "standard" solutions (if there are
any) before diving into eventual socket-programming or anything
similar...
There are no standard solution, other than you should probably rethink about using a dedicated remote server for this
iPhones can't communicate directly with each other using 3G. You can access the internet through the 3G, but you can't do peer-to-peer as you are suggesting. If you were close enough, you could use bluetooth, but I expect you are too far away.
You would have no way of detecting the one device that acts as a server from the other devices. The IP address could (and probably would) change every time the device connects to a mobile data network. You would need a central server to co-ordinate all of the clients.
You have multiple questions, but I'll try to address as many of them as I can:
I was thinking that one device could act as a server, and the rest as
clients that should connect to the server. Is this possible over the
3G network?
No, you cannot run a server on a iPhone/iPad that is accessible over 3G without an external website acting as an intermediary. (You can run one that is accessible over Wi-Fi, but this does not solve your problem as stated.)
I've also read about push-notifications, is this relevant here? Can
you receive notifications without disturbing the user with a popups
etc?
Push requires you (or a third party contracted by you) to have a web server, so if you want a server-free solution it is not relevant here.
Are there other ways?
Over 3G you will, under the current Apple restrictions, always need an external server.
Basically I would like to use apple "standard" solutions (if there are any) before diving into eventual socket-programming or anything similar...
Diving won't help you here. Even using low-level socket programming you will not be able to run a server on an iPhone accessible over 3G without an external website to aid in establishing a connection.
You can try using GameCenter. The mechanism of network games in Game Center allows connect up to four players with no third-party solutions.

iOS app with real-time updates from server: Socket (using streams) or Apple Push Notification service?

I'm trying to make an iOS 5 app that features real-time things coming from the server. It will only use these whilst the app is running.
To make it real-time without polling I have been evaluating two design routes:
Creating a socket from the app to the server, and exchanging information via streams.
Pros: Relatively simple and would not involve a 3rd party.
Cons: Battery life drain.
For an overview of how this might work, check
out this excellent tutorial:
http://www.raywenderlich.com/3932/how-to-create-a-socket-based-iphone-app-and-server
Using standard HTTP to communicate with the server, and with each request from the app let the server know what they are viewing. If something new is available for user, send an Apple Push Notification (with no visible alert) to let app know it can go and download new thing.
Pros: Not opening up a new TCP connection, so battery life not drained unnecessarily.
Cons: Feels like a poor hack.
The official docs on APNs http://developer.apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ApplePushService/ApplePushService.html
I think a socket would be the way to go, but before I commit to it I wanted a second opinion, as this is the first time I've made anything like this!
Sockets would be my choice. I do not know how time critical your application is, but sockets might perform better as APNs if realtime is a must.
Does it really need to be "full real time"? From my point of view i would prefer http since it is already well integrated into the iOS SDK. Its easy to understand, maintain and implement and plenty of documentation is on the web. So maybe a http poll every minute or so will be enough (depending on the app and the number of users). Please consider firewalls too! Traffic to unknown ports maybe denied due to firewall policies of provider or local wifi. So if you really need realtime connectivity I guess you have to use sockets.

Resources