# The iOS app, in depth

This is the deep dive: every screen of URnetwork on iPhone and iPad, the
settings with their shipped defaults, and the troubleshooting knowledge that
usually lives in a support engineer's head. For the install-to-connected
path, see [getting started on iOS](/docs/getting-started-ios); for the
network design behind it all, the [overview](/docs/overview).

## How the app is built

One Xcode project produces both the iOS and macOS apps. On your device it
runs as two processes:

- **The app** (bundle `network.ur`) is the interface you see.
- **The tunnel extension** (`network.ur.extension`) is a Network Extension
  (`NEPacketTunnelProvider`) that iOS itself starts and supervises. Your
  traffic moves through this process, not the app: it wraps what your phone
  sends in encryption (the "tunnel") before it leaves the device. Four things
  stay outside it by configuration, as on any well-behaved iOS VPN: your
  local network (printers, AirPlay, home devices), Apple push notifications,
  carrier services like Wi-Fi calling, and traffic to your own nearby Apple
  devices.

The two talk over a local device RPC, so after a relaunch the app adopts the
live tunnel instead of tearing it down and starting over. This split is why
the VPN keeps working when you swipe the app away, and why iOS asks you to
approve a VPN configuration the first time: the extension is a system-managed
component. That approval is Apple's standard consent step for any VPN app. It
grants no other control over your phone, and it stays visible, and revocable,
in Settings → General → VPN & Device Management.

