Skip to content

TUN Mode (Full-Tunnel VPN)

TUN mode provides a full-tunnel VPN experience where all client traffic is routed through the server. This differs from SOCKS5 relay mode, which requires per-application SOCKS5 configuration.


FeatureTUN ModeSOCKS5 Mode
Traffic routingFull tunnel, all appsPer-app, requires SOCKS5 config
Setup complexityServer-side NAT configClient-side app configuration
PerformanceKernel-level packet handlingApplication-level relay
Use caseComplete privacy, all trafficApp-specific tunneling

In TUN mode, the client creates a virtual TUN interface and routes all traffic through it. The server receives these packets and NATs them to the internet, similar to a traditional VPN.


TUN mode requires the server to act as a NAT gateway for client traffic. The server must have IP forwarding enabled and proper NAT rules configured.

Enable IP forwarding:

Terminal window
# Temporary (resets on reboot)
sudo sysctl -w net.ipv4.ip_forward=1
# Permanent
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Configure NAT with iptables:

Terminal window
# Assuming your public interface is eth0
# -s should match [server.network].dhcp_range in server.toml
sudo iptables -t nat -A POSTROUTING -s 10.200.0.0/24 -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i tun0 -o eth0 -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o tun0 -m state --state RELATED,ESTABLISHED -j ACCEPT

Using nftables instead:

Terminal window
sudo nft add table ip nat
sudo nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }
sudo nft add rule ip nat postrouting oifname "eth0" masquerade
sudo nft add chain ip filter forward { type filter hook forward priority 0 \; }
sudo nft add rule ip filter forward iifname "tun0" oifname "eth0" accept
sudo nft add rule ip filter forward iifname "eth0" oifname "tun0" ct state related,established accept

Replace eth0 with your actual network interface name (ip addr or ip link to check).

macOS does not support server-side TUN mode natively. For macOS servers, use SOCKS5 mode or run rvpn-server inside a FreeBSD/Linux VM with proper NAT configuration.

Enable IP forwarding:

Terminal window
# Temporary
sudo sysctl -w net.inet.ip.forwarding=1
# Permanent in /etc/rc.conf
echo 'gateway_enable="YES"' | sudo tee -a /etc/rc.conf

Configure NAT with ipfw:

Terminal window
sudo sysctl -w net.inet.ip.fw.enable=1
sudo natd -s -m -u -dynamic -i nat0
# Or using ipfw rules directly
sudo ipfw add 100 nat 1 all from any to any via tun0

For a full ipfw/natd setup, add to /etc/rc.conf:

Terminal window
firewall_enable="YES"
firewall_type="OPEN"
natd_enable="YES"
natd_interface="vtnet0" # your public interface

[server]
bind_address = "0.0.0.0:443"
tls_cert_file = "/etc/letsencrypt/live/your-domain.com/fullchain.pem"
tls_key_file = "/etc/letsencrypt/live/your-domain.com/privkey.pem"
identity_key_file = "/etc/rvpn/server_identity.key"
websocket_path = "/api/v1/ws"
[server.network]
nat_enabled = true
dhcp_range = "10.200.0.0/24"
[server.tun]
enabled = true
tun_ip = "10.200.0.1/24"
mtu = 1420
dns_servers = ["1.1.1.1", "8.8.8.8"]

Key settings for TUN mode:

  • websocket_path — Must be /api/v1/ws for TUN mode clients to reach the TUN endpoint at /api/v1/ws/tun
  • [server.network].nat_enabled and dhcp_range — Startup-hint fields used to check your iptables NAT rules. NAT itself is programmed by your operator (iptables/pf); see the Server Installation guide.
  • [server.tun].tun_ip — The subnet client IPs are handed out from. Change this if 10.200.0.0/24 clashes with your LAN.
  • [server.tun].dns_servers — DNS resolvers pushed to clients over the tunnel

Terminal window
sudo rvpn-server -c /etc/rvpn/server.toml

The service runs the same binary regardless of mode. Ensure server.toml has TUN-mode settings as shown above.

Terminal window
sudo systemctl restart rvpn-server

Check server logs:

Terminal window
sudo journalctl -u rvpn-server -f

Look for entries showing the WebSocket path and TUN handler:

INFO Starting rVPN Server on 0.0.0.0:443
INFO Server listening on wss://0.0.0.0:443
INFO WebSocket endpoint (mobile TUN): /api/v1/ws/tun
INFO TUN server started on 10.200.0.1/24

Verify NAT rules are active (Linux):

Terminal window
sudo iptables -t nat -L POSTROUTING -v
sudo iptables -L FORWARD -v

Test connectivity:

Connect a client in TUN mode and verify:

  1. Client receives an IP in the dhcp_range (e.g., 10.200.0.x)
  2. Client can ping external IPs (e.g., 8.8.8.8)
  3. Client DNS queries resolve correctly

Check active connections on server:

Terminal window
sudo ss -tlnp | grep 443
sudo ip addr show tun0 # if interface exists

  • Verify port 443 is open in firewall
  • Check websocket_path is /api/v1/ws (clients append /tun automatically)
  • Review server logs for TLS or WebSocket upgrade errors
  • Verify IP forwarding is enabled: sysctl net.ipv4.ip_forward
  • Check NAT rules: iptables -t nat -L POSTROUTING
  • Ensure the server’s security group/firewall allows outbound traffic on all ports
  • Confirm nat_enabled = true in server.toml
  • Verify DHCP range does not conflict with existing networks
  • Check that dns_servers are reachable from the server

The server creates a real TUN interface (e.g., tun0 with IP 10.200.0.1) when TUN mode is enabled. This provides true TUN-to-TUN tunneling:

ComponentDescription
Server TUNtun0 with IP 10.200.0.1/24
Client TUNVirtual interface with IP from 10.200.0.x
RoutingKernel routes packets through TUN interface

The server’s TUN interface handles:

  • Writing packets received from clients to the kernel
  • Reading response packets from the kernel
  • Forwarding responses back to the appropriate client

When running behind a reverse proxy (Caddy, nginx, HAProxy), ensure the proxy forwards /api/v1/ws/tun to the server. The proxy configuration for TUN mode is identical to SOCKS5 mode — both use the same WebSocket base path.

See Reverse Proxy Setup for complete proxy configurations.


ItemValue
WebSocket path/api/v1/ws
TUN endpoint/api/v1/ws/tun
Default port443
DHCP range default10.200.0.0/24
NAT requiredYes