Skip to content

SOCKS5 Proxy Mode

SOCKS5 mode is the default and most flexible way to use r-vpn. It runs a local SOCKS5 proxy that individual apps can be pointed at — without affecting other traffic on your machine.


Starting the Proxy

rvpn -c ~/.config/rvpn/client.toml

Default listen address: 127.0.0.1:1080

Once running you'll see:

INFO  SOCKS5 proxy listening on 127.0.0.1:1080


Configuring Apps

macOS — System-wide Proxy

System Settings → Network → your connection → Details → Proxies

Enable SOCKS Proxy and set: - Server: 127.0.0.1 - Port: 1080

This routes all system traffic (Safari, curl, etc.) through the VPN.

Firefox

Settings → General → Network Settings → Manual proxy configuration

  • SOCKS Host: 127.0.0.1
  • Port: 1080
  • Select SOCKS v5
  • Check Proxy DNS when using SOCKS v5 to prevent DNS leaks (not needed if you have the DNS proxy enabled)

Chrome / Brave

Chrome uses the system proxy on macOS. On Linux, use the SwitchyOmega extension:

  1. Install SwitchyOmega
  2. Create a new profile → Protocol: SOCKS5, Server: 127.0.0.1, Port: 1080
  3. Switch to that profile when you want to use the VPN

curl

curl --socks5 127.0.0.1:1080 https://api.ipify.org

Linux — System-wide (environment variables)

export ALL_PROXY=socks5://127.0.0.1:1080
export HTTPS_PROXY=socks5://127.0.0.1:1080
export HTTP_PROXY=socks5://127.0.0.1:1080

Add to ~/.bashrc or ~/.zshrc to persist across sessions.


Split Tunneling

Split tunneling lets you route only certain traffic through the VPN while the rest connects directly. This is useful when you want to reach blocked sites through the VPN while keeping local network and domestic traffic unaffected.

Built-in China bypass

Enable split tunneling with automatic China IP bypass in client.toml:

[split_tunnel]
enabled = true
builtin_bypass_countries = ["CN"]

When enabled, traffic to Chinese IPs (based on APNIC data — ~8800 networks) connects directly, and everything else routes through the VPN.

Custom bypass networks

[split_tunnel]
enabled = true
bypass_networks_file = "~/.config/rvpn/bypass-networks.txt"

bypass-networks.txt — one CIDR per line:

192.168.0.0/16
10.0.0.0/8
172.16.0.0/12

Ad blocking

[split_tunnel]
block_ads = true

Blocks known ad and tracker domains at the DNS level. No bytes sent, no connection established.


DNS Proxy

Important: Without the DNS proxy, your DNS queries may leak to your ISP even when using the SOCKS5 proxy. See DNS Leak Prevention for a complete explanation.

By default, DNS queries are resolved by your system's DNS server — outside the VPN tunnel. This means your ISP can observe which domains you look up even while your traffic is proxied.

r-vpn includes a built-in DNS proxy that resolves all queries server-side through the same encrypted WebSocket tunnel. It is also split-tunnel aware: bypass domains are resolved locally, and blocked ad/tracker domains return NXDOMAIN immediately without ever hitting the network.

Enable the DNS proxy

[dns_proxy]
enabled        = true
listen_address = "127.0.0.1:53"

Note: Port 53 requires root or CAP_NET_BIND_SERVICE. Use port 5353 for unprivileged testing (see below).

Restart the client — you should see:

INFO  DNS proxy listening on 127.0.0.1:53

macOS — system-wide

Run the client with sudo (so it can bind port 53), then add 127.0.0.1 as your DNS server:

System Settings → Network → your connection → Details → DNS → +127.0.0.1

Or via the command line (replace Wi-Fi with your interface name):

sudo networksetup -setdnsservers Wi-Fi 127.0.0.1

To restore the original DNS when you're done:

sudo networksetup -setdnsservers Wi-Fi empty

Linux — system-wide

Run the client as root (or with the CAP_NET_BIND_SERVICE capability) with listen_address = "127.0.0.1:53", then point your resolver at it.

/etc/resolv.conf (direct):

nameserver 127.0.0.1

