This post follows Installing TinySSH.
Disclaimer: I’m in not a crypto expert! Don’t take anything below for granted.
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.
sudo dropbear -p 10021 -E
tcpserver -HRDl0 0.0.0.0 10022 ./tinysshd -v ./keys
sudo dropbear -p 10021 -E
~/.ssh/authorized_keys
is cleared up to only contain the key (RSA or
Ed25519) being testing.
~/.ssh/config
is set to:
Ciphers chacha20-poly1305@openssh.com
HostKeyAlgorithms ssh-ed25519
KexAlgorithms curve25519-sha256@libssh.org
Ciphers chacha20-poly1305@openssh.com,aes128-ctr,aes256-ctr
Cipher stream protocol preference was detected using:
ssh -vvv $HOST "exit 0" |& grep "debug1: kex: server->client"
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 |
~/.ssh/config
or on the server in
/etc/ssh/sshd_config
.
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 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
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.
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
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 |
This is in no way scientific, I ssh’ed in and look at the ps
output of the
server process for the connection.
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.
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.