Why OpenVPN is so slow? (cool story)
From time to time, I see people asking for help on forums, who have connected 2 remote sites via OpenVPN and have an awful speed compared to link speed, like 400 Kbit/s with 2 Mbit/s link or 20 Mbit/s with 100 Mbit/s link. Some recommend them to increase MTU on tunnel interface up to 48000, some say they should tune mssfix parameter, but none really helps. Sometimes people say that OpenVPN is so slow because it's userspace and this is its' usual speed. That's Nonsense!
A little bit of history
It's July, 2004. Usual home internet speed in developed countries is 256-1024 Kbit/s, in less developed countries is 56 Kbit/s. Linux 2.6.7 has been released not a long ago and 2.6.8 where TCP Windows Size Scaling would be enabled by default is released only in a month. OpenVPN is in active development for 3 years already, 2.0 version is almost released.
One of the developers decides to add some code for socket buffer, I think to unify buffer sizes between OSes. In Windows, something goes wrong with adapters' MTU if custom buffers sizes are set, so finally it transformed to the following code:
#ifndef WIN32 o->rcvbuf = 65536; o->sndbuf = 65536; #endif
A little bit of technical info
If you used OpenVPN, you should know that it can work over TCP and UDP. If you set custom TCP socket buffer value as low as 64 KB, TCP Window Size Scaling algorithm can't adjust Window Size to more than 64 KB. What does that mean? That means that if you're connecting to other VPN site over long fat link, i.e. USA to Russia with ping about 100 ms, you can't get speed more than 5.12 Mbit/s with default OpenVPN buffer settings. You need at least 640 KB buffer to get 50 Mbit/s over that link.
UDP would work faster because it doesn't have window size but also won't work very fast.
What should I do?
As you already may guess, the latest OpenVPN release still uses 64 KB socket buffer size. How should we fix this issue? The best way is to disallow OpenVPN to set custom buffer sizes. You should add the following code in both server and client config files:
sndbuf 0 rcvbuf 0
After this, socket buffers would be handled by OS. As for Linux and TCP, this is values from net.ipv4.tcp_rmem and net.ipv4.tcp_wmem and for UDP is a fixed value from net.core.rmem_default and net.core.wmem_default, divided by two.
If you can't change client config, you should push bigger buffer sizes from server:
sndbuf 0 rcvbuf 0 push "sndbuf 393216" push "rcvbuf 393216"
UDP is different from TCP. It doesn't have Window Scale but it doesn't need it OS-wide, but low buffer sizes may slow down it, too. If you think OpenVPN is still slow after changing buffer values to 0, you should either increase OS-wide buffer sizes (net.core.rmem_default and net.core.wmem_default) or increase buffer in server config:
sndbuf 393216 rcvbuf 393216 push "sndbuf 393216" push "rcvbuf 393216"
But I use Windows!
If you use Windows on both server and client, you should not suffer from this bug.