Hi, this is flownspores who is working at TwoGate inc. This article is my first one! And this is the first of my english blog article in my life. If you find any weird grammar mistakes or misspells, feel free to comment below.
Making the fastest SSH connection
I set up my raspberry pi 3's sshd then I just wondered about performance. Raspberry pi 3 has a tiny ARM cpu with no AES acceleration. Recent Intel or AMD's cpus have AES-NI which can accelerate AES encryption and decryption.
Without AES acceleration, which cipher algorithm is the fastest? That's my question.
I also want to test key exchange algorithms and MAC algorithms. Key exchange algorithm is used to establish of ssh connection (and during rekeying). Public-key cryptography is a secure way to communicate, but it is too slow to use every transfer. So that symmetric-key algorithms are used during data transfer. Public-key encryption is only used to encrypt symmetric-key. Key exchange algorithm is the way to exchange symmetric-key in a secure way. I am not a specialist in this domain, so you may read more details about ssh encryption on the Internet.
Testing ssh algorithms
There are several items in SSH configuration that can be changed, and I compared the algorithms for each. Key exchange algorithms (Kex), Algorithms of Message authentication code (MAC), Cipher algorithms.
KexAlgorithm
SSH's KexAlgorithm is a key exchange algorithm. You can see algorithms which can be used in your ssh connection.
$ ssh -Q kex diffie-hellman-group1-sha1 diffie-hellman-group14-sha1 diffie-hellman-group14-sha256 diffie-hellman-group16-sha512 diffie-hellman-group18-sha512 diffie-hellman-group-exchange-sha1 diffie-hellman-group-exchange-sha256 ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521 curve25519-sha256 curve25519-sha256@libssh.org sntrup4591761x25519-sha512@tinyssh.org
Diffie-hellman (DH) key exchange is common in the past but newer algorithms like ECDH or curve25519 have appeared.
So the kex algorithm is used only in establishing the connection*1, I just write the code which simply connects the server and executes :
then quickly disconnects. :
is a command which does nothing.
ssh -v -o "ControlMaster=no" -o "ControlPath=none" -o "Compression=no" -o "KexAlgorithms=..." host :
As you can see, I wrote some additional options: "ControlMaster/Path=no" and "Compression=no". ControlMaster/ControlPath option is to multiplex ssh connections which holds persistent connections to the server. At this time, this feature bothers my testing so it should be turned off. Compression is also unnecessary feature during test*2.
I've tested each KexAlgorithms per 5 times. Then I calculated the median value of each algorithm. The graph is shown below.
- Testing environment
- Client: Mac mini 2018 Core i7-8700B equipped with 10Gb Ethernet
- macOS Catalina, OpenSSH_8.1p1, LibreSSL 2.7.3
- Server: Raspberry Pi 3B+ with Heat sink
- Debian 10 (Raspberry Pi OS)
- Network: 1GbE
- Client: Mac mini 2018 Core i7-8700B equipped with 10Gb Ethernet
As you can see from the graph, the fastest key exchange algorithm is ecdh-sha2-nistp256
. The slowest is diffie-hellman-group-exchange-sha256
. Curve25519-*
appears to be doing well. SHA1 is considered to be obsolete, so you may not use diffie-hellman-group14-sha1
.
I will use curve25519-sha256
which is a great balance of speed and security.
MACs
MAC stands for message authentication code, which is like a hash function. (This is a very rough explanation. You may read some informative information on the Internet.)
You can get MAC algorithms to type ssh -Q mac
that can be used in your ssh command.
$ ssh -Q mac hmac-sha1 hmac-sha1-96 hmac-sha2-256 hmac-sha2-512 hmac-md5 hmac-md5-96 umac-64@openssh.com umac-128@openssh.com hmac-sha1-etm@openssh.com hmac-sha1-96-etm@openssh.com hmac-sha2-256-etm@openssh.com hmac-sha2-512-etm@openssh.com hmac-md5-etm@openssh.com hmac-md5-96-etm@openssh.com umac-64-etm@openssh.com umac-128-etm@openssh.com
MAC is used only for non-AEAD encryption like aes256-ctr
, aes256-cbc
. AEAD encryption like aes256-gcm
already has an MAC-ish authentication algorithm itself, so I use encryption of aes256-gcm
at this time.
Sending large file to Raspberry pi
The test is transferring a 100MiB file by scp. Measuring time of sending client to server (/dev/null
).
Yes I know that scp is outdated today, but sftp is complex to use from programs. Rsync can't write out to /dev/null. that's why i use scp.
- Tesing environment
- hardware configuration is same as before.
- using
aes256-ctr
as cipher
The fastest algorithm is umac-64@openssh.com
and umac-128-etm@openssh.com
. The slowest is hmac-sha2-512
.
ETM means encrypt-then-mac, which is considered stronger than non-ETM (like MAC-then-Encrypt). You should use *-etm
over non-ETM.
Note that MAC option is not effective if you use AEAD encryption (like AES-GCM). AES-GCM is preferred over non-GCM for security reasons.
Receiving large file from Raspberry pi
The fastest is umac-64@openssh.com
and umac-64-etm@openssh.com
. umac-128-etm@openssh.com
and umac-128@openssh.com
is also fast enough.
umac-*
s are the best choice for both sending and receiving.
Ciphers
Finally I have tested cipher algorithms. RC4 (arcfour) is considered the fastest algorithm on non-AES accelerated CPUs. But RC4 is considered a weak algorithm today. It is not usable algorithms in my OpenSSH:
$ ssh -Q cipher 3des-cbc aes128-cbc aes192-cbc aes256-cbc rijndael-cbc@lysator.liu.se aes128-ctr aes192-ctr aes256-ctr aes128-gcm@openssh.com aes256-gcm@openssh.com chacha20-poly1305@openssh.com
I use these algorithms for testing at this time.
- Tesing environment
- hardware configuration is same as before.
- for non-AEAD cipher,
umac-128-etm@openssh.com
as MAC - 100MiB transfer, same as before
Can't wait to see the results? Let's see.
Sending large file to Raspberry pi
Surprisingly, the newest algorithm chacha20-poly1305@openssh.com
is the slowest 😭.
The fastest is aes128-ctr
.
Why? When I transferring large file from Mac mini, mini's AES-NI hardware acceleration is used for encryption. So this test is not informative for raspberry pi's performance index.
Receiving large file from Raspberry pi
So I've also tested reverse transmission. Client to RPi. But the results are not much different.
The fastest is aes128-ctr
. *-ctr
s are the fastest in this test.
The transfer rate may be capped by the bandwidth of the Raspberry Pi's SD card.
Despite these results, I would still use *-gcm
for security reason.
Conclusion
If you want to harden security with small amount of speed sacrifice:
curve25519-sha256
as KexAlgorithmsaes*-gcm@openssh.com
as Ciphers
If you want the fastest connection (not so bad for security), use:
ecdh-sha2-nistp256
as KexAlgorithmsumac-*-etm@openssh.com
as Macsaes128-ctr
as Ciphers
Benchmarking script
I've tested the performance of ssh in various algorithms by this script. This is an automated script that connects host with many different ssh configurations. Then this script writes CSV files. Each test is executed only one time, so you may need to run the test repeatedly to get accurate results. If you run this script for remote server over the Internet, results may not be accurate. So you might be better using it for local network.