Improving SSH Performance with Faster Ciphers
SSH performance is constrained by cipher choice, especially for large file transfers over high-bandwidth links where CPU becomes the bottleneck. Selecting the right cipher, key exchange algorithm, and compression settings can yield substantial throughput improvements.
Current Cipher Landscape
Modern OpenSSH (7.4+) has deprecated or removed weak ciphers. Here’s what’s viable today:
Secure and performant:
chacha20-poly1305@openssh.com— Best choice for most workloads. Software-based, no hardware dependency, ~400-600 MB/s on modern CPUs.aes256-gcm@openssh.com/aes128-gcm@openssh.com— Hardware-accelerated via AES-NI when available, ~300-500 MB/s.aes256-ctr/aes128-ctr— Fallback for systems without AES-NI support, slower but universally compatible.
Avoid entirely:
arcfour,rc4— Cryptographically broken; removed from OpenSSH 7.4+.blowfish-cbc— 64-bit block size, practical security weaknesses.3des— Obsolete, too slow.
Check Your Hardware
Before configuring, verify AES-NI support on your CPU:
grep aes /proc/cpuinfo
If aes appears in the output, your CPU supports AES-NI, making GCM ciphers fast. On systems without it, chacha20-poly1305 or AES-CTR are better choices.
Client Configuration
Edit ~/.ssh/config:
Host *
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512
HostKeyAlgorithms ecdsa-sha2-nistp256,rsa-sha2-512,rsa-sha2-256
Compression no
Modern key exchange and host key algorithms are equally important. Avoid diffie-hellman-group1, group14, and legacy RSA signatures.
Server Configuration
Edit /etc/ssh/sshd_config:
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512
HostKeyAlgorithms ecdsa-sha2-nistp256,rsa-sha2-512,rsa-sha2-256
Compression no
Then reload SSH:
sudo systemctl reload sshd
Verify the reload succeeds without breaking existing connections:
sshd -t && sudo systemctl reload sshd
Compression Tuning
Compression helps on slow WAN links but wastes CPU on fast LANs. General rules:
- Disable for LAN/datacenter transfers — Disk and network I/O will be the bottleneck, not encryption.
- Enable selectively for slow links — Useful for high-latency or bandwidth-constrained connections.
If enabling compression, set CompressionLevel 6 for a reasonable compression-ratio-to-CPU tradeoff. Levels 7-9 add diminishing returns in compression with significant CPU cost.
Host-specific tuning in ~/.ssh/config:
# Fast local cluster
Host 10.0.*
Compression no
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
# Slow remote link
Host slow-remote.example.com
Compression yes
CompressionLevel 6
Verify Cipher Negotiation
Check what cipher is actually negotiated:
ssh -v user@host 2>&1 | grep "encrypt ciphers:"
Output should show:
debug1: kex: encrypt ciphers: chacha20-poly1305@openssh.com
If an older cipher appears, check that neither client nor server config is forcing a legacy cipher, and that both have compatible algorithm lists.
Benchmark Your Setup
Test real-world performance with a large file:
# Compression disabled
time scp largefile.bin user@host:/tmp/
# With rsync (allows resume and skipping unchanged files)
time rsync -avz --stats largefile.bin user@host:/tmp/
# SSH with verbose timing
ssh user@host "dd if=/dev/zero bs=1M count=1000" | md5sum
On modern hardware with chacha20-poly1305 or AES-GCM, expect 300+ MB/s over gigabit links. Disk I/O, not encryption, typically becomes the limiting factor.
Common Pitfalls
Mismatched client and server ciphers — If the server doesn’t list a cipher the client prefers, SSH falls back to the next compatible option. Always ensure both sides have overlapping algorithm lists.
Compression enabled by default for all hosts — Legacy configurations sometimes enable global compression. Disable it and enable only where needed.
Using RSA key exchange — Older systems may default to diffie-hellman-group14-sha1 or worse. Explicitly set KexAlgorithms to enforce modern alternatives.
ED25519 host keys — Faster and stronger than RSA for authentication. If your system supports it (OpenSSH 6.3+), consider switching:
sudo ssh-keygen -A
This generates ED25519 and other key types. Ensure HostKeyAlgorithms includes ssh-ed25519 if available.
Summary
Start with chacha20-poly1305@openssh.com as your primary cipher paired with modern key exchange algorithms. Disable compression globally and enable it only for high-latency links. Test in your environment—network conditions, hardware capabilities, and file sizes all affect real-world throughput. On current hardware, you should easily saturate gigabit links with encryption overhead below 10%.

