# VPN for the whole computer (zev vpn)

> sudo zev vpn on sends every program through your own proxy server, with its DNS and IPv6, a kill switch, sites that need no proxy kept direct, and a leak test (zev vpn check) that proves nothing gets around it.

Source: https://zaryn.xyz/docs/en/vpn

`zev proxy share` gives apps a proxy port they can use if they're set up for it. `zev vpn` doesn't need any setup: **every program on this computer**, its DNS lookups and its IPv6, goes through your proxy server, the same one `zev proxy use` chose. It is Linux only for now.

```bash
sudo zev vpn on --kill-switch    # everything through the proxy; nothing leaks if it stops
zev vpn check                    # prove it: TCP, UDP (WebRTC), DNS, IPv6
sudo zev vpn off                 # back exactly as it was
```

```diagram
type: graph
title: What the VPN carries, and what stays direct
alt: Every program's traffic goes into the zev0 interface, which the Xray engine reads and sends through your proxy server to the internet; the LAN, Docker's networks and excluded sites go direct; the engine's own connections carry a mark so they don't loop
legend: path=Through the proxy; path2=Direct on purpose; new=The engine's own (marked)
start: Every program
caption: One interface, zev0, catches everything. Point at each piece for what it is.
height: 62
---
box This computer | 2 2 56 58 | dim
node apps | every program | 12 12 | folder | accent | Browsers, games, Telegram, apt, Docker pulls: no proxy settings in any of them
node dns | their DNS | 12 30 | log | | Every question on port 53 is taken in by the tunnel, wherever it was sent
node lan | LAN, Docker | 12 48 | host | good | Anything the computer has a more specific route for stays direct
node tun | zev0 | 34 21 | router | | A TUN interface: the routes send everything into it
node xray | engine (Xray) | 48 21 | collector | | Runs your link; its own connections carry mark 7701, so they leave by the normal route
node proxy | your proxy server | 74 21 | server | | Yours: Zaryn carries none of its traffic
node web | the internet | 94 12 | cloud
node ex | excluded sites | 94 40 | cloud | good | --exclude, and the sites zev proxy learn found need no proxy on this network
link apps tun | | path
link dns tun | | path
link tun xray | | path
link xray proxy | | new
link proxy web | | path
link xray ex | | path2
note 30 56 | nothing to set in any app | accent
```

## Start in one minute

```diagram
type: cards
title: From nothing to a VPN
---
1️⃣ | A server | zev proxy add home 'vless://…' --use, or a subscription: zev proxy sub add myvpn <url> (see the proxy guide)
2️⃣ | The engine | zev proxy engine install, once (Xray, checked against its SHA-256)
3️⃣ | On | sudo zev vpn on --kill-switch: a system service, on across restarts
4️⃣ | Proof | zev vpn check: what sites, WebRTC and DNS see now
```

`sudo` only sets up the network: the proxy, its fixes and routes stay yours (`~/.config/zev`), and the VPN follows them when you change them, without being turned off and on again.

## Every command