systemd-resolved — add to /etc/systemd/resolved.conf:

[Resolve]
DNS=127.0.0.1
Then restart: sudo systemctl restart systemd-resolved

Unprivileged testing (port 5353)

[dns_proxy]
enabled        = true
listen_address = "127.0.0.1:5353"

Verify it works:

dig @127.0.0.1 -p 5353 example.com

The response will come from your VPN server rather than your local ISP.


Connection Modes

The SOCKS5 proxy supports two connection modes to the server:

Multiplexed Mode (Default)

All SOCKS5 flows share a single WebSocket connection with one shared DoubleRatchet session. Each SOCKS5 CONNECT creates a logical "flow" via CreateFlow/CloseFlow control messages over the same tunnel.

Benefits: - Single TLS handshake, single X3DH key exchange — ~250ms overhead vs ~600ms per-connection - Lower server resource usage (one WebSocket, one ratchet vs one per flow) - Better for high-flow-count scenarios (browsers open 100+ connections) - Server supports up to 2000 concurrent flows per mux session

How it works: 1. First SOCKS5 CONNECT opens the mux WebSocket tunnel ({server_path}/mux) 2. Performs X3DH handshake to establish the shared DoubleRatchet 3. Subsequent flows send CreateFlow control messages over the same tunnel 4. The server responds with FlowCreated ACK, then data flows through multiplexed frames

Configuration:

[socks5]
multiplex = true        # enabled by default
# mux_path defaults to {server_path}/mux automatically

To override the mux endpoint explicitly:

[socks5]
multiplex = true
mux_path = "/api/v1/ws/mux"

Legacy Mode (Fallback)

Each SOCKS5 flow opens its own separate WebSocket connection with its own X3DH handshake and DoubleRatchet. This is the original behavior.

When to use: - Troubleshooting — isolate whether an issue is flow-specific or tunnel-wide - Compatibility with older server versions that don't have the mux endpoint

[socks5]
multiplex = false

Comparing Modes

Multiplexed Legacy
WebSockets per session 1 1 per flow
X3DH handshakes 1 1 per flow
Server flows Up to 2000 Unlimited
Server-side WS connections 1 N
Best for Browsers, heavy sites Debugging, old servers

Troubleshooting tip: If you experience connection issues in multiplexed mode (e.g. some apps fail to load, timeouts on heavy sites), try switching to legacy mode to isolate whether the problem is tunnel-wide or flow-specific:

[socks5]
multiplex = false
Be aware that legacy mode opens one WebSocket per TCP flow. On busy networks (e.g. browsers with many tabs), this can quickly exhaust the server's max_connections_per_ip limit. If you use legacy mode regularly, increase the server's rate limits accordingly:
[server.rate_limit]
max_connections_per_ip    = 500
max_handshakes_per_minute = 2000


Changing the Listen Address

To listen on a specific interface (e.g. to share the proxy with other devices on your local network):

[socks5]
listen_address = "0.0.0.0:1080"

Security note: Only expose the SOCKS5 port on trusted networks. There is no authentication by default.

To add authentication:

[socks5]
listen_address = "0.0.0.0:1080"
auth_enabled   = true
auth_username  = "user"
auth_password  = "changeme"

Running as a Service

Linux (systemd)

sudo nano /etc/systemd/system/rvpn-client.service
[Unit]
Description=r-vpn Client
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=YOUR_USER
ExecStart=/usr/local/bin/rvpn -c /etc/rvpn/client.toml
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now rvpn-client

FreeBSD (rc.d)

Create /usr/local/etc/rc.d/rvpn_client:

#!/bin/sh
# PROVIDE: rvpn_client
# REQUIRE: NETWORKING
# KEYWORD: shutdown

. /etc/rc.subr

name="rvpn_client"
rcvar="rvpn_client_enable"
command="/usr/local/bin/rvpn"
command_args="-c /usr/local/etc/rvpn/client.toml"
pidfile="/var/run/rvpn-client.pid"

load_rc_config $name
run_rc_command "$1"
chmod +x /usr/local/etc/rc.d/rvpn_client
echo 'rvpn_client_enable="YES"' >> /etc/rc.conf
service rvpn_client start