The app needs iOS 16.6 or later, and everything is open source at
[github.com/urnetwork](https://github.com/urnetwork). No independent audit
covers the protocol or the operator's server code, where the privacy claims
live. Two 2025 third-party assessments cover other surfaces: a penetration
test of the web application and API, and a Leviathan Security Group MASA AL2
assessment of the Android app, which passed. Neither covers the iOS app. The
[threat model](/docs/threat-model) records both and their limits.

## The four tabs

The app is four tabs: **Connect**, **Account**, **Leaderboard**, and
**Support**.

### Connect

The main screen, top to bottom:

- **The globe.** A live picture of your session. When connected, it shows the
  locations your traffic is exiting from: where the internet sees you. Your
  client holds several providers at once, commonly three to eight, in two
  windows side by side (a quality window that HTTPS prefers and a speed
  window for the rest), and pins each site to one. The picture is plural on
  purpose while any single website still sees one steady address. The
  [overview](/docs/overview) explains the provider window in full.
- **The connect button.** One tap to connect or disconnect.
- **The drawer.** A collapsible sheet under the button holding your selected
  location, **Connect options**, live traffic charts, and the **Block ads
  and trackers** switch. Drag it up for the full content; tapping the Connect
  tab while you are already on it collapses the drawer back down. Provide
  mode is not here. It lives in Account → Settings.

Tap the location card to open the **Available providers** sheet. It opens on
your own devices, "Best available provider", and countries with a live count
of providers online. Type a place name into "Search providers" and the
results grow a **Cities** section: searching is how you reach city-level
targeting, not scrolling. A location is listed only while a member's device
is online in it, and the platform derives the city from the connection it
observes rather than trusting a provider's own claim; an address that looks
like a datacenter or a VPN is demoted rather than trusted. "Best available"
picks the highest-scored providers near you; a specific location makes you
appear there (nearby exits are usually fastest, since distance costs
latency). Providers are other members sharing spare bandwidth. Your traffic
reaches them already encrypted, because the web is HTTPS before it ever
enters the tunnel, so a provider sees where the traffic it carries is going,
like an ISP does, but not its contents, and not your real address.

Further down the drawer sit four **Connect options**:

| Setting | Default | Effect | Main cost |
|---|---|---|---|
| Connection Mode | Auto | Auto runs both provider windows and routes each packet to the fitting one | Web or Streaming commit to a single window |
| Fixed IP | Off | Narrows the window to one provider, so every site sees one steady address | Gives up the plural exit |
| Strong Anonymization | On | Forbids a direct client-to-provider path, so the provider never sees your real IP | Slower than the direct path |
| Post Quantum Encryption | On | Seals the session end to end to the provider, so the operator carries ciphertext | Skips providers it cannot seal to |

- Fixed IP is selectable outside Auto.
- Turning Strong Anonymization off is how you opt into direct mode: the
  anonymization hop drops out, your client talks straight to the provider,
  throughput rises, and that provider now sees your real address. The default
  protects your identity; spend it for speed only if you mean to.
- **Block ads and trackers**, in the same drawer, is off until you turn it on
  and filters everything the tunnel carries.
- Between the two On defaults, a provider never learns who you are and the
  operator never reads what you send. Both are true without touching a
  setting, so no single party holds both your identity and your activity.

Those two switches and the shipped default are the whole picture:

| Mode | Operator sees | Provider sees | Default and availability |
|---|---|---|---|
| **Relayed sealed** | your account and source connection, which providers you are on, and ciphertext with its timing and volume | destinations it egresses and a device/contract id, **not** your real IP | the shipped default: Post Quantum Encryption, on in the connect drawer |
| **Relayed standard** | your account and source connection, which providers you are on, and the destinations and packet bytes inside | destinations it egresses and a device/contract id, **not** your real IP | opt-in: switch off **Post Quantum Encryption** |
| **Direct** | less relay involvement | **your real IP** and the destinations it egresses | opt-in: switch off **Strong Anonymization** |

Read the first row as where you are by default. While Post Quantum Encryption
is on the client is fail-closed: a provider it cannot seal a session with is
skipped, not used in the clear, so what a mismatch costs you is that provider,
not your confidentiality. Switching the setting off is what puts you in the
second row. No app yet shows a per-connection sealed-or-not verdict, so the
setting, not the session, is what tells you where you are. Limit: nothing
verifies that the providers offered to you are independent of each other or
of the operator, and the operator can run providers itself. The
[threat model](/docs/threat-model) works these rows against named
adversaries, including a hostile operator, and is explicit
about where each one fails.

### Custom DNS

Under the Connect tab's details lives a full DNS control panel. DNS is the
internet's phonebook, the lookup that turns a name like ur.io into a network
address, and whoever answers those lookups (the resolver) sees the name of
every site you visit. The default is the most secure arrangement: encrypted
DNS over HTTPS, resolved through the tunnel. Everything else is a trade you
can make:

- **DNS over HTTPS (remote).** DoH resolved on the far side of the tunnel.
  The default, and the most private: the resolver sees a provider's address,
  not yours.
- **DNS over HTTPS (local).** DoH resolved from your device directly.
- **Unencrypted DNS (remote / local).** Classic UDP DNS, through the tunnel
  or straight from the device, for networks and resolvers that need it.
- **Local DNS fallback.** Races a local resolver while the tunnel starts, so
  name lookups do not stall during the handshake. When it is off, DNS only
  ever resolves through the tunnel.

You can edit the resolver lists yourself (remote and local DoH URLs, remote
and local DNS servers, IPv4 and IPv6). Two conveniences on top:

- **Per-country recommendations.** The strongest settings are known not to
  work in some countries. When you connect somewhere with a known
  recommendation, the screen says so and offers a one-tap "Use recommended
  settings", and a one-tap restore back to the most secure defaults.
- **Suggested servers.** A curated list of remote DNS servers, with the ones
  suggested for your connected country marked in its color. Turning one on
  adds it to your remote resolver list.

### Split rules

Split rules let you route specific traffic outside the tunnel or pin it in
place, at the domain and IP level:

- While connected, the screen shows live routing activity. Tap a domain to
  route it locally (bypassing the tunnel, so that site then sees your real
  address), or hold it to a single provider so that site sees one stable
  address for longer instead of your usual plural exit. Useful for banks and
  logins that challenge any address change.
- Rules apply to the whole co-associated network cluster around a domain, so
  related hosts and CDN traffic are caught together rather than leaking one
  subdomain at a time.
- Rules persist and can be removed any time from the same screen.

Limit: **per-app split tunneling is not available on iOS** (Android and
Windows have it). iOS does not give VPN apps a supported way to include or
exclude traffic by app, so on iPhone and iPad split rules operate on domains
and IPs, not apps.

### Provide mode

Sharing your spare bandwidth is a four-way **Provide mode** picker in
Account → Settings → Connections, set to **Never** until you change it:

| Mode | What it carries |
|---|---|
| **Never** | Nothing. The default. |
| **Auto** | Public traffic while you are connected yourself; only your own devices when you are not |
| **Always** | Public traffic, connected or not |
| **Network** | Only your own network's devices, unpaid. The narrowest sharing the app implements |

Some ground rules. Providing uses Wi-Fi only unless you flip **Allow
providing on cellular network** in the same section, so it never touches
your data plan by surprise. It runs inside the tunnel process, so it keeps
working while the phone sits idle. The traffic you carry is other people's
encrypted sessions: you cannot read it, and it cannot touch your device.
Abuse enforcement runs on your device at egress, where traffic leaves for
the internet: BitTorrent and known attack patterns are dropped there. The
drop records nothing, no destination, no domain, no contents, though a
plaintext BitTorrent match also sends the operator a flag carrying the
device id and a boolean, nothing more. Public traffic you carry is metered
under signed contracts, and providers participate in the UR protocol.
[ur.xyz](https://ur.xyz) documents how the rewards work.

### Account

Your identity and plan live here:

- **Plan.** Free or Pro, the balance you have left, the Upgrade path, and a
  running total of what your connection has carried for the network.
- **Redeem Balance Code.** A one-time data grant, no subscription required.
- **Profile**, **Settings**, **Wallet**. Settings is the deep one:
  seedphrase, sign-in methods, device name, Connections (provide mode, the
  cellular allowance, the kill switch, **Blocked locations**: countries you
  never want to exit through), notifications, account deletion, and a "Uses
  the UR Protocol" link to [ur.xyz](https://ur.xyz) for how providers are
  rewarded.
- **Check my IP.** Opens [ur.io/ip](https://ur.io/ip), the way to confirm
  from outside the app that your traffic really is exiting somewhere else.
- **Post Quantum Identity.** The panel below, and the route to the
  identities of the providers you are connected to.

### The post-quantum identity panel

The panel at the bottom of Account shows your device's identity as an
identicon (a picture derived from the key, easier to eyeball than hex) with
its key hash and client id beneath, each tapping to copy, a share sheet, and
a deck of the peers you are connected to that opens the full list. It states
its own purpose: if a peer's key ever looks different from the one stored
locally, the operator in the middle cannot be trusted. This makes operator
blindness checkable.

The encryption it names is the **Post Quantum Encryption** switch in the
connect drawer, on by default, so your client seals traffic directly to the
provider from the first connection. The session is mutually authenticated
TLS 1.3 keyed with **X25519MLKEM768** (a classical curve hybridized with
NIST's ML-KEM), so the operator relays bytes it cannot read. The responder
side is opportunistic: every current provider build enables it, so one
provider can serve sealed and unsealed consumers alike. Your side is not.
While the switch is on the client is fail-closed, and a provider it cannot
seal a session with is skipped rather than used in the clear. No app yet
shows a per-connection sealed-or-not verdict. Identities stay Ed25519.

### Leaderboard

Rankings of top providers by data moved. If you provide, you can appear
here, publicly or privately, your choice.

### Support

Titled "Get in touch": a feedback box, a star rating, an optional **Attach
logs to feedback** switch, and a Discord invite for live help. Plans are not
here; upgrading lives on the Account tab.

## Siri and Shortcuts

The app registers two App Intents: **Connect URnetwork VPN** and
**Disconnect URnetwork VPN**. They appear in the Shortcuts app, work by
voice ("Hey Siri, connect URnetwork"), and chain into automations, like
connecting when you leave home Wi-Fi.

## Starting with no email, and the phrase that keeps it

**Create Instant Account** on the login screen gives you a real, permanent
network in one tap. No email, no phone, no password, as the screen itself
says. What secures it instead is a **seedphrase**: a list of words the
platform generates and shows you exactly once, on the screen right after
creation, keeping only hashed forms of it afterwards. Save it there and
then. It is the only way back in from a device that is not already signed
in. While you still have one that is, Settings → Seedphrase mints a fresh
phrase and retires the old one. With it saved, the account survives a
reinstall or a new iPhone, plan and history intact, which a device-local
identity never does. None of this is second-class: Settings → Sign-In
Methods attaches an email, phone, Apple or Google sign-in, or a wallet to
the very same network, keeping your data balance and history. The anonymity
is in the account, not the payment: a subscription bought in the app is tied
to your Apple account, a balance code to nobody.

## Troubleshooting

### The VPN configuration approval

The first connect asks to add a VPN configuration. If you declined it, the
tunnel can never start. Approve it on the next connect attempt, or check
Settings → General → VPN & Device Management, where the URnetwork
configuration should be listed.

### Multiple VPN profiles, and how the app manages them

iOS can accumulate more than one URnetwork VPN profile over reinstalls and
upgrades. The app expects this: on connect it enumerates every profile,
resets and retries any that fails to start, then moves on to the next. If a
tunnel is already running it adopts that one over the device RPC instead of
restarting it. Broken profiles are reset or removed, with a cap on removals
so cleanup can never run away, and every profile operation is
deadline-bounded so a wedged system daemon cannot hang the app. All of it is
automatic. It is described here only so the profile list in Settings makes
sense when you look at it.

### "Failed to load VPN profiles" (error 12)

If connecting fails with **"Failed to load VPN profiles"** (error code 12),
the system's VPN preferences store is refusing to enumerate profiles, a
state the app cannot repair from inside. Fix it by hand:

1. Open Settings → General → VPN & Device Management.
2. Remove the URnetwork VPN configuration(s).
3. Return to the app and connect. You'll be asked to approve a fresh
   configuration, and the tunnel starts clean.

### How the kill switch works here

The app ships a **Kill switch** toggle in Account → Settings → Connections,
the same SDK control every URnetwork app has, off until you turn it on. With
it on, the client refuses to fall back to your local route, so traffic stops
rather than leaking outside the tunnel. What iOS does not give it is
OS-level enforcement. The app does not set `includeAllNetworks`, so if the
tunnel process dies unexpectedly, iOS restores normal networking rather than
blocking traffic. Supervision, retries and profile recovery keep the tunnel
healthy, but the app does not ask the OS to hard-fail closed. If your threat
model requires a guaranteed fail-closed network, plan for that.

### Reading the tunnel's logs

The tunnel extension logs to the unified system log, not to files. To watch
it:

1. Connect the device to a Mac and open **Console.app**.
2. Select the device, and in the Action menu enable **Include Info
   Messages** and **Include Debug Messages**. The interesting lines are at
   those levels.
3. Filter by the `network.ur.extension` subsystem or search "URnetwork".

### Sleep and background behavior

The tunnel is configured with `disconnectOnSleep` off: the VPN stays up
across device sleep rather than re-handshaking every time the screen locks.
With the two-process design it also survives the app being swiped away.
Disconnecting is something you do with the button, Siri, or by removing the
profile.

## Where next

- [Getting started on iOS](/docs/getting-started-ios) for the short path.
- [The macOS tour](/docs/tour-macos) for the same engine, Mac-shaped.
- [FAQ](/docs/faq) and the [overview](/docs/overview) for the network
  itself.
