First, some background. We are working on the iOS port of this as part of our ZeroTier SDK for mobile development project:
https://www.zerotier.com/product-netcon.shtml
More background here:
https://www.zerotier.com/blog/?p=612
(scroll down to "Standards Based Peer to Peer Networking")
The idea is that this could be built as a framework and linked against the app and would provide the app with the ability to communicate over virtual networks seamlessly without requiring other code to be rewritten or recompiled. We've figured out how to package this appropriately into a single self-contained framework, get it to load, and get it to run both in the simulator and on a real device. It works when we make direct BSD socket API calls in our app, e.g. socket() and bind() and connect() and friends, and is able to connect and communicate over virtual networks as expected.
Now what we're trying to do is to figure out how to get this to work when sockets are used via CFSocket, CFStream, etc. and with native iOS HTTP/HTTPS clients and other normal iOS network I/O code.
The prroblem we're running into is that library interposition does not seem to work this way on iOS (or OSX/Darwin). Our library's interception of socket(), bind(), etc. does not carry over into other libraries the way it does on Linux. I assume this is a difference in how Apple's dynamic linker/loader works, or maybe something related to security policies.
So I'm posting to ask:
(1) Is there any way to achieve the desired library interposition/interception behavior on iOS (and OSX) without "heroic" things like code injection that would not be allowed in a normal app? We're linking our library and calls made from our app's main code itself are overridden, but this isn't currently carrying over to other libraries. Is it somehow related to library load or link order and is there any way to change this?
(2) If not, is there any other way to achieve the desired end goal? We are in parallel working on an iOS version of our ZeroTier One VPN app (see Android version here for comparison https://play.google.com/store/apps/details?id=com.zerotier.one), and this is going well. This is straightforward in that we're just using Network Extensions, etc., and writing a VPN app. Is there any way for a normal iOS app to have anything like a "private network extension" that is entirely self-contained within the app and visible only to itself? That's what we are more or less trying to achieve, so if it can't be achieved with library interposition then perhaps it can be achieved in some other way.
If there's no way to achieve (1) and (2), the last resort option we're considering is launching a background thread that runs a private SOCKS5 endpoint and then having the app use that. Theoretically that should work but it's ugly and probably slower than doing it the right way.
What we want in the end is to be able to package this as something entirely private and self-contained within an app that can allow the app to talk over the virtual network seamlessly without special elevated permissions or external secondary apps to provide connectivity.
Edit:
We found references to an "official" way of interposing functions:
http://toves.freeshell.org/interpose/
http://www.opensource.apple.com/source/dyld/dyld-97.1/include/mach-o/dyld-interposing.h
The question is whether this works when a library is actually linked with the application, since you can't set DYLD_INSERT_LIBRARIES in an iOS app. If we figure it out we'll edit and update for anyone else's reference, but in the meantime feedback is welcome.
Edit #2: this looks promising, will report: https://github.com/facebook/fishhook