Skip to content

Instantly share code, notes, and snippets.

@joeharr4
Forked from dlenski/ssh-cipher-benchmark.sh
Last active November 18, 2024 03:43
Show Gist options
  • Save joeharr4/c7599c52f9fad9e53f62e9c8ae690e6b to your computer and use it in GitHub Desktop.
Save joeharr4/c7599c52f9fad9e53f62e9c8ae690e6b to your computer and use it in GitHub Desktop.
Check speed of ssh cipher(s) on your system
#!/bin/bash
# ssh-cipher-benchmark.sh - Assesses speed of SSH encryption between specific hosts.
# Usage:
# ssh-cipher-benchmark.sh <remotehost> [ciphers]
# Default ciphers: all we can find...
#
# Note: In some cases, the first cipher tested runs faster than the others, regardless of order.
# Cause of this is not known, but changing the order of testing shows it to be true. Run the
# first one twice if you suspect this. Perhaps it is due to buffering?
#
# Hosted at:
# https://gist.github.com/dlenski/e42a08fa27e97b0dbb0c0024c99a8bc4#file-ssh-cipher-benchmark-sh
# Which was based on:
# Based on: http://www.systutorials.com/5450/improving-sshscp-performance-by-choosing-ciphers/#comment-28725
#
# You should set up PublicKey authentication so that you don't have to type your
# password for every cipher tested.
# parse command line
remote=${1:-localhost} # machine to test
shift
set -o pipefail
ciphers="$@"
if [[ -n "$ciphers" ]]; then echo "User-supplied ciphers: $ciphers"; fi
if [[ -z "$ciphers" ]]; then
ciphers=$(egrep '^\s*Ciphers' /etc/ssh/sshd_config|sed 's/Ciphers//; s/,/ /g')
if [[ -n "$ciphers" ]]; then echo "/etc/ssh/sshd_config allows these ciphers: $ciphers"; fi
fi
if [[ -z "$ciphers" ]]; then
ciphers=$(echo $(ssh -Q cipher))
if [[ -n "$ciphers" ]]; then echo "ssh -Q cipher reports these ciphers: $ciphers"; fi
fi
if [[ -z "$ciphers" ]]; then
read -rd '' ciphers <<EOF
3des-cbc aes128-cbc aes128-ctr aes128-gcm@openssh.com aes192-cbc aes192-ctr
aes256-cbc aes256-ctr aes256-gcm@openssh.com arcfour arcfour128 arcfour256
blowfish-cbc cast128-cbc chacha20-poly1305@openssh.com rijndael-cbc@lysator.liu.se
EOF
echo "Default cipher test list: $ciphers"
fi
echo
echo "For each cipher, will transfer 1000 MB of zeros to/from ${remote}."
echo
tmp=$(mktemp)
for i in $ciphers
do
echo -n "$i: "
dd if=/dev/zero bs=1000000 count=1000 2> /dev/null |
ssh -c $i -o Compression=no ${remote} "(time -p cat) > /dev/null" > $tmp 2>&1
if [[ $? == 0 ]]; then
grep real $tmp | awk '{print 1000 / $2" MB/s" }'
else
echo "failed, for why run: ssh -vc $i ${remote}"
fi
done
@mrl22
Copy link

mrl22 commented Dec 15, 2020

Thank you. Worked a treat. As I was testing over the internet I did need to alter dd to output 100MB file.

@nerrons
Copy link

nerrons commented Mar 29, 2021

Thanks, this is really helpful.

@JJGO
Copy link

JJGO commented Jul 2, 2021

time -p does not work if the remote shell is zsh. To work around this, you can use /usr/bin/time -p instead, as long as the time program is installed in the remote machine.

@jeremylowery
Copy link

Thank you for this script. Was exactly what I was looking for trying to test AES-NI.

@deajan
Copy link

deajan commented Oct 3, 2022

Quick and dirty automated with sshpass. Also removed the -n from echo -n "$i: " for more readability.

@Shulyaka
Copy link

The script tests the upload speed. To test the download speed I've changed lines 56-57 to this:

  ssh -c $i -o Compression=no ${remote} "dd if=/dev/zero bs=1000000 count=1000 2> /dev/null" |
  (time -p cat) > /dev/null 2> $tmp

@lainedfles
Copy link

Hi, thanks for this (and for the comments!). @Shulyaka I've implemented default bidirectional testing (and much more!) based on your suggestion. Take a look. Here is an example:

[user@hostname ssh-cipher-benchmark]$ bash ssh-cipher-benchmark.sh size=5000
For each cipher, transfer 5000 MB of zero data to/from localhost (compression=no).

CIPHER                           RATE            STATUS
3des-cbc                         0 MB/s          send failed, for why run: ssh -vc 3des-cbc localhost
3des-cbc                         0 MB/s          receive failed, for why run: ssh -vc 3des-cbc localhost
aes128-cbc                       0 MB/s          send failed, for why run: ssh -vc aes128-cbc localhost
aes128-cbc                       0 MB/s          receive failed, for why run: ssh -vc aes128-cbc localhost
aes192-cbc                       0 MB/s          send failed, for why run: ssh -vc aes192-cbc localhost
aes192-cbc                       0 MB/s          receive failed, for why run: ssh -vc aes192-cbc localhost
aes256-cbc                       0 MB/s          send failed, for why run: ssh -vc aes256-cbc localhost
aes256-cbc                       0 MB/s          receive failed, for why run: ssh -vc aes256-cbc localhost
aes128-ctr                       2032.52 MB/s    send success
aes128-ctr                       1893.94 MB/s    receive success
aes192-ctr                       1976.28 MB/s    send success
aes192-ctr                       1851.85 MB/s    receive success
aes256-ctr                       1930.5 MB/s     send success
aes256-ctr                       1818.18 MB/s    receive success
aes128-gcm@openssh.com           2325.58 MB/s    send success
aes128-gcm@openssh.com           2164.5 MB/s     receive success
aes256-gcm@openssh.com           2222.22 MB/s    send success
aes256-gcm@openssh.com           2040.82 MB/s    receive success
chacha20-poly1305@openssh.com    1054.85 MB/s    send success
chacha20-poly1305@openssh.com    996.016 MB/s    receive success

@Shulyaka
Copy link

Looks good!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment