A Rant About Proxying API Requests on iOS (and others)

Wherein I try to find a way to redirect API requests from Twitter clients through an external proxy, for request modification shenanigans. It's easy everywhere... except for non-jailbroken iOS. Because Apple.

I'm a heavy Twitter user, and I'm not happy with any of the clients that exist right now - I've wanted to develop my own for a long time, but due to my lack of time and motivation, it's never really gone anywhere.

My current mobile client is a modified version of Fenix for Android, with a few tweaks that make it work better for my uses (a larger tweet cache, a streaming toggle, and loading images through a compression proxy when on mobile data).

This sort of works, but it's not optimal. These changes only work on that app and I have to manually port them to new versions. I've lived with it up until now, but I'm planning on switching to iOS, where installing modified apps is considerably more difficult (especially without a jailbreak).

So, I hit upon an idea: if I create a Twitter API proxy, I can implement many of the features I rely on (or want to have) without having to modify clients at all, and make other useful tweaks - for instance, if I keep a persistent userstream connection open and then simulate the server-side API in my proxy, then clients can connect/disconnect all they want without ever triggering Twitter's rate limiting. And I can force images to be compressed simply by replacing the image URLs in API responses.

This should work on any platform, with any app - even desktop apps.

Except for one thing. How DO you get your client to connect to the proxy?

Twidere on Android lets you provide a different API URL. Twitter for iPhone has an "API root" option which does the same (although it may have been removed in a newer app version; I'm running the last iOS 6 compatible build). Most other clients are locked to the default api.twitter.com.

This means you've got to hijack connections to it somehow. SSL is required, so this will require a self-signed certificate for api.twitter.com and userstream.twitter.com, but this shouldn't be too much of a problem as even iOS lets you install root CAs.

On Android, this isn't a massive deal. If you root, you can modify your hosts file (with the caveat that you'll break Twitter for Android, as it forces certificate pinning). If you don't want to do this, you can always install a patched client.

The situation on iOS is different. If you jailbreak, you can modify your hosts file - that's pretty straightforward, but you can't depend on a jailbreak being available for newer iOS devices. And if you don't, what CAN you do?

It's a complete mess.

iOS allows you to specify a global http proxy, to be used on mobile data AND all wifi networks, which seemed like the perfect solution at first. But this option can only be enabled on a "supervised device", which is the mode used for businessy enterprise deployments or some junk like that. And you need a Mac running Yosemite (or newer) to run Apple Configurator, the tool that lets you supervise a device.

So what other options do I have? My iPhone 3GS doesn't have data access, so I'm unable to test out anything for real until I actually get a new phone.

I might still be able to use a http proxy - I found out online that you can modify configuration files in an iTunes backup, which would potentially allow me to edit SystemConfiguration/preferences.plist and insert settings that the UI won't let me add.

I think you can force a http proxy on mobile data through the APN settings, but there doesn't seem to be a way to set a username/password here. I won't run an open HTTP proxy, so that idea's out.

Barring these, a VPN is probably my only choice.

It's nice that iOS has been slowly becoming more open, but silly restrictions like this are amazingly frustrating. What harm is there in allowing unsupervised devices to assign a global http proxy, for instance? (Even if it has to be configured using a profile and not through the device UI.)

It probably won't stop me from getting an iPhone, because I'm sick of Android and there aren't really any viable alternatives. Ah, well, I guess it'll be a change... and hopefully it won't take too long for an iOS 9 / iPhone 6S+ jailbreak to be available.

Previous Post: How I Began Modding NSMBWii
Next Post: An Unholy Combination: Closure Compiler, Preact and JSX