Below is a script I made that you can use to benchmark each cipher. I use /dev/zero, /dev/null, and localhost to eliminate potential i/o bottlenecks. The results should report realistic maximum transfer throughput. There is also the “openssl speed” benchmark, but I find that doesn’t produce accurate data transfer throughput results.
The following code works on Linux, Mac OS X, and Solaris:
for i in 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; do dd if=/dev/zero bs=1000000 count=1000 2> /dev/null | ssh -c $i localhost "(time -p cat) > /dev/null" 2>&1 | grep real | awk '{print "'$i': "1000 / $2" MB/s" }'; doneWith AES-NI acceleration, aes128-gcm@openssh.com is the fastest cipher on OpenSSH Intel systems… take a look:
Intel Core i7-2635QM (MacBookPro8,2)/ Fedora 21:
3des-cbc 18.34 MB/s
aes128-cbc 167.54 MB/s
aes128-ctr 230.26 MB/s
aes128-gcm@openssh.com 328.37 MB/s
aes192-cbc 158.13 MB/s
aes192-ctr 228.28 MB/s
aes256-cbc 148.89 MB/s
aes256-ctr 222.80 MB/s
aes256-gcm@openssh.com 317.49 MB/s
arcfour 178.52 MB/s
arcfour128 177.52 MB/s
arcfour256 178.50 MB/s
blowfish-cbc 66.75 MB/s
cast128-cbc 58.68 MB/s
chacha20-poly1305@openssh.com 131.70 MB/s
rijndael-cbc@lysator.liu.se 149.04 MB/s
Mac OS X 10.10 cipher support is abysmal compared to Linux, take a look at the results:
Intel Core i7-2635QM (MacBookPro8,2)/ Mac OS X 10.10:
3des-cbc 14.98 MB/s
aes128-cbc 88.08 MB/s
aes128-ctr 87.18 MB/s
aes192-cbc 85.18 MB/s
aes192-ctr 84.10 MB/s
aes256-cbc 82.51 MB/s
aes256-ctr 81.48 MB/s
arcfour 133.93 MB/s
arcfour128 133.99 MB/s
arcfour256 133.93 MB/s
blowfish-cbc 39.96 MB/s
cast128-cbc 39.06 MB/s
rijndael-cbc@lysator.liu.se 82.24 MB/s
Good tool and info. Thanks for the sharing!
With automatic cipher selection:
for i in `ssh -Q cipher`; do dd if=/dev/zero bs=1000000 count=1000 2> /dev/null | ssh -c $i localhost “(time -p cat) > /dev/null” 2>&1 | grep real | awk ‘{print “‘$i’: “1000 / $2″ MB/s” }’; done
@Nikolas:
You test are performed on the same hardware, just different OS ?
If so, the difference is indeed quite impressive.
Make sense that a CPU with AES hardware support performs better, no ?
I think that you need to take into account both machine, a ssh is not usualy used to connect locally.
I use ssh for two main purpose.
– edit file remotely, using a screen and vi.
– ssh -Y to forward some graphical application (wireshark for instance)
the cipher, the MACs and the compression have huge and different impact according to the usecase.
I use one dedicated ~/.ssh/config entry for each usecase, different parameters (to connect to the same server).
I have different parameters per server, as some have aes hardware acceleration and some don’t.
I also take into account the network, when I work on my laptop on wifi, I use different parameters than ethernet.
Bref, it’s a very deep and non-deterministic science.
I don’t think there is one config that rules them all.