25 January 2021
No. 10
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.
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.
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:
After step 7, the custom hotspot is configured. Data from this hotspot is treated just like normal app data!
Here's how I got this working.
apk
for package management. New downloads have it enabled by default.python3 -m http.server
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.
echo "[paste here]" | base64 -d > publickey
.sshd
on iSH
/.ssh/authorized_keys
filePort 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
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.
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:
brew install proxychains-ng
/usr/local/etc/proxychains.conf
to use socks5 127.0.0.1 1080
as the proxyproxychains4 program_name [arguments]
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.
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.
There are a couple of limitations to this method from the app side, as well. Though they're both bearable as-is.
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.
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:
Until then, this is a proof-of-concept that leaves productionization as an exercise to the reader.
Enjoy!