Command Palette

Search for a command to run…

ZarynZaryn
Guides·20 min read

Proxy and VPN (zev proxy, zev vpn)

When Zaryn or other sites are blocked, use your own VLESS, VMess, Trojan, Shadowsocks, Hysteria2 or WireGuard servers for zev, every app, or the whole computer (a VPN).

Some networks block or slow down the way to Zaryn, GitHub and much else. If you have a proxy server that works on that network (VLESS, VMess, Trojan, Shadowsocks, Hysteria2, WireGuard, SOCKS5 or HTTP), zev uses it at the level you choose: | | What goes through the proxy | How | |---|---|---| | **zev only** (the default) | zev's own connections: sign-in, clone, push, pull, `zev self update`, private networks | `zev proxy use <name>` | | **Every app you point at it** | anything that can use a SOCKS5 or HTTP proxy: browsers, git, SSH, pip, npm, cargo, apt… | `zev proxy share on` (port 10808), then `zev proxy system on`, `zev proxy ssh` | | **The whole computer** | every program, its DNS and IPv6, without any settings in them | `sudo zev vpn on` (Linux) | zev never uses a proxy you didn't choose, and never falls back to going out directly when the proxy fails. With these it replaces apps like v2rayN, NekoRay or Hiddify: [moving from v2rayN](#moving-from-v2rayn-nekoray-hiddify) takes a minute. ## One command on, one off ```bash zev proxy start # asks for your server's link the first time zev proxy stop ``` `zev proxy start` does everything: saves the server, installs the engine if needed, opens the shared port 127.0.0.1:10808 for every app, sets your desktop's proxy, and then shows where you appear from. It stays on across restarts. `zev proxy stop` turns all of it off again. ```bash zev proxy start 'vless://…' # with a new server (keep the quotes) zev proxy start --tun # the whole computer: a VPN (asks for your sudo password) zev proxy start --tun --kill-switch # ... and nothing gets out directly if it stops zev proxy # is it on? through which server? ``` The rest of this page explains each part, for when you want more control. `zev proxy` is **free** on every plan: you bring your own proxy, and Zaryn carries none of its traffic. Private networks are part of [Premium](/docs/en/billing-and-credits), so using them through your proxy is too. Below: [the links zev understands](#links-zev-understands), then how to add yours. ## Links zev understands zev understands the share links VPN apps (v2rayN, v2rayNG, Hiddify, Nekoray, Shadowrocket) use, and the subscriptions providers hand out: | Link | What it is | Needs | |---|---|---| | `vless://…` | VLESS: TLS or REALITY, XTLS Vision, VLESS Encryption (such as `mlkem768x25519plus`), the `tcp`, `ws`, `grpc`, `xhttp` and `httpupgrade` transports | the Xray engine | | `vmess://…` | VMess (the v2rayN format), with the same TLS and transports | the Xray engine | | `trojan://…` | Trojan, over TLS or REALITY, same transports | the Xray engine | | `ss://…` | Shadowsocks: the 2022 ciphers (`2022-blake3-…`) and `aes-128-gcm`, `aes-256-gcm`, `chacha20-poly1305` | the Xray engine | | `hysteria2://…` or `hy2://…` | Hysteria2 over QUIC, with Salamander obfuscation (`obfs=salamander`) | the Xray engine | | `wireguard://…` or `wg://…` | WireGuard, including Cloudflare WARP (`reserved=`); no root needed | the Xray engine | | `socks5://user:pass@host:port` | a SOCKS5 proxy | nothing | | `http://…` or `https://…` | an HTTP proxy | nothing | | a subscription URL | a list of any of the above, from your provider: see [Subscriptions](#subscriptions) | | zev refuses what isn't safe or won't work rather than failing later: old Shadowsocks stream ciphers (`aes-256-cfb`, `rc4-md5`), Shadowsocks plugins, and the transports Xray dropped (`h2`, `kcp`, `quic`). A link's `insecure=1` or `allowInsecure` never turns certificate checks off; if your server uses its own certificate, pin it with `pcs=` (or `pinSHA256=` for Hysteria2), as your provider's app does. ## Add your proxy Save it under a name you choose. To keep the link (it holds your credentials) out of your shell history, leave it off and paste it when asked: ```bash zev proxy add work --use Paste the link, then press Enter: vless://… ✓ Saved work: vless proxy.example.com:443 tcp+tls xtls-rprx-vision mlkem768x25519plus fp=firefox sni=… pinned ``` `--use` also makes it the proxy zev uses from now on. Saved links live in `~/.config/zev/proxies`, readable by you alone. `zev proxy ls` lists them without their secrets. ## Subscriptions If your provider gives you a subscription URL (one link that lists many servers, updated when they change), add it once: ```bash zev proxy sub add myvpn https://provider.example/sub/abc123 ✓ myvpn: 24 servers (12 vless, 6 trojan, 4 shadowsocks, 2 hysteria2), named myvpn-1 … myvpn-24 Pick one: zev proxy use myvpn-1 (zev proxy test myvpn-1 tries it first) ``` zev downloads it through the proxy you use now (subscription hosts are often blocked too), or directly if that fails. Servers it can't use are listed with the reason, and the rest are saved. | Command | What it does | |---|---| | `zev proxy sub update [<name>]` | download it again: its servers are replaced by the new list. If the one you use is gone, zev says so and connects directly | | `zev proxy sub ls` | subscriptions and how many servers each has | | `zev proxy sub rm <name>` | forget it and its servers | The usual base64 format and plain lists of links both work. Clash (`proxies:`) and sing-box (JSON) files aren't share links: ask your provider for the v2ray / share-link format of the same subscription. ## Install the engine Everything except SOCKS5 and HTTP is spoken by [Xray-core](https://github.com/XTLS/Xray-core), which zev runs for you on this computer. Install it once: ```bash zev proxy engine install ``` zev downloads the Xray release it was tested with and checks its SHA-256 before unpacking it. If GitHub is blocked, download the zip for your system another way and run `zev proxy engine install --from Xray-linux-64.zip` (the same check applies). An Xray you already have also works: zev looks on your `PATH`, or set `ZEV_XRAY=/path/to/xray`. ## Check it ```bash zev proxy test work: vless proxy.example.com:443 tcp+tls xtls-rprx-vision … engine ✓ Xray on 127.0.0.1:41377 (48 ms) Zaryn ✓ 200 in 310 ms internet ✓ 204 in 290 ms ``` `zev proxy test <name>` tries a saved proxy without switching to it. When a check fails, the last lines of Xray's log are shown below it. To see exactly what zev makes of a link, `zev proxy config <name>` prints the Xray config it runs (it contains the proxy's secrets, so don't share it). ## When it doesn't work: zev proxy doctor `zev proxy doctor` finds what stands between you and Zaryn, fixes what zev can fix itself, and proves each fix with a real request before keeping it: ```bash zev proxy doctor ``` ```text Checking the way to Zaryn through work: vless proxy.example.com:443 tcp+tls fp=chrome … Network: wlan0 via 192.168.1.1; fixes in force: none work vless proxy.example.com:443 … ✗ DNS lies: this network answers 10.10.34.36 for proxy.example.com, DNS over HTTPS 203.0.113.9 (only that one accepts connections) fix: look names up with DNS over HTTPS (https://1.1.1.1/dns-query) ✓ TCP: 203.0.113.9:443 connects in 84 ms ✗ SNI filtering: TLS naming proxy.example.com is reset, naming www.example.com goes through · the reset comes from 3 routers away, near you: in your provider's network (the server is 14 away) Finding a way through 8 ways at once · as it is: no way through · firefox fingerprint: no way through · ClientHello in pieces (split: 10-20 byte pieces): 231 ms · ClientHello in pieces (large: 100-200 byte pieces, 10-20 ms apart): 400 ms … ✓ kept: ClientHello in pieces (split: 10-20 byte pieces) (the cheapest that works, and proven again) Clock ✓ within 2 s of api.zaryn.xyz's clock Throughput ✓ a download through the proxy: 2.0 MB in 1.4 s (1.43 MB/s) Result ✓ api.zaryn.xyz answers through the proxy (200 in 310 ms) · fixes for this network: DNS over HTTPS (https://1.1.1.1/dns-query), ClientHello in pieces (split) ✓ saved for wlan0 via 192.168.1.1: every zev command here uses them, and zev picks them up again when you're back on this network ``` What it looks for, and what it does about it: | Problem | How zev tells | What zev does | |---|---|---| | **DNS that lies** | the network's answer for the proxy's name against DNS over HTTPS (asked straight by IP address); a different answer that accepts no connections, or the filter's own address (`10.10.34.x`), is a lie | looks names up with DNS over HTTPS from then on, zev and Xray both | | **SNI filtering** | TCP connects, but a TLS handshake naming the server is cut while one naming another site goes through | races the ways around it (below) | | **Where the filter is** | the handshake is sent again with a TTL of 1, 2, 3 …: it expires that many routers away, so the first distance that gets a reset is where the filter sits | tells you whether it's in your provider's network or nearer the server | | **Broken IPv6** | the name's IPv6 address times out while IPv4 connects (every connection waits for IPv6 first) | IPv4 only | | **A blocked port** | the proxy's port doesn't answer while other ports of the same address do | says which ports answer: ask whoever runs the server for a link on one | | **A blocked address** | no port of the address answers | says so: another server, or a CDN-fronted link | | **The freeze** | small requests work but a download stops after 15-20 KB and never resumes (filters starve connections they can't classify) | says so: a REALITY or XHTTP link, or another server, usually avoids it | | **Throttling** | downloads crawl | says so, with the speed | | **The clock** | Zaryn's `Date` header against yours: VMess refuses connections more than 2 minutes off, and certificates look expired when the clock is days off | tells you how to set it (that needs an administrator) | | **TLS interception** | Zaryn's certificate isn't trusted on the direct path: something answers in its place (or a Wi-Fi sign-in page) | never turns certificate checks off; a link with a pinned certificate gets around it | ### Finding a way through When the way doesn't work, the doctor doesn't make you guess settings. It tries them all at once, in one Xray, each as its own way to the server: - **the ClientHello in pieces**, in three sizes (`split` 10-20 bytes, `large` 100-200 bytes, `tiny` 1-5 bytes), so a filter reading the server's name never sees it whole in one packet; - **other TLS fingerprints** (Chrome, Firefox, Safari, randomized), for filters that block a handshake by its shape; - both together. Each way's time is measured; the cheapest that works wins (a little extra time counts against the tiny pieces, which slow every connection). The winner must then work again in the engine zev really runs, with a real request; one that only got through once is skipped for the next. Nothing is saved until that passes. ### Per network The fixes are saved **for the network you're on**, which zev tells apart by its router (a hash of the router's address and hardware address; on Linux). Home, the office and a phone's hotspot each keep their own, and zev picks them up again by itself when you come back. Elsewhere, the fixes you set by hand apply. ```bash zev proxy set # this network, its fixes, and the networks zev remembers zev proxy set forget # forget what the doctor found here zev proxy set fragment split # set fixes by hand, for every network (dns <url>, ipv4 on, fp <name> … , or off) zev proxy doctor --no-fix # only look, change nothing zev proxy doctor home # check another saved proxy ``` ### For support and AI agents `zev proxy doctor --json` prints the whole report as JSON: every finding with its hint, the fixes, whether they were saved, and how far away the filter is. It never contains a link or its secrets, so it's safe to paste into a support request or hand to an assistant. ## Everyday use Once a proxy is chosen there's nothing more to do: every zev command goes through it. The engine starts with the first command that connects and keeps running for the ones after it. ```bash zev proxy status # which proxy, and whether the engine runs zev proxy use home # switch to another saved proxy zev proxy off # connect directly again zev proxy stop # everything off (shared port, desktop, VPN) zev proxy rm old # forget a proxy ``` For a single command, or in scripts and CI, `ZEV_PROXY` overrides the choice: a saved name, a link, or `off`. ```bash ZEV_PROXY=off zev pull ZEV_PROXY=home zev push ``` ## Every app on this computer: zev proxy share ```bash zev proxy share on ``` From then on **127.0.0.1:10808** is a proxy port any program can use, SOCKS5 and HTTP on the same port (10808 is the port v2rayN uses, so settings made for it keep working). It runs in the background, starts again when you log in, and: - **follows your choice**: `zev proxy use other` switches it, a pool switches to the fastest working server by itself, and the fixes `zev proxy doctor` found for the network you're on come with you when you move between networks; - **looks after itself**: if its engine stops, it starts it again; with no proxy chosen (`zev proxy off`) the port closes instead of letting traffic go out directly ([it fixes itself](#it-fixes-itself) has more). ```bash zev proxy share status # sharing? through which server, since when zev proxy share on --port 1080 zev proxy share off ``` **Other devices on your network** (a phone, a second laptop): `zev proxy share on --lan` opens the port to the LAN behind a password, which zev prints. Set the device's proxy to this computer's address, port 10808, user `zev` and that password. `zev proxy share on --local` closes it to the LAN again. Addresses on your own network (LAN, `10.0.0.0/8`, `192.168.0.0/16` and the like) are reached directly, not through the proxy. ### Your desktop and browsers: zev proxy system ```bash zev proxy system on # GNOME's or KDE's proxy setting → the shared port; new terminals get http_proxy, all_proxy… zev proxy system off ``` Browsers and most desktop apps follow the system setting. Terminals opened after a new login pick up `http_proxy`, `https_proxy` and `all_proxy` (from `~/.config/environment.d/90-zev-proxy.conf`). ### SSH and git: zev proxy ssh ```bash zev proxy ssh # GitHub, GitLab and Codeberg through the proxy zev proxy ssh github.com myserver # or the hosts you name zev proxy ssh off ``` zev puts a marked block at the top of `~/.ssh/config` with `ProxyCommand zev proxy connect %h %p`; `git push` to GitHub then goes through the proxy, and nothing else in the file changes. `zev proxy connect <host> <port>` works anywhere a ProxyCommand does, and needs neither `nc` nor the shared port (it uses zev's own engine when sharing is off). ### One command: zev proxy run ```bash zev proxy run git push zev proxy run pip install requests zev proxy run -- curl https://example.com ``` The command gets `http_proxy`, `https_proxy`, `all_proxy` and a `GIT_SSH_COMMAND` that goes through the proxy, so HTTP, SOCKS and git over SSH all use it. Its exit code is zev's. ## The whole computer: zev vpn On Linux, zev can carry **everything**: every program, without any proxy settings in it, plus its DNS lookups and IPv6. ```bash sudo zev vpn on sudo zev vpn on --kill-switch sudo zev vpn on --exclude example.ir,192.0.2.0/24 zev vpn status sudo zev vpn off ``` - It uses the proxy you chose with `zev proxy use` (as yourself: `sudo` only sets up the network), and follows it when you change it. - It runs as a system service: it starts with the computer and comes back if it stops. - **Your LAN stays direct**, and so do Docker's networks and private networks: anything your computer has a more specific route for. - **DNS goes through the tunnel**: names are looked up over HTTPS by the far side, so a poisoned DNS on your network can't send you elsewhere. - **`--exclude`** sends some sites or addresses directly (names, IP addresses, CIDR ranges). `zev proxy route iran` sends Iran's sites direct for every mode. - **`--kill-switch`**: if the VPN stops for any reason, nothing goes out directly; only your LAN keeps working, until the VPN is back or you run `sudo zev vpn off`. How it works: zev creates a network interface (`zev0`) that the Xray engine reads, and routes everything into it except what has a more specific route and the engine's own connections (which carry a firewall mark so they don't loop). `sudo zev vpn off` removes the interface, the routes, the rules and the firewall table; nothing is left behind. On macOS and Windows, use `zev proxy share on` with `zev proxy system on` for now. ## It fixes itself The shared port and the VPN check every 30 seconds that traffic really gets through. When it stops for three checks in a row: 1. You get a notification on the desktop. 2. zev runs [`zev proxy doctor`](#when-it-doesnt-work-zev-proxy-doctor) by itself, at most every 10 minutes. It finds what blocks the way on this network (DNS lies, a blocked port, SNI filtering, a clock that's off) and saves a fix for this network. 3. The engine restarts with the fix, and a notification says what was fixed, for example *Fixed for wlo1 via 192.168.1.1: TLS fragmentation (split)*. With a pool, a dead server is simply skipped in the meantime. With the VPN's kill switch on, zev doesn't pause the VPN to run the doctor; it only restarts the engine. ## Check it: zev proxy check ```text $ zev proxy check Where you appear from through zev 203.0.113.9 (DE) without zev 5.160.12.34 (IR) Leaks ✓ every app goes through the VPN (they appear from the proxy's address) ✓ DNS goes through the tunnel ✓ no IPv6 way out (nothing to leak) ``` It shows the address and country websites see through the proxy and without it, and with the VPN on, whether every app, DNS and IPv6 really go through it. ## Watch it: zev proxy top ```bash zev proxy top ``` Live traffic of the shared port or the VPN: what each part sent and received in total and right now (zev itself, the shared port, the VPN, each server of a pool, what went direct). `--once` prints it once. ## Moving from v2rayN, NekoRay, Hiddify 1. Copy your servers out of the old app: most can export a server as a share link (`vless://…`) or give you the subscription address. 2. Add them to zev: ```bash zev proxy engine install # once: the Xray engine zev proxy add home 'vless://…' --use # a server, or: zev proxy sub add work https://… # a subscription zev proxy use work # all of its servers as a pool: the fastest, with failover ``` 3. Quit the old app (it holds port 10808), then: ```bash zev proxy share on # the same port 10808: your SSH config and apps keep working zev proxy system on # browsers and the desktop ``` 4. Or for everything at once: `sudo zev vpn on`. What you get on top: failover between servers ranked by measured speed, self-healing on networks that filter, per-network fixes that follow you, leak checks, and the same settings for zev's own connections. ## Many servers: the fastest, and failover Servers come and go on filtered networks: one is fast in the morning and blocked by the evening. Give zev several and it uses the best of them, and switches on its own when one stops answering: ```bash zev proxy use myvpn # every server of a subscription zev proxy use auto # every proxy you saved zev proxy use work,home,backup # these ones ``` zev times every server at once (a small request through each), keeps the three best running, and Xray sends each connection through the fastest that answers, checking them again every 30 seconds. When the one in use goes down, the next connection takes another; nothing for you to do. Every 30 minutes the next zev command times the whole list again, so a server that got better comes back. To see the ranking, or rank them now: ```bash zev proxy probe Probing 4 servers at once (https://www.gstatic.com/generate_204)… server now expected answers ● work 92 ms 95+-12 100% vless proxy.example.com:443 … ● home 140 ms 151+-20 100% trojan home.example:443 … ● backup 410 ms 388+-61 83% shadowsocks 203.0.113.9:8388 … old down - 0% vmess old.example:443 … ● in use (the best 3 by expected latency and answers; Xray switches between them) ``` > **Why "expected" and not just "now"?** One request says little: a slow DNS answer or a lost packet can make a good server look bad once. zev keeps a running estimate for each server (a Kalman filter): it smooths the noise, ignores a single spike, follows a server that really got slower, and trusts an old measurement less than a fresh one. A server that often fails to answer is ranked below a steady one, even a slightly slower one. The measurements are kept in `~/.cache/zev/proxy/health.json`, under a hash of each link, never the link itself. `zev proxy probe <name>`, `zev proxy probe auto` or `zev proxy probe a,b,c` rank other servers without switching to them. `zev proxy status` shows which servers the engine runs now. ## Chains: one proxy through another A chain reaches its last server through the ones before it. Use one when the server you want to come out of is blocked from your network but reachable from another server: ```bash zev proxy chain out home work # zev → home → work → Zaryn zev proxy use out ``` `home` sees only that you connect to `work`; Zaryn sees `work`'s address. Each hop is a saved proxy, any of the kinds above. Hysteria2 and WireGuard run over UDP, so in a chain they can only be the first hop. `zev proxy ls` lists chains with their hops, and `zev proxy rm out` forgets one (a proxy that is a hop of a chain can't be removed until the chain is). ## Routes: what goes direct Some places are faster without the proxy, or only work without it: a server in your own country, a company mirror, sites that refuse connections from abroad. Routes send those direct and everything else through the proxy (split routing): ```bash zev proxy route iran # Iran's sites and addresses direct zev proxy route direct git.company.example 10.20.0.0/16 zev proxy route proxy blocked.example.ir # through the proxy, whatever a direct route says zev proxy route # list them zev proxy route rm git.company.example zev proxy route clear ``` | A route | Matches | |---|---| | `example.com` | that name and every name under it (`api.example.com`) | | `.ir` | every name ending in `.ir` | | `full:host.example` | that name only | | `5.160.0.0/16`, `2a01:5ec0::/29`, `203.0.113.7` | addresses | | `geoip:ir` | every address in a country (any two-letter country code) | | `geosite:category-ir` | a list of a country's or a service's sites, kept by the Xray project | | `iran` | `.ir`, `geosite:category-ir` and `geoip:ir` together | Routes apply to every proxy, single servers, pools and chains alike, from the next zev command. `geoip:` and `geosite:` use Xray's routing data, which `zev proxy engine install` puts beside Xray; if you installed the engine before these routes existed, run it once more. With a route on addresses, Xray looks up names on this computer to compare them; names that only resolve through the proxy still go through it. ## Private networks `sudo zev net up` takes the proxy you use and saves it with the network, so the network's background service reaches Zaryn and the relay through it as well. The relay's traffic travels inside the proxy too, which is how a device behind a network that blocks everything else still joins its team. `zev net status` shows `through the proxy …` when this is the case. ```bash sudo zev net up your-name/office # with the proxy you use sudo zev net up your-name/office --proxy home # with another saved proxy (a pool or a chain works too) sudo zev net up your-name/office --no-proxy # directly ``` The service runs its own copy of Xray from `/var/lib/zev/net` (root only), never one from your home folder. Devices behind a proxy talk to their peers through the relay. Their traffic stays end-to-end encrypted; the proxy and the relay only see WireGuard's encrypted packets. ## What never goes through the proxy Addresses on your computer, your local network and private networks: `localhost`, `127.0.0.0/8`, `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `100.64.0.0/10` (private networks), `fc00::/7` and `*.zaryn.internal`. To change this list, set `ZEV_NO_PROXY` to your own, in curl's `--noproxy` form (names, `.domains`, CIDR ranges). ## Security - **zev doesn't fall back to a direct connection.** If the chosen proxy can't be used (the engine won't start, the link is broken), the command stops and says why. Run `zev proxy off` to connect directly. - **Certificate checks stay on.** A link can pin the server's certificate (`pcs=` / `pinSHA256=`), and zev passes that on. zev ignores `allowInsecure` in links: a link someone hands you can't switch certificate checks off. - **The shared port is for this computer.** `zev proxy share on` listens on `127.0.0.1` only; `--lan` opens it to the network only behind a password. - **The VPN runs its own copy of the engine.** `sudo zev vpn on` copies Xray into `/var/lib/zev/vpn`, owned by root, so a root service never runs a file your user account could replace. - **The engine is yours alone.** zev's own engine listens on `127.0.0.1` only, behind a random password. curl gets that password from a file only you can read, never from its command line, so other users on the computer can't use your proxy or see it. - **Treat a link like a password.** It contains your account's key on that server. If one leaks (into a chat, a screenshot, a public repository), ask whoever runs the server for a new one.