| Command | Example | What it does |
|---|---|---|
| `sudo zev vpn on` | `sudo zev vpn on` | every program through the proxy, as a service (`zev-vpn`) that starts with the computer |
| `--kill-switch` | `sudo zev vpn on --kill-switch` | if the VPN stops for any reason, nothing goes out directly; only the LAN works until it's back |
| `--exclude` | `sudo zev vpn on --exclude bank.example.com,192.0.2.0/24` | these names, addresses or ranges go direct |
| `zev vpn status` | `zev vpn status` | on or off, through which server, since when, restarts and self-repairs |
| `zev vpn check` | `sudo zev vpn check` | the leak test below; with `sudo` it also shows this network's own address, to compare |
| `sudo zev vpn off` | `sudo zev vpn off` | the interface, routes, rules and firewall table removed; nothing left behind |
| `direct --` | `sudo zev vpn direct -- steam` · `sudo zev vpn direct -- firefox --private-window` | one program (and what it starts) outside the VPN; the rest stays in |
| `direct` | `sudo zev vpn direct` | what runs outside the VPN now |
| `pause` | `sudo zev vpn pause` · `sudo zev vpn pause 1h` · `sudo zev vpn pause forever` | everything directly for a while (10 minutes if you don't say), the kill switch too, then back by itself |
| `resume` | `sudo zev vpn resume` | end a pause now |
| `trust` | `sudo zev vpn trust` · `sudo zev vpn trust ls` | on this network the VPN steps aside; on any other it carries everything |
| `untrust` | `sudo zev vpn untrust this` · `sudo zev vpn untrust all` | the VPN carries everything there again |
| `zev proxy start --tun` | `zev proxy start --tun --kill-switch` | the VPN, the shared port and the desktop setting, in one command (asks for sudo) |
| `zev proxy top` | `zev proxy top` | live traffic: the VPN, each server, what went direct |
| `zev proxy usage` | `zev proxy usage quota 50G` | the proxy's data by day, a monthly limit, where it's heading ([usage](/docs/en/proxy#data-and-a-quota-zev-proxy-usage)) |
| `zev proxy learn on` | `zev proxy learn on` | sites that work without the proxy on this network go direct ([learn](/docs/en/proxy#only-what-needs-it-zev-proxy-learn)) |
| `zev proxy why` | `zev proxy why youtube.com` | which way one site goes, and why ([why](/docs/en/proxy#which-way-and-why-zev-proxy-why)) |

## The leak test: zev vpn check

A VPN that's on isn't necessarily a VPN that covers everything. `zev vpn check` asks the internet what it sees, the ways a website, a browser and a DNS server would:

```text
$ sudo zev vpn check
zev vpn check  a leak test: what the internet sees of this computer

  ✓ the VPN is on (zev0), through vless proxy.example.com:443 tcp+tls
  ✓ sites see 185.220.101.4 (DE)
      this network's own address is 198.51.100.34 (FR): hidden
  ✓ UDP too (what WebRTC in a browser shows): 185.220.101.4
  ✓ DNS: a question to an address with no DNS server was answered inside the tunnel; no DNS question leaves around it
  ✓ IPv6: none on this network, nothing to leak
  ✓ kill switch: on; if the tunnel drops, nothing leaves
    direct on purpose (--exclude): bank.example.com

  No leaks found.
```

```diagram
type: cards
title: What each line proves
---
🌐 | Sites see | an ordinary connection to Cloudflare's trace page, from a program with no proxy settings: the address every website sees
🏠 | This network's own address | with sudo, the same request marked to go around the tunnel: if both are the same, traffic isn't in the tunnel
🎥 | UDP (WebRTC) | a STUN request, the way a browser's WebRTC finds your address for calls: the classic VPN leak. If UDP comes out elsewhere, sites can see your real address
🔎 | DNS | a DNS question sent to 192.0.2.53, an address where no DNS server exists. Only something that takes in every DNS question can answer: the tunnel. So no program's DNS gets around it
6️⃣ | IPv6 | a public IPv6 address on this computer is a way around an IPv4-only tunnel: the kill switch closes it
🔒 | Kill switch | on or off, and what happens if the VPN stops
```

A `✗` line is a leak, with what to do about it; `zev vpn check` then exits with status 1, so scripts can rely on it. With the VPN off, it shows what leaves the computer now, for comparison.

## The kill switch

```diagram
type: flow
title: When the VPN stops, with --kill-switch
---
Running | Everything goes through zev0 and the proxy | good | 🛡️
~ the engine crashes, the server goes away, the service is killed
Closed | A firewall table (inet zev_vpn) lets nothing out but the LAN and the proxy server itself | warn | 🔒
~ systemd starts the service again
Back | The engine is running, traffic flows through the tunnel again; nothing went out directly in between | good | ✅
~ sudo zev vpn off
Off | The table, the routes and the interface are removed: the computer is as it was | dim | 🏠
```

Without `--kill-switch`, traffic goes out directly while the VPN is down, which is better on a network where you'd rather be online than private.

## What goes direct

```bash
sudo zev vpn on --exclude bank.example.com,192.0.2.0/24   # these names and ranges go directly
sudo zev vpn on --kill-switch --exclude intranet.example  # and nothing else gets out if the VPN stops
sudo zev vpn run --for 60                                 # the VPN in this terminal for a minute (what the service runs; set up with sudo zev vpn on first)
```

- **Your LAN, Docker's networks, private networks**: anything with a more specific route than the default, so the printer, the NAS and containers keep working.
- **`--exclude`**: names (and every name under them), addresses and CIDR ranges you list.
- **Your routes**: `zev proxy route direct …` and the others apply to the VPN as well.
- **One program**: what you started with `sudo zev vpn direct -- <program>` ([below](#one-program-outside-zev-vpn-direct)).
- **During a pause, and on trusted networks**: everything ([pause](#a-break-zev-vpn-pause), [trust](#trusted-networks-zev-vpn-trust)).
- **What zev learned**: with [`zev proxy learn on`](/docs/en/proxy#only-what-needs-it-zev-proxy-learn), sites measured to work without the proxy on this network go direct: they're faster, and they don't use the proxy's data. Through the VPN, zev learns from the names programs look up.

`zev proxy why <site>` says which of these applies to one site.

## One program outside: zev vpn direct

Some programs shouldn't go through the VPN: a bank that refuses foreign addresses, a game that needs the lowest latency, a video call on the office network. Run just that program outside it; everything else stays in:

```bash
sudo zev vpn direct -- steam
sudo zev vpn direct -- firefox --private-window
sudo zev vpn direct -- curl -s https://example.com/   # check: this one goes directly
sudo zev vpn direct                                    # what runs outside now
```

```text
Outside the VPN now
  48213    steam
  48290    steamwebhelper
```

The program runs as you (not as root), and everything it starts stays outside too. It works with the kill switch on: its traffic is marked as allowed to go directly, and only its traffic. Names it looks up still go through the VPN's DNS, so nothing about the rest of the computer changes.

```diagram
type: flow
title: Two programs, two ways
---
A program | everything else, as before | | 🌐
~ into the tunnel
zev vpn | through your proxy server | accent | 🔒
~
steam | started with zev vpn direct | good | 🎮
~ marked: the computer's own route
Directly | out through Wi-Fi or the cable, the kill switch lets it pass |  | ➡️
```

How: the program starts in its own cgroup (`zev-direct`); one firewall rule marks that cgroup's connections, and marked connections take the computer's own route, the same way zev's engine reaches the proxy server. `sudo zev vpn off` removes the rule and the cgroup.

## A break: zev vpn pause

Need the real connection for a few minutes (a captive portal, a site that blocks VPNs, a speed test of your own line)? Pause it; it comes back by itself:

```bash
sudo zev vpn pause            # 10 minutes
sudo zev vpn pause 30s
sudo zev vpn pause 1h30m
sudo zev vpn pause forever    # until you resume it
sudo zev vpn resume           # end the pause now
```

```text
⏸ VPN paused for 1 min: traffic goes directly, the kill switch is off too.
  The engine keeps running, so it comes back at once. sudo zev vpn resume ends the pause now.
```

`zev vpn status` shows how long is left. During a pause the kill switch steps aside as well (that's the point of a pause); it's back with the VPN.

## Trusted networks: zev vpn trust

At home you may not want the VPN; on a café's Wi-Fi you do. Mark the networks you trust, and the VPN steps aside there by itself, and carries everything on any other network:

```bash
sudo zev vpn trust            # the network you're on now
sudo zev vpn trust ls
sudo zev vpn untrust this     # or a name from the list, or all
```

```diagram
type: flow
title: The same laptop, three networks
---
Home | trusted: traffic goes directly | good | 🏠
~ you leave
Café Wi-Fi | not trusted: everything through the VPN, the kill switch on | accent | ☕
~ you're back
Home | directly again, by itself | good | 🏠
```

A network is recognized by its router (its address and hardware address), checked every five seconds, so the switch happens as soon as you join another one. This only matters while the VPN is on: trusting a network never turns the VPN on or off by itself, and nothing starts at boot unless you ran `sudo zev vpn on`.

Every pause, trusted network and return is written to the history ([zev proxy history](/docs/en/proxy#how-did-it-hold-up-zev-proxy-history)).

## How it works

```diagram
type: sequence
title: One connection through the VPN
lanes: Program | zev0 + engine | Proxy server | Site
alt: A program connects normally; the routes send its packets into zev0; the engine reads them, finds the site's name, checks the routes, and sends the connection through the proxy server with mark 7701 so it leaves by the normal route; the site answers through the proxy
---
Program -> zev0 + engine : connect to 104.16.124.96:443, as always
zev0 + engine -> zev0 + engine : the name from the TLS hello (www.cloudflare.com), then the routes: direct or proxy
zev0 + engine -> Proxy server : through your link, marked 7701 so it doesn't loop
Proxy server -> Site : the connection, from the server's address
Site --> Program : the answer, back the same way
note zev0 + engine : DNS on port 53 never leaves: it is answered by the engine, over HTTPS | good
```

zev creates the `zev0` interface (172.19.0.1/30), adds policy routing rules (mark 7701 to the main table, everything else to table 7701, which points at `zev0`), points systemd-resolved at the tunnel's DNS (172.19.0.2) and runs the engine as a systemd service from its own root-owned copy in `/var/lib/zev/vpn`. `sudo zev vpn off` removes every one of these.

## It fixes itself

Every 30 seconds the service checks that traffic really gets through. After three failures in a row it notifies you, runs [`zev proxy doctor`](/docs/en/proxy#when-it-doesnt-work-zev-proxy-doctor) (DNS lies, a blocked port, SNI filtering, a clock that's off), saves the fix for this network and restarts the engine with it. A server that dies is replaced by the next of a pool on its own. With the kill switch on, zev doesn't pause the VPN to run the doctor.

## With zev dns

The VPN already takes every DNS question into the tunnel. [zev dns](/docs/en/dns) is for when the VPN is off, or for names you send direct: it finds which resolvers tell the truth on this network, checks DNSSEC signatures itself, and keeps the network's own DNS behind them. They work together; neither changes the other's settings.

## When something's wrong

| You see | What it means | What to do |
|---|---|---|
| `zev vpn check`: UDP comes out elsewhere | the proxy server's protocol or setup doesn't carry UDP, or something sends it around | a link that carries UDP (VLESS, Trojan, Hysteria2, WireGuard); `--kill-switch` keeps it from leaking meanwhile |
| `zev vpn check`: IPv6 warning | this network gives you public IPv6 and the tunnel is IPv4 | `sudo zev vpn on --kill-switch` |
| Nothing loads, `zev vpn status` says failing | the server can't be reached from this network | `zev proxy doctor`, or another server: `zev proxy use auto` |
| A site works only without the VPN | it refuses visitors from the proxy's country | `zev proxy route direct that-site.example`, or `zev proxy learn` |
| `sudo zev vpn on` on macOS or Windows | not yet | `zev proxy share on` with `zev proxy system on` |

## Security

- The service runs a root-owned copy of the engine, never a file your account could replace.
- Certificate checks stay on, and a link can pin the server's certificate.
- The names zev learns from are kept in the service's folder, readable by root only, and emptied each time they're measured (every half hour).
- `sudo zev vpn off`, or the service stopping without the kill switch, puts routing and DNS back as they were.
