# The Windows app, in depth

This is the deep dive: every major surface of the Windows app, what it
controls, its defaults, and how to fix it when something breaks. It assumes
you have already installed and connected. If not, start with
[getting started](/docs/getting-started-windows). For how the network behind
the app works, read the [overview](/docs/overview).

The Windows client is two programs with different privileges, a kernel driver
for per-app split tunneling, and a UI aligned with the macOS app. All of it is
open source at [github.com/urnetwork/windows](https://github.com/urnetwork/windows).

## Settings at a glance

The defaults protect you without configuration. Every control below lives in
the connect drawer, except the app split rules under Settings.

| Setting | Default | Effect | Main cost |
|---|---|---|---|
| Connection mode | Auto | picks the provider windows; Auto runs quality and speed together | Web or Streaming narrow to one window |
| Strong Anonymization | On | hides your source IP from the provider | more latency |
| Post Quantum Encryption | On | encrypts from the app to the provider | skips providers it cannot seal to |
| Kill switch | Off | stops local fallback when the tunnel is down | no traffic while providers fail |
| Fixed IP | Off | one provider, one exit address | no failover; inactive in Auto |
| Block ads and trackers | Off | filters ad and tracker traffic | filtering can break some sites |
| Custom DNS | encrypted DoH via the tunnel | DNS stays encrypted and inside the tunnel | loosening it is the trade |
| Provide mode | Never | shares spare bandwidth as an exit for others | strangers' traffic egresses from your IP |
| App split rules | empty | listed apps bypass the tunnel | their traffic is unprotected |
| Split rules (domain/IP) | empty | listed destinations use your local connection | that traffic is unprotected |

Caveats that go with the table:

- Turning **Strong Anonymization** off is direct mode: the client talks
  straight to the provider and gets faster, and that provider then sees your
  real address. The default protects your identity. Spend it deliberately.
- Switch settings persist across connection modes. Fixed IP is inactive until
  you pick Web or Streaming.
- The kill switch also decides what happens to a packet the security filter
  drops (see provide mode): on, it is blocked outright; off, it leaves by your
  normal route.
- Deleting your account is not on Windows. Do that in the
  [web app](https://ur.io/app), which manages the same account.

## Two processes, one tunnel

The app is split into two programs on purpose:

- **URnetwork.exe.** The WinUI 3 tray app you interact with. It runs
  unprivileged, in your user session: a flyout from the system tray plus a
  full window for connect, account, wallet, leaderboard, support, and
  settings.
- **urnetworkd.** A Windows service running as LocalSystem, Windows' most
  privileged built-in account: the power needed to create network adapters
  and set routes, which the app you click never gets. It embeds the URnetwork
  SDK, owns the **wintun** virtual adapter, pumps packets, applies routes,
  DNS and MTU, and keeps its own control traffic off the tunnel.

They talk over two channels, each doing one job:

1. **Device RPC.** The app's `DeviceRemote` drives the service's `DeviceLocal`
   over the SDK's own RPC: a mutually authenticated TLS WebSocket on
   loopback. Both ends prove their identity with certificates and the
   connection never leaves your machine, so another local program cannot
   simply connect and drive the service. Everything you do in the UI travels
   this channel: connect, pick a location, toggle providing.
2. **A named pipe** (`\\.\pipe\urnetwork.control`). It carries only lifecycle
   and configuration: start and stop the tunnel, apply split-tunnel rules,
   log out. It mirrors how the macOS app talks to its network extension, so
   the two codebases stay aligned.

Why the split: a VPN tunnel needs privileges, and a UI should never have
them. Nearly every Windows VPN is two programs for this reason. You approve
one UAC prompt, at install time, when the service registers. Day-to-day use
never asks for admin.

It also means your protection does not depend on the window being open. Close
the window and it hides to the tray. Quit from the tray menu and the tunnel
is still up, because the service owns it. Only **Disconnect**, a sign-out, or
stopping the service brings it down.

## The window

The nav runs Connect, Account, Wallet, Leaderboard, Support, Settings.

**Connect** is the globe and the drawer beneath it. The drawer is where the
session lives:

- **Selected location and peers.** What you are connected through, and how
  many providers are currently carrying your traffic. Click the peer count to
  open the connected-providers sheet: a globe over one row per provider, with
  its client id, city/region/country, coordinates, and how long it has been
  in your window, plus an inline remove.
- **Connect options.** The connection mode (**Auto**, **Web**, or
  **Streaming**: how aggressively the client trades provider count for
  throughput) and the four switches from the table above: **Fixed IP**,
  **Strong Anonymization**, **Post Quantum Encryption**, and the
  **kill switch**.
- **Client statistics** and **Local statistics** cards, each opening a detail
  sheet: live contracts on one side, split rules and blocked-traffic activity
  on the other.
- **Custom DNS.** A status card over the full resolver editor (below).
- **Block ads and trackers.** One switch.
- **Plan and usage.** Your tier, the used/pending/available bar, the daily
  allowance, referrals, **Get UR Pro**, and redeeming a balance code.

**Account** carries plan and usage, redeemed balance codes, your network
name, and referrals. **Wallet** covers your plan and upgrade path, and the
wallet settings for participating in the UR protocol
([ur.xyz](https://ur.xyz)). Bittensor wallets can be attached but are
recorded for future use only, and the app says so where you would expect it
to. **Leaderboard** ranks provider networks. **Support** sends feedback and
reaches [feedback.ur.io](https://feedback.ur.io). **Settings** holds the app
split rules and sign-out.

One caveat on the way in: the sign-in screen still offers **Try Guest Mode**.
It creates an ordinary, permanent account, but the Windows app throws away
the recovery seedphrase the server hands back, and there is no seedphrase
sign-in here. Add an email or a wallet to that account before you rely on it.

## The tray

Classic Win32 tray behavior, because WinUI has no tray API of its own:

- **Left-click** opens the window positioned next to the tray icon, flyout
  style.
- **Right-click** gives a menu with connect/disconnect, show, and quit.
- **Four icon states** mirror the macOS menu-bar matrix (connected or not,
  providing or not), each in light and dark artwork, switched to match your
  taskbar theme.

## Picking providers, and what that means

The location picker is the SDK's own grouping: connected network peers first,
then best-available, then **countries** with live provider counts. Type in
the search box and the results re-section into top matches plus **regions**,
**cities** and **devices**. Targeting is city-level; you reach a city by
searching for it, not by scrolling to it.

Two protections stand behind every relayed session, and neither needs a
setting touched. The provider egressing your traffic never learns who you
are, because the operator sits in between. The operator cannot read the
packets it forwards, because Post Quantum Encryption seals the session end to
end to the provider by default. Together, no single party holds both your
identity and your activity. The full path, including the extender leg that
carries your encrypted session to the operator, is in the
[overview](/docs/overview).

| Mode | Operator sees | Provider sees | Default and availability |
|---|---|---|---|
| **Relayed sealed** | account and source connection, provider association, ciphertext with timing and volume | destinations it egresses, a device/contract id, **not** your real IP | the shipped default: Post Quantum Encryption on in the drawer |
| **Relayed standard** | account and source connection, provider association, inner destinations and packet bytes | destinations it egresses, 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 |

The [threat model](/docs/threat-model) works these rows against named
adversaries and is explicit about where each one fails.

In **Auto** two provider windows run side by side, so traffic typically exits
through 3–8 providers at once, with each site pinned to one. A single
provider only ever sees a slice of your session. Web and Streaming each run
one window, narrower. **Fixed IP** collapses it to one provider and one exit
address.

## Per-app split tunneling and the driver

"Let this app bypass the VPN", so a game keeps its lowest ping or a
VPN-hostile banking app stays on your normal connection, cannot be done well
from user space on Windows. The redirect decision has to happen where the
socket is created, inside the network stack. So the app ships
**SplitTunnel.sys**, a Windows Filtering Platform (WFP) callout driver:

- **Clean-room.** Implemented from first principles against Microsoft's
  documentation and public specs, not derived from another vendor's driver.
- **MPL-2.0 licensed**, developed in the same open repository as the app.
- **Process-based, never destination-based.** The driver registers exactly
  one callout, at Windows' bind-redirect layer. When any process opens a
  socket, the driver compares that process's executable path against your
  exclusion list and, on a match, rewrites the socket's local address to the
  physical interface, so the flow leaves through your normal connection. It
  reads no remote address at all. The service exempts its own traffic by
  process id.
- **Child processes inherit.** A launcher's helper processes follow the app
  you excluded.
- **Fail-open, never blackhole.** If no physical interface is set,
  redirection goes inert rather than dropping traffic.

Manage the list under **Settings → app split rules**. Three limits. Sockets a
process already had open keep their existing path until they reconnect. An
excluded app's DNS lookups still go through Windows' shared resolver service,
so they can follow the tunnel even when the app itself does not. And the
driver is a build-time option: an MSI packaged without it installs a working
tunnel with no per-app rules.

Separately, the **split rules sheet** in the connect drawer does domain- and
IP-level rules through the tunnel itself, the same surface the Apple and
Linux apps have. The two compose: the driver decides per app, the rules
decide per destination.

## Keeping the service off its own tunnel

A tunnel process has a bootstrapping problem: its own traffic to the platform
must not go through the tunnel it creates, or the first packet loops forever.
The service solves this at the socket layer. The SDK exposes an egress
binding hook, and the service pins its own control and relay sockets to the
physical interface, tracked by an egress monitor that recomputes the right
interface on every network change (Wi-Fi to Ethernet, adapters appearing and
disappearing).

## Routes and DNS

When the tunnel comes up, the service does not delete your default route. It
outbids it: the whole IPv4 space **except** the private LAN ranges
(10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) is installed as a set of
more-specific routes through the tunnel adapter. They win over your existing
default without touching it, teardown is just removing them, and your printer
and NAS keep working locally. The tunnel adapter gets its address and an MTU
of 1440 from the SDK, and the network's resolvers are set on that adapter.

Three limits you can hold the app to:

- **DNS is set per adapter, and Windows resolves per adapter.** The app's own
  DNS settings (the Custom DNS sheet, whose default is encrypted
  DNS-over-HTTPS resolved through the tunnel) are the meaningful protection
  here. If you run an unusual resolver setup, check where your queries
  actually go.
- **The tunnel carries IPv4.** IPv6 is not routed through it today, so on an
  IPv6-enabled network a v6-capable site can still see your real address. If
  you need everything to exit through a provider, disable IPv6 on the
  connection.
- **Failing closed is a switch, not an assumption.** Leave the kill switch
  off and a stopped tunnel means Windows falls back to your normal
  connection. Turn it on and traffic stops instead. It is the SDK's
  `SetRouteLocal` primitive inverted, the same one every URnetwork app binds,
  and it ships off by default.

## Custom DNS

The same cross-platform resolver panel the Apple and Linux apps have. The
default is the strictest option: encrypted DNS over HTTPS, resolved through
the tunnel. You can deliberately trade it off: DoH or unencrypted, resolved
remotely or locally, with editable server lists, a local-DNS fallback switch
that races a local resolver while the tunnel starts so lookups do not stall,
and one action to restore the secure defaults.

## Provide mode

Providing is off by default and lives in the connect drawer: **Auto**,
**Always**, **Network** (your own account's devices only), or **Never**.
Providers participate in the UR protocol; [ur.xyz](https://ur.xyz) documents
how rewards work.

What protects you when you share is the connect engine's open-source
`ip_security` layer. It inspects traffic on your own egress and drops
DMCA-class traffic (stateful BitTorrent and file-sharing signatures,
opaque-protocol drops) and CFAA-class traffic (attack and intrusion
patterns) before it leaves your connection. A match is a dropped packet, with
no destination, domain or contents recorded. A plaintext BitTorrent signature
on traffic you carry for someone else additionally sends the operator an
abuse flag holding the peer's device id and a boolean, nothing else, and the
operator ships no handler for it today. The same filter runs on your own send
path whether or not you provide, and your own traffic is never reported.
Sealing does not bypass the filter, because it runs where traffic exits. The
[overview](/docs/overview) covers the layer in full.

## What Post Quantum Encryption actually does

Your client seals traffic end to end to the provider over a session
negotiated with **X25519MLKEM768** (hybrid classical plus ML-KEM). That
sealed leg is what makes the middle hop blind: the operator carries bytes it
cannot read. It is on by default and fail-closed: while it is on, the client
will not send or accept application data in the clear, so a provider it
cannot establish a sealed session with is skipped rather than used unsealed.
Every current provider build enables the responder side, so in practice the
seal is automatic. The cost is availability, not confidentiality — you can
lose a provider, never your encryption, and there is no silent downgrade.
Switch the setting off and traffic can take the standard TLS-to-platform
path again. Identity signatures remain Ed25519 and the cipher is
AES-256-GCM. "Post-quantum" means this key exchange, nothing broader.

Limit: the Windows app has no identity-inspection panel. There is no key
fingerprint to compare out of band, and no per-connection verdict telling you
whether this session sealed. The connected-providers sheet is the nearest
surface.

## Signing and updates

- **Windows 10 21H2 or later and Windows 11**, x64 and ARM64, as a
  per-machine MSI from the release page. ARM64 is a native build, not
  emulation.
- **App, service, and installer** are Authenticode-signed.
- **The driver** needs more: an EV certificate plus Microsoft's attestation
  signing. Windows only loads attestation-signed drivers, so this is the load
  gate, not ceremony.
- **The driver ships inside the MSI.** Nothing is fetched at runtime; what
  the installer contains is what runs. Pinned third-party dependencies
  (wintun) are verified by hash and upstream signer before packaging.
- **Updates are the service's job, not the Store's.** The Microsoft Store
  does not push updates for EXE/MSI listings, and an MSIX package (the kind
  the Store does auto-update) cannot cleanly carry a kernel driver. So the
  update path runs through `urnetworkd`: fetch, verify the signature, swap
  the binaries. No UAC prompt per update, and security fixes do not wait on
  store review. Windows guards this pattern too: a service binary can only be
  replaced when old and new are signed by the same publisher.

## Troubleshooting

### The app says it can't reach the service

The tunnel lives in `urnetworkd`. Check it is running in **Services** (or
`sc query urnetworkd`); it is registered to start automatically and to
restart itself twice on failure. If it is stopped and will not start,
reinstall the MSI, which re-registers the service.

### Connected, but a specific app has no internet

Check **Settings → app split rules**. An app on the exclusion list bypasses
the tunnel by design, and if you excluded something that then could not reach
a service on your normal connection, that is the rule working. Changes take
effect on that app's next connection, because already-open sockets keep their
path, so restart the app.

### Per-app split tunneling isn't available

The driver is an optional feature in the installer. Re-run the MSI and make
sure the split-tunneling feature is selected. Kernel drivers also require the
attestation-signed build; a self-built driver will not load on a machine that
is not in test-signing mode.

### Sites still see my real address

Almost always IPv6. The tunnel carries IPv4 today; disable IPv6 on the
network adapter and retest. Second most likely: a per-adapter DNS path, which
the Custom DNS sheet's default (DoH through the tunnel) is designed to close.

### Traffic stalls after switching networks

Moving between Wi-Fi and Ethernet changes which interface the service must
pin its own sockets to. It watches for this and recomputes, but if a session
is wedged, disconnect and reconnect to rebuild cleanly.

### Nothing happens when I quit

That is the design: quitting the tray app leaves the tunnel running in the
service. Use **Disconnect**.

## Elsewhere

The [overview](/docs/overview) explains the network end to end: providers,
contracts, what each party can and cannot see, and the encryption. The
[FAQ](/docs/faq) answers the common questions. Other platforms:
[Android](/docs/getting-started-android), [iOS](/docs/getting-started-ios),
[macOS](/docs/getting-started-macos), [Linux](/docs/getting-started-linux),
and the [browser](/docs/getting-started-browser).
