TinySSH vs others

Comparison of Dropbear, OpenSSH and TinySSH
2016-01-26 sysadmin

This post follows Installing TinySSH.

Disclaimer: I’m in not a crypto expert! Don’t take anything below for granted.

Security features

The clear winner here is OpenSSH due to its maturity and privilege separation feature. Microsoft recently committed to support OpenSSH, albeit still in a fork.

Setup

Caveats

Preferred cipher stream protocol

Measurements

Cipher stream protocol preference was detected using:

ssh -vvv $HOST "exit 0" |& grep "debug1: kex: server->client"

Results

Server Host .ssh/config Cipher chosen
dropbear ARM Default aes128-ctr with hmac-md5
dropbear ARM Strict Failure to connect
dropbear x64 Default aes128-ctr with hmac-md5
dropbear x64 Strict Failure to connect
openssh ARM Default aes128-ctr with hmac-sha1-etm
openssh ARM Strict chacha20-poly1305@openssh.com
openssh x64 Default aes128-ctr with hmac-md5-etm
openssh x64 Strict chacha20-poly1305@openssh.com
tinyssh ARM Default chacha20-poly1305@openssh.com
tinyssh ARM Strict chacha20-poly1305@openssh.com
tinyssh x64 Default chacha20-poly1305@openssh.com
tinyssh x64 Default chacha20-poly1305@openssh.com

Connection latency

Connection latency is important for use case like a git server where repeated but short lived connections are frequently done. In practice, we’d aim for sub 200ms on a local network with high performance machines to reduce the perceptible overhead.

Measurements

Measurements are done by taking the median value of 5 repetitions via:

(for i in {0..4}; do time ssh $HOST "exit 0"; done) |& grep real | sort -n

Results

Server Host .ssh/config Algo Latency
dropbear ARM Default RSA 287ms
dropbear x64 Default RSA 95ms
openssh ARM Default RSA 206ms
openssh ARM Default Ed25519 241ms
openssh ARM Strict RSA 218ms
openssh ARM Strict Ed25519 252ms
openssh x64 Default RSA 310ms
openssh x64 Default Ed25519 304ms
openssh x64 Strict RSA 309ms
openssh x64 Strict Ed25519 334ms
tinyssh ARM Default Ed25519 192ms
tinyssh ARM Strict Ed25519 197ms
tinyssh x64 Default Ed25519 103ms
tinyssh x64 Strict Ed25519 132ms

The results clearly warrants a follow up with further diagnostics.

I/O Performance

Measurements

The test reads from /dev/zero and sends it over stdout. Since the stream is not compressed and network not encumbered, this measures the cipher stream performance with minimal CPU overhead and no disk I/O.

Measurements are done by taking the median value of 5 repetitions via:

(for i in {0..4}; do time ssh $HOST "dd if=/dev/zero count=1024 bs=1048576" > /dev/null; done) |& grep real | sort -n

Results

The Raspberry Pi2 has a 100mbit ethernet port connected over USB, so it’s bound to be significantly slower.

Server Host .ssh/config Algo Time to send 1Gb Speed
dropbear ARM Default RSA 155942ms 6.6MiB/s
dropbear x64 Default RSA 10240ms 100.0MiB/s
openssh ARM Default RSA 120216ms 8.5MiB/s
openssh ARM Default Ed25519 114913ms 8.9MiB/s
openssh ARM Strict Ed25519 114913ms 8.9MiB/s
openssh x64 Default RSA 9464ms 108.2MiB/s
openssh x64 Default Ed25519 9450ms 108.4MiB/s
openssh x64 Strict Ed25519 9568ms 107.0MiB/s
tinyssh ARM Default Ed25519 124963ms 8.2MiB/s
tinyssh x64 Default Ed25519 9319ms 109.9MiB/s
tinyssh x64 Strict Ed25519 9515ms 107.6MiB/s

Memory use

Measurement

This is in no way scientific, I ssh’ed in and look at the ps output of the server process for the connection.

Results

The memory values are for up to 3 processes involved: daemon / priv separation / connection

The values varies a lot from one host to another (e.g. between two Ubuntu 14.04 x64 hosts) so take these with a large grain of salt.

Server Host .ssh/config Algo Virtual Memory Size Resident Set Size*
dropbear ARM Default RSA 2456 / N/A / 2908 1648 / N/A / 1860
openssh ARM Default Ed25519 7808 / 11072 / 11072 4388 / 4932 / 3104
openssh ARM Default RSA 7808 / 11072 / 11072 4388 / 4956 / 3048
tinyssh ARM Default Ed25519 N/A / N/A / 3176 N/A / N/A / 2292
dropbear x64 Default RSA 11032 / N/A / 19464 1300 / N/A / 2268
openssh x64 Default Ed25519 61376 / 109796 / 109796 1304 / 6588 / 3904
openssh x64 Default RSA 61376 / 109796 / 109796 1304 / 6556 / 4108
tinyssh** x64 Default Ed25519 4244 / N/A / 15720 1136 / N/A / 2792

5Mb on a <=1Gb machine is a welcome saving, yet OpenSSH’s privilege separation security benefit is undeniable.

Conclusion

It’s definitely too early to use TinySSH in production, wouldn’t it be because because privilege separation is not implemented and as far as I know nobody did an external review of the code. For security products, “it works” is not enough. I can see a niche on embedded devices, it could be a good choice performance wise especially for Linux based system using systemd, the gain in memory use is real and I/O performance significant. It could probably be a good case for specific use like boot time remote LUKS decryption for desktop use.

In particular, Dropbear doesn’t seem to use sound default values so replacing uses of Dropbear by TinySSH should be considered in the coming years. TinySSH is significantly faster than Dropbear in connection latency on ARM and in throughput on all platforms.

As I noted in my previous post, I’m concerned by TinySSH coding style (lacks of brackets around conditions: a recipe for another goto fail) but I like the philosophy and the fact that less secure algorithms (like md5) are simply not implemented. The coding style could probably be fixed if desired by the author.

There’s definitely caveats in moving from RSA keys to Ed25519. OSX 10.11 supports Ed25519 just fine yet Gnome keyring still doesn’t support Ed25519 key, one has to use OpenSSH’s agent. An Ed25519 key will also not be usable on older servers, requiring users to have 2 keys, one RSA, one Ed25519. But at the same time, if you connect to an old server not supporting Ed25519, you should question its security!

Updates:

2016-01-29: Added note about OSX 10.11 client default settings which fail with tinyssh.