Running server & client
Creating a TUN device requires elevated privileges (root on Linux, sudo on macOS, Administrator on Windows). Both binaries log to stderr; set RUST_LOG=debug for verbose tracing.
Server
sudo ./target/release/shadowvpn-server -c server.jsonOr entirely via CLI flags:
sudo ./target/release/shadowvpn-server \
--listen 0.0.0.0:8388 \
--password "correct horse battery staple" \
--cipher chacha20-poly1305 \
--tun-ip 10.9.0.1 \
--peer-ip 10.9.0.2For tunneled clients to reach the wider network through the server, the server host must also enable IP forwarding and NAT — see Routing & IP forwarding. The binaries print these hints at startup.
Client
sudo ./target/release/shadowvpn-client -c client.jsonOr via CLI flags:
sudo ./target/release/shadowvpn-client \
--server vpn.example.com:8388 \
--password "correct horse battery staple" \
--cipher chacha20-poly1305 \
--tun-ip 10.9.0.2 \
--peer-ip 10.9.0.1Once the tunnel is up, verify connectivity with a ping across the tunnel addresses — from the client:
ping 10.9.0.1Windows (client)
Put shadowvpn-client.exe, wintun.dll (matching the CPU architecture), and your client.json in one folder, then run from an elevated PowerShell:
.\shadowvpn-client.exe -c client.jsonWintun and the routing/DNS changes need Administrator, so launch the terminal with Run as administrator.
Stop with Ctrl-C, not taskkill
Stop the client with Ctrl-C for a graceful shutdown — it restores the system resolver, removes the per-destination routes, and saves the DNS cache. Avoid taskkill /F, which skips that cleanup.
Self-elevating launcher
The scripts/ folder has a launcher that elevates itself via a UAC prompt:
shadowvpn-client.cmdor, if your execution policy already allows local scripts (Set-ExecutionPolicy -Scope CurrentUser RemoteSigned):
.\shadowvpn-client.ps1 -Config client.jsonshadowvpn-client.cmd is a thin wrapper that runs the .ps1 with -ExecutionPolicy Bypass, so you don't have to relax the policy at all.
Keepalive
The client periodically sends a tiny encrypted keepalive datagram (every 15 seconds by default; keepalive_secs / --keepalive-secs to tune) so that stateful NAT/firewall mappings stay open and the server learns the client's current source address before any real traffic flows. Keep the interval below your path's UDP NAT timeout. Details: wire protocol § keepalive.
Graceful shutdown
The client handles Ctrl-C / SIGTERM cleanly: it restores the system resolver, removes the tunnel routes it added, and saves the DNS cache before exiting. Service managers get the same behaviour — see Running as a service.