Server Tuning¶
This page covers operating-system-level tuning for the R-VPN server, especially for high-latency or lossy international paths (for example, clients in China connecting to a server in the US).
Symptoms that tuning can help¶
- Ping through the VPN starts reasonable but grows over time (e.g. 500 ms → 5–12 seconds).
- Throughput collapses to tens of kbps even though the server has plenty of bandwidth.
ss -tishows a very small congestion window (cwnd: 2), high retransmits, andbytes_retransclimbing.- The same client and server work fine on a different network (e.g. mobile 5G vs. fixed-line Wi-Fi).
These symptoms usually mean the TCP connection between the client and server is crossing a lossy or heavily shaped link. The default Linux congestion controller, CUBIC, interprets packet loss as network congestion and aggressively shrinks the send window, causing latency to spiral.
Switch to BBR congestion control¶
BBR (Bottleneck Bandwidth and RTT) models the link instead of treating loss as congestion. On high-loss, high-RTT paths it keeps throughput much higher and latency much more stable than CUBIC.
Check available algorithms¶
If bbr is not listed, load the module:
To load tcp_bbr automatically at boot, create /etc/modules-load.d/tcp_bbr.conf:
Apply BBR now¶
Persist BBR across reboots¶
Create /etc/sysctl.d/99-rvpn-tcp-tuning.conf:
# R-VPN TCP tuning for high-latency / lossy international paths
net.ipv4.tcp_congestion_control=bbr
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.ipv4.tcp_rmem=4096 262144 16777216
net.ipv4.tcp_wmem=4096 262144 16777216
net.ipv4.tcp_notsent_lowat=16384
Apply it:
The buffer increase gives each TCP connection enough headroom for the bandwidth-delay product of a 250–350 ms RTT path.
Verify the active connection is using BBR¶
After reconnecting the VPN client (existing connections keep their old congestion controller):
Look for:
If it still says cubic, the client has not reconnected yet.
FreeBSD tuning¶
FreeBSD also supports BBR through the cc_bbr kernel module, which is the best choice for high-loss, high-RTT paths.
Load BBR¶
Check whether the module is already loaded:
If it is not loaded:
To load it automatically at boot, add this line to /boot/loader.conf:
Apply BBR and tune buffers¶
sudo sysctl net.inet.tcp.cc.algorithm=bbr
sudo sysctl kern.ipc.maxsockbuf=16777216
sudo sysctl net.inet.tcp.recvspace=16777216
sudo sysctl net.inet.tcp.sendspace=16777216
To persist these settings across reboots, create /etc/sysctl.conf:
# R-VPN TCP tuning for high-latency / lossy international paths
net.inet.tcp.cc.algorithm=bbr
kern.ipc.maxsockbuf=16777216
net.inet.tcp.recvspace=16777216
net.inet.tcp.sendspace=16777216
Verify on FreeBSD¶
Check the active congestion controller:
FreeBSD does not expose per-connection congestion-control names as conveniently as Linux ss, so verify throughput and latency with ping and iperf3 after reconnecting the client.
Other things to check¶
- Interface MTU: Google Cloud VPC uses a 1460-byte MTU by default. R-VPN’s TUN MTU is 1420, which fits comfortably inside the VPC MTU plus TLS/WebSocket overhead.
- CPU:
rvpn-serveris single-threaded for crypto per connection but async; a 1-vCPU VM is usually enough for one or two clients but may become a bottleneck at higher throughput. - Disk / logging: at default
INFOverbosity the server logs every frame. On a busy client this can generate a lot ofjournaldI/O. Consider reducing log verbosity in production.
When tuning does not help¶
If latency and loss persist after BBR and buffer tuning, the problem is likely outside the server:
- ISP/routing issues on the international segment
- Carrier-grade DPI or throttling targeting TLS on port 443
- Local Wi-Fi router with aggressive QoS or small buffers
In those cases, try a different client network (mobile hotspot, different ISP) or a different server location closer to the client.