blog.cyrusroshan.com

25 January 2021

No. 10

Bypassing hotspot limits on iOS

My parents live in a fairly rural area of Texas. There's no cable internet, and fiber is out of the questionβ€”they're the target demographic for Starlink. When I was in high school, we used our phone landline for a very-flaky, too-expensive DSL. Nowadays we use hotspots.

So if there's no hotspot, there's no internet.

And when I flew in this winter to visit, my paid hotspot plan didn't activate on time. So there I was, sitting in quarantine, trying to use my laptop with no internet. But annoyingly, I already had unlimited phone data.

I wondered: why can't I use my phone's LTE data to hotspot? As it turns out, it's not that you can'tβ€”-it's just that iOS doesn't want you to.

Here's how I managed to get a DIY hotspot working on a regular, non-jailbroken iPhone.

Logs from sshd -d -d
And the speed's not bad!
Note: Cloudflare Warp is the VPN app I use on iOS

How does it work?

When you use a hotspot on iOS, your device treats your hotspot's network packets differently than the network data that apps use. Hotspot packets get routed differently, and they get metered. And if your hotspot plan isn't activated, your device won't even let you hotspot at all.

Connecting through my built-in iOS hotspot doesn't route traffic through my iOS VPN

In order to prevent that, this custom hotspot tunnels your laptop's network packets through an app (in this case, iSH). This way, your laptop's traffic gets treated as if it's just an app making network connections.

Here's a quick visual overview of the process:

πŸ’» LaptopiPhone πŸ“±πŸ’» LaptopiPhone πŸ“±Creates an ad-hoc WiFi network1Connects to Laptop's wifi network2iPhone assigned an IP address3Sets up SSH server4Laptop SSHes into iPhone5SOCKS5 proxy established6Configures applications to use proxy7
After setting this up once, subsequent runs take under a minute

After step 7, the custom hotspot is configured. Data from this hotspot is treated just like normal app data!

Setting it up

Here's how I got this working.

  1. Download iSH, an interactive shell, to proxy connections through an iOS app
    • If you previously had an old version of iSH installed, you will need to manually enable its built in apk for package management. New downloads have it enabled by default.
  2. Create a new adhoc wifi network from your laptop, connect to it from your phone, and get your phone's IP
    • you can quickly verify that the connection works using something simple like python3 -m http.server
  3. Send your SSH public key from laptop β†’ phone
    This step was harder without wifi. Click here to expand and see the quick-and-dirty way I did it.On my laptop, I ran cat publickey | base64 | pbcopy, then pasted the result into http://$PHONE_IP/$RESULT. This hit the server on my phone (run using python3 -m http.server), which showed it in the URL path of the server logs on my phone.
    Then on my phone, taking that result from phone logs, I copy β†’ pasted it into a shell command, echo "[paste here]" | base64 -d > publickey.
  4. Install sshd on iSH
    • Add your public key from the previous step to the /.ssh/authorized_keys file
    • Configure the ssh server settings. The changes I made were:
    Port 2222 # Custom port, 22 won't work ListenAddress 0.0.0.0 # Allow the laptop to connect via wifi PermitRootLogin prohibit-password # Allow root login PubkeyAuthentication yes # Allow public key auth AuthorizedKeysFile /.ssh/authorized_keys # Allow access from your public key PasswordAuthentication no # Disable passwords PermitEmptyPasswords no Compression no # CPU is a concern more than bandwidth, when we're doing this emulated + local network AllowTCPForwarding yes # Allow port forwarding GatewayPorts yes # Allow port forwarding UseDNS no # Not useful PermitTunnel yes # Allow our reverse tunnel
  5. Test an SSH connection to the app from the laptop
    • You should be able to get your phone's IP from the settings page
    • SSH in from your laptop with ssh root@$PHONE_IP -p 2222

Now, on your laptop you should be able to run ssh -N -D 1080 root@$PHONE_IP -p 2222 to create a SOCKS5 proxy server on port 1080! You can open your browser (Firefox, Chrome), configure this as a proxy, and use this to route traffic!

If you only need to use your browser, you're good! But you might also want to use other tools, and many of these tools don't respect system proxy settings. For that, we can use proxychains.

Using Proxychains

Proxychains and proxychains-ng are tools that allow you to use a proxy with software that isn't configured for it.

Since I'm on macOS, and proxychains-ng has better support, I used it here. Here's the setup:

  1. Install with brew install proxychains-ng
  2. Edit the file /usr/local/etc/proxychains.conf to use socks5 127.0.0.1 1080 as the proxy
  3. Run the program you want to use with proxychains4 program_name [arguments]

Limitations

Though this is a great backup internet solution, it's not as good as a normal carrier-enabled hotspot. Here's a little more depth on what its drawbacks are and why they occur.

Desktop limitations

On an unrooted iPhone, you can't modify iptables or truly run as root, so setting up a VPN server on the phone and connecting to it on your laptop doesn't work. You'll have to route the traffic through SSH or another protocol whose server can be run in iSH.

I spent a couple hours, but for whatever reason, I couldn't get sshuttle working. Proxychains works fine, but it means you need to manually launch every program you'd like proxied, and UDP traffic isn't supported, just TCP.

Note that you may be able to work around these limitations on Linux, where you have more control over the network stack than on macOS.

App limitations

There are a couple of limitations to this method from the app side, as well. Though they're both bearable as-is.

1. Backgrounding

When your phone locks, or you switch apps, iSH will get backgrounded, and your connection to the server will be lost.

To allow iSH to run into the background, you can run cat/dev/location > dev/null &, which polls your location, though it's still a bit flaky. You could also disable auto-lock screen, though remember to re-enable it after you're done.

2. Heat

After an hour or two of constantly running sshd on iSH, your phone gets warm and toasty. This is because iSH emulates all of its commandsβ€”-but for good reason, App Store approval!


However, with effort, a custom app could solve the above limitations by:

  1. Allowing more control over backgrounding behavior, including abusing background music for unlimited backgrounding.
  2. Running arm64 sshd without requiring x86 emulation, reducing CPU usage.
  3. And doing both of the above without requiring App-Store approval, since you can load custom apps locally.

Until then, this is a proof-of-concept that leaves productionization as an exercise to the reader.

Enjoy!

Get new indie blog posts in your mailbox, personally written by me