Introduction

During the SSH handshake, the client and server negotiate which encryption cipher, key exchange algorithm, and MAC (message authentication code) to use. If there is no common algorithm between the two sides, the connection fails with no matching cipher found, no matching key exchange method found, or no matching MAC found. This commonly occurs when connecting from a modern client to a legacy server, or when security hardening disables older algorithms on one side.

Symptoms

  • ssh user@old-server fails with no matching cipher found. Their offer: aes128-cbc,3des-cbc
  • Unable to negotiate with X port 22: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1
  • no matching MAC found. Their offer: hmac-sha1,hmac-md5
  • Connection fails immediately after TCP connection is established
  • ssh -v shows the algorithm lists from both sides with no overlap

Common Causes

  • Modern SSH client (OpenSSH 8.8+) disables weak algorithms by default
  • Legacy SSH server only supports deprecated algorithms (3des-cbc, diffie-hellman-group1-sha1)
  • Security hardening (CIS benchmarks) removed all but the strongest algorithms
  • Network equipment (Cisco IOS, old routers) using obsolete SSH implementations
  • FIPS mode enabled on one side restricting available algorithms

Step-by-Step Fix

  1. 1.Identify the incompatible algorithms with verbose output:
  2. 2.```bash
  3. 3.ssh -v user@old-server 2>&1 | grep -E "offer|match|no matching"
  4. 4.# Shows exactly which algorithms each side supports
  5. 5.`
  6. 6.Check available algorithms on both sides:
  7. 7.```bash
  8. 8.# On the client:
  9. 9.ssh -Q cipher
  10. 10.ssh -Q kex
  11. 11.ssh -Q mac

# On the server: sshd -T | grep -E "ciphers|kexalgorithms|macs" ```

  1. 1.Connect by enabling the required legacy algorithms:
  2. 2.```bash
  3. 3.# Enable specific weak algorithms for this connection only
  4. 4.ssh -o KexAlgorithms=+diffie-hellman-group1-sha1 \
  5. 5.-o Ciphers=+aes128-cbc \
  6. 6.-o HostKeyAlgorithms=+ssh-rsa \
  7. 7.user@old-server
  8. 8.`
  9. 9.Make the configuration persistent for specific hosts:
  10. 10.```bash
  11. 11.# In ~/.ssh/config:
  12. 12.Host legacy-server
  13. 13.HostName 10.0.5.100
  14. 14.User admin
  15. 15.KexAlgorithms +diffie-hellman-group1-sha1
  16. 16.Ciphers +aes128-cbc,3des-cbc
  17. 17.HostKeyAlgorithms +ssh-rsa
  18. 18.MACs +hmac-sha1,hmac-md5
  19. 19.`
  20. 20.Upgrade the server's SSH configuration (preferred long-term fix):
  21. 21.```bash
  22. 22.# On the legacy server, update sshd_config:
  23. 23.Ciphers aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes128-gcm@openssh.com
  24. 24.KexAlgorithms curve25519-sha256,diffie-hellman-group-exchange-sha256
  25. 25.MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
  26. 26.sudo systemctl restart sshd
  27. 27.`
  28. 28.For network equipment that cannot be upgraded, use a jump host:
  29. 29.```bash
  30. 30.# SSH to a modern jump host first, then use its SSH client to reach the legacy device
  31. 31.ssh -J modern-jump user@legacy-switch
  32. 32.# The jump host may have a more permissive SSH config
  33. 33.`

Prevention

  • Plan algorithm compatibility when deploying new SSH servers or upgrading clients
  • Maintain a list of legacy systems requiring special SSH configuration
  • Use SSH certificates to reduce dependency on specific key exchange algorithms
  • Document special SSH config requirements for each legacy system
  • Create SSH config snippets that can be included for specific device types (network-equipment, legacy-linux, etc.)