SSH tunneling is faster than OpenVPN, could it be

networkingopenvpnssh

Logically, VPN should be faster than SSH for tunneling, because:

  • It's running on UDP and not TCP (so no TCP over TCP)
  • It has compression

However, today I tested Redis replication over both methods.
I ran the test over an Ireland AWS VM, connecting to a US-East AWS VM.
Since my test case is Redis replication, this is exactly what I tested – I ran a blank Redis server, and after it finished loading, I executed slaveof the other server, and measured the time between Connecting to MASTER and MASTER <-> SLAVE sync: Finished with success. In between, I used

while 1; do redis-cli -p 7777 info | grep master_sync_left_bytes;sleep 1; done

To get a crude estimation of the speed.
SSH won by a long shot: ~11MB/s compared to OpenVPN's ~2MB/s.
Does that mean that all of what I reaserched was wrong, or have I grossly misconfigured my setup?

Update

I've made several test with the same dataset, and got these results:

  • OpenVPN
    • TCP:
      compression: 15m
      no compression: 21m
    • UDP:
      compression: 5m
      no compression: 6m
  • SSH
    defaults: 1m50s
    no compression: 1m30s
    compression: 2m30s

Update2

Here are the iperf results, with bidirectional tests (except SSH, where no return path is available)

| method           | result (Mb/s)|
|------------------+--------------|
| ssh              | 91.1 / N.A   |
| vpn blowfish udp | 43 / 11      |
| vpn blowfish tcp | 13 / 12      |
| vpn AES udp      | 36 / 4       |
| vpn AES tcp      | 12 / 5       |

Technical specs

I'm running CentOS 6.3 (server), CentOS 6.5 (client).
OpenVPN version is 2.3.2 (same as in Ubuntu 14.10, so no moldy version there)
My SSH tunnelling looks like:

ssh -f XXXX@XXXX -i XXXX -L 12345:127.0.0.1:12345 -N

My configuration file looks like:
server

port 1194
proto udp
dev tun0
topology subnet
log /var/log/openvpn.log

ca XXXX
cert XXXX
key XXXX
dh XXXX
crl-verify XXXX

cipher AES-256-CBC

server XXXX 255.255.255.0

ifconfig-pool-persist /etc/openvpn/ipp.txt
keepalive 10 120
comp-lzo
status /var/log/openvpn-status.log
verb 3
tun-mtu 1500
fragment 1300

persist-key
persist-tun

client

client

remote XXXX 1194

proto udp
dev tun
log /var/log/openvpn.log
comp-lzo

cipher AES-256-CBC
ns-cert-type server

# the full paths to your server keys and certs
ca XXXX
cert XXXX
key XXXX

tun-mtu 1500 # Device MTU
fragment 1300 # Internal fragmentation

persist-key
persist-tun
nobind

Best Answer

Thanks to kasperd's comment, I learnt that SSH doesn't suffer from TCP-over-TCP since it only moves packet data. I wrote a blog post about it, but the most interesting thing is the netstat output, proving that SSH indeed doesn't preserve Layer 3,4 data:

after tunneling, before connecting

backslasher@client$ netstat -nap | grep -P '(ssh|redis)'
...
tcp        0      0 127.0.0.1:20000             0.0.0.0:*                   LISTEN      20879/ssh
tcp        0      0 10.105.16.225:53142         <SERVER IP>:22              ESTABLISHED 20879/ssh
...

backslasher@server$ netstat -nap | grep -P '(ssh|redis)'
...
tcp        0      0 0.0.0.0:6379                0.0.0.0:*                   LISTEN      54328/redis-server
tcp        0      0 <SERVER IP>:22              <CLIENT IP>:53142           ESTABLISHED 53692/sshd
...

after tunneling and connecting

backslasher@client$ netstat -nap | grep -P '(ssh|redis)'
...
tcp        0      0 127.0.0.1:20000             0.0.0.0:*                   LISTEN      20879/ssh
tcp        0      0 127.0.0.1:20000             127.0.0.1:53142             ESTABLISHED 20879/ssh
tcp        0      0 127.0.0.1:53142             127.0.0.1:20000             ESTABLISHED 21692/redis-cli
...

backslasher@server$ netstat -nap | grep -P '(ssh|redis)'
...
tcp        0      0 0.0.0.0:6379                0.0.0.0:*                   LISTEN      54328/redis-server
tcp        0      0 127.0.0.1:6379              127.0.0.1:42680             ESTABLISHED 54328/redis-server
tcp        0      0 127.0.0.1:42680             127.0.0.1:6379              ESTABLISHED 54333/sshd
tcp        0      0 <SERVER IP>:22              <CLIENT IP>:53142           ESTABLISHED 52889/sshd
...

So I'm going to use SSH tunneling, since it seems that my OpenVPN isn't misconfigured or anything, just not the right tool for the job.