Icemoon ← All posts

Guide

Proxies on iOS: why per-device egress is harder than on Android

August 1, 2026 · 7 min read

On Android you can point an app, or a whole device, at a proxy and move on. On iOS you cannot. The setting lives somewhere else entirely, and discovering that halfway through building a fleet is a bad afternoon.

Where the setting actually lives

iOS attaches HTTP proxy configuration to the Wi-Fi network. Not to the device, not to an app, not to a system-wide preference. Join an SSID with a proxy configured, and everything on the device uses it. Join a different SSID, and you get that network's settings instead.

The consequence is immediate: if twenty phones are on one SSID, they share one egress. There is no per-device toggle to change that, because from iOS's point of view there is nothing to toggle — the network decided.

This is also why advice written for Android farms does not transfer. "Set a proxy per device" is a sentence that means something on Android and nothing on iOS.

Three ways around it

1. One SSID per device

Crude and completely reliable. A router capable of broadcasting many SSIDs, each configured with its own proxy, and each phone joined to its own network.

Works because: it uses the mechanism exactly as designed, so nothing surprising happens.

Costs you: SSID limits on consumer hardware (often 4–8), radio congestion when you push past a handful, and a configuration surface that grows linearly with devices. Changing one phone's egress means editing a network, not a device.

Fine to five devices. Painful at twenty.

2. Routing upstream by MAC address

One SSID with no proxy configured. The router or a gateway box in front of it decides which egress each device gets, keyed on its MAC address.

Works because: the decision moves off the phone entirely. iOS just uses the network; the network does the interesting part.

Costs you: a router you can actually program — OpenWrt, pfSense, a small Linux box, something in that family. Consumer firmware will not do policy routing per client. You also need to keep MAC addresses mapped to devices, and iOS private Wi-Fi addresses will randomise MACs unless you turn that off per network.

This is the right answer once you are past a handful of devices and comfortable with network gear.

3. Let the fleet layer own the assignment

The tool that already knows which account is on which device also assigns that device's egress, so there is one place where the pairing lives.

Works because: the thing that matters most is not the proxy but the pairing — this account, this device, this egress, staying together. When account assignment and egress assignment live in two different systems, they drift, and drift is what causes the damage.

This is what per-device assignment in Icemoon does: an account and a proxy are attached to a device together, and flows resolve both automatically.

The part people optimise in the wrong order

Operators spend a great deal of energy on proxy quality — residential versus datacentre, which provider, how clean the subnet — and comparatively little on proxy stability.

Stability matters more. An account that has been seen from one address for three months and suddenly appears somewhere else is a strong signal. An account that appears from a new address every single day is a strong signal. Fifty accounts sharing one address is a strong signal.

A mediocre proxy used consistently by one account beats an excellent proxy that rotates. The pairing is the product; the proxy is an input.

Practical rule: when an account and an egress are paired, treat that pairing as permanent. Changing it should be a deliberate decision with a reason, not a side effect of a config reload.

Private Wi-Fi Address

iOS randomises the MAC address it presents to each network by default. That feature is good for people and inconvenient for anyone routing by MAC.

It is per-network, so you disable it on your farm's SSID and leave it alone everywhere else: Settings → Wi-Fi → (i) next to the network → Private Wi-Fi Address off. Do this before you build the routing table, not after you spend an hour wondering why the rules stopped matching.

What about VPN profiles?

iOS supports VPN configurations, and they are device-level rather than network-level, which sounds like it solves the problem.

In practice it trades one set of constraints for another. VPN profiles need to be installed per device, they can be disrupted by the device sleeping or switching networks, and a VPN that drops leaves the device on the underlying network rather than failing closed — which is the worst possible failure mode for this use case. Routing upstream keeps the enforcement somewhere the phone cannot accidentally bypass.

Testing that it works

Do not assume. From each device, open a browser and check the address the wider internet sees. Do it once per device after setup, and again after any network change.

The failure you are looking for is not "no connection" — that is obvious. It is a device silently using the wrong egress: the proxy was misconfigured, the profile did not apply, the MAC randomised. That one is invisible until it matters.

Worth automating: a flow that opens a page showing the current IP, reads it off the screen, and posts it to your own endpoint. Run it across the fleet after any change and you have a per-device confirmation in seconds. An HTTP step makes this a five-minute build.

Summary

ApproachGood forBreaks down at
One SSID per deviceUp to ~5 devicesSSID limits, radio congestion
Upstream routing by MACAny size, if you run the gearNeeds programmable networking
Fleet layer assignmentKeeping account and egress pairedStill needs the network to allow it

Whichever you choose, the thing worth protecting is the pairing, not the proxy.

One account, one proxy, one device

Icemoon assigns an account and an egress per device from the dashboard, and flows resolve both automatically — so the pairing stays where you put it.

Start free trial
All posts Home Install guide MCP server