Very low TCP OpenVPN throughput (100Mbit port, low CPU utilization)

Solution 1:

After a lot of Googling and configuration file tweaks, I found the solution. I'm now getting sustained speeds of 60Mbps and burst up to 80Mbps. It's a bit slower than the transfer rates I receive outside the VPN, but I think this is as good as it'll get.

The first step was to set sndbuf 0 and rcvbuf 0 in the OpenVPN configuration for both the server and the client.

I made that change after seeing a suggestion to do so on a public forum post (which is an English translation of a Russian original post) that I'll quote here:

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

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.

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

The author goes on to describe how to push buffer size adjustments to the client if you are not in control of the client config yourself.

After I made those changes, my throughput rate bumped up to 20Mbps. I then saw that CPU utilization was a little high on a single core so I removed comp-lzo (compression) from the configuration on both the client and server. Eureka! Transfer speeds jumped up to 60Mbps sustained and 80Mbps burst.

I hope this helps someone else resolve their own issues with OpenVPN slowness!

Solution 2:

After some tries, I've reached a good solution. In my case, @Elliot's reply didn't helped. Googling more, I found out this snippet to add in server's configuration that made the job

sndbuf 393216
rcvbuf 393216
push "sndbuf 393216"
push "rcvbuf 393216"

I have a little OpenVPN server running on a Raspberry PI3 and now I get 71 Mbps downlink and 16Mbps uplink. Download is limited since CPU's power. Right now, my configuration is the following:

client-to-client
duplicate-cn
keepalive 10 120
cipher AES-128-CBC
#cipher AES-256-CBC <<<---- lowers the speed to around 50Mbps, still not bad
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
tun-mtu 9000

OpenVPN 2.4.0 arm-unknown-linux-gnueabihf with OpenSSL 1.0.2l

It feels so weird that such a problem about the default configuration of a buffer still exists.

[EDIT] My client.ovpn file is structured like this:

client
dev tun
proto tcp
remote SERVER.IP.ADDRESS.HERE
resolv-retry infinite
nobind
persist-key
persist-tun
mute-replay-warnings
ns-cert-type server
tun-mtu 9000
key-direction 1
cipher AES-128-CBC
comp-lzo
verb 1
mute 20
<ca>
-----BEGIN CERTIFICATE-----
[...]
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
[...]
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN RSA PRIVATE KEY-----
[...]
-----END RSA PRIVATE KEY-----
</key>
<tls-auth>
-----BEGIN OpenVPN Static key V1-----
[...]
-----END OpenVPN Static key V1-----
</tls-auth>