| Tested on | RHEL 10.2 client (OpenSSH_9.9p1, crypto-policy DEFAULT) and Ubuntu 26.04 client (OpenSSH_10.2p1) against an isolated legacy SSH server container on port 2233/2234 |
|---|---|
| Package | openssh-clients-9.9p1-25.el10_2.x86_64 (RHEL 10.2 lab captures); openssh-client 1:10.2p1-2ubuntu3.6 (Ubuntu 26.04) |
| Scope | Client-side KEX negotiation failures (no matching key exchange method found) and the follow-on errors that appear after KEX is fixed (no matching host key type found, no matching cipher found). Does not cover RSA public-key signature rejects (PubkeyAcceptedAlgorithms) or password auth failures after negotiation succeeds. |
| Related guides | ssh command Fix userauth_pubkey ssh-rsa not in PubkeyAcceptedKeyTypes |
In this article we will fix the OpenSSH client error no matching key exchange method found.
This error means your SSH client and the remote server cannot agree on a method for creating the encrypted SSH session. OpenSSH calls this method a key-exchange, or KEX, algorithm. The most common cause is a modern client connecting to an older switch, router, appliance, or SSH server that offers only deprecated KEX algorithms, but restrictive client or server configuration can produce the same error. The failure happens before authentication, so read Their offer: first and enable only the KEX name the server actually lists.
Quick fix and what the error means
The canonical message looks like this:
Unable to negotiate with legacy-switch.lab.example: no matching key exchange method found.
Their offer: diffie-hellman-group1-sha1Another common variant names the IP and port explicitly:
Unable to negotiate with 203.0.113.10 port 22:
no matching key exchange method found.
Their offer: diffie-hellman-group14-sha1What it means:
- The SSH client and server could not pick a shared key-exchange algorithm
- The server told you which KEX names it supports in
Their offer: - The client never reached host-key verification, user authentication, or shell access
Quick fix when the offer names a single algorithm — copy that exact token:
ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 legacy@legacy-switch.lab.exampleIf the offer is diffie-hellman-group14-sha1, use that name instead:
ssh -oKexAlgorithms=+diffie-hellman-group14-sha1 legacy@legacy-switch.lab.exampleOpenSSH documents the + prefix as append to the compiled-in default list instead of replacing it. That keeps modern KEX algorithms available for other hosts while allowing one legacy name for a single connection.
Why Their offer matters
Read Their offer: first. Do not copy a random KEX fix from another article. The option you enable must match an algorithm the server actually offers.
OpenSSH's own legacy documentation uses exactly this pattern: the client may support a weak algorithm, but has disabled it by default. Their offer: is the list of KEX algorithms the server is willing to use. Your client rejected all of them, so you need to enable one compatible choice temporarily.
This is not an SSH user-key problem
Do not generate a new SSH key to fix this error. KexAlgorithms controls how the client and server establish the encrypted session. That step is separate from the RSA or Ed25519 key pair used later for user authentication. Running ssh-keygen will not resolve diffie-hellman-group1-sha1 or diffie-hellman-group14-sha1 in the offer line.
When several algorithms are listed
Real errors often list more than one KEX name:
Their offer: diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1If several names are listed, enable only one. If the server offers a SHA-2 KEX such as diffie-hellman-group-exchange-sha256 or diffie-hellman-group14-sha256, prefer that over any *-sha1 option. Only fall back to SHA-1 when no stronger shared algorithm is available.
Among SHA-1 options, choose the less outdated name your client supports — for example, try diffie-hellman-group14-sha1 before diffie-hellman-group1-sha1. If diffie-hellman-group-exchange-sha1 is the only name your client can match after checking ssh -G, use that one.
Append one name, reconnect, and stop when the KEX error disappears.
Negotiation stages you will see later
SSH negotiation is sequential. Each stage must succeed before the next one runs:
| Stage | What is negotiated | Typical error when it fails |
|---|---|---|
| 1. Key exchange (KEX) | How the session key is derived | no matching key exchange method found |
| 2. Host key | Which server host-key algorithm signs the connection | no matching host key type found |
| 3. Cipher (+ MAC) | Bulk encryption and integrity | no matching cipher found |
| 4. Authentication | Password, public key, keyboard-interactive | Permission denied or pubkey-specific errors |
The Their offer: suffix is the server's answer at the stage that failed. It is not a full capability list for the device.
Restrictive configuration can cause the same KEX error on otherwise modern hosts. An Ubuntu peer with a custom sshd_config that allows only diffie-hellman-group-exchange-sha1, diffie-hellman-group14-sha1, and diffie-hellman-group1-sha1 can trigger the same client error as an old network switch. The fix path is still the same: read the offer and enable one matching name.
Check supported vs enabled KEX algorithms
Two different ssh queries answer two different questions.
What ssh -Q kex shows
ssh -Q kex lists algorithms compiled into the client binary. It does not mean every name is enabled in a default connection.
ssh -Q kex | head -8diffie-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-nistp256diffie-hellman-group14-sha1 appears in that list, yet a default connection can still fail. So ssh -Q kex answers “does this OpenSSH build know this algorithm?”, while ssh -G host answers “will this connection actually try it?”
What ssh -G host shows
ssh -G prints the effective client configuration for a target, including the ordered KEX list that a real connection would use. See the SSH config file guide for other fields this command exposes.
Check the default KEX list:
ssh -G legacy@203.0.113.10 | grep '^kexalgorithms 'A typical modern default list ends with curves and diffie-hellman-group14-sha256 but not diffie-hellman-group14-sha1:
kexalgorithms mlkem768x25519-sha256,sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256Confirm that the one-off + override appends the legacy algorithm to the effective list:
ssh -oKexAlgorithms=+diffie-hellman-group14-sha1 -G legacy@203.0.113.10 | grep '^kexalgorithms 'The output should now include diffie-hellman-group14-sha1. Trust ssh -G over ssh -Q when you need to know what a connection will really send.
Temporarily enable the offered KEX algorithm
When the offer is diffie-hellman-group14-sha1
group14-sha1 is a common offer on older switches, routers, and SSH servers.
Run one connection with the legacy KEX appended:
ssh -oKexAlgorithms=+diffie-hellman-group14-sha1 legacy@legacy-switch.lab.exampleIf you only need a non-interactive check that KEX now negotiates, add -o BatchMode=yes and look for a different error stage instead of the KEX message.
When the offer is diffie-hellman-group1-sha1
OpenSSH's canonical legacy example uses diffie-hellman-group1-sha1. It appears frequently in Stack Exchange threads, appliance docs, and very old SSH implementations.
Enable it the same way, with the name from the offer line:
ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 legacy@legacy-switch.lab.examplegroup1-sha1 is older and weaker than group14-sha1. Use it only when that is what the server advertises, or when group14-sha1 did not clear the KEX error.
Make the exception for one host only
Command-line -o flags are fine for a single test. For a host you must keep reaching, put the KEX exception in ~/.ssh/config so only that alias is affected.
Add a Host block:
Host legacy-switch
HostName 203.0.113.10
Port 22
User legacy
KexAlgorithms +diffie-hellman-group14-sha1Verify what the client will send before you connect:
ssh -G legacy-switch | grep '^kexalgorithms 'The line should include the legacy KEX name while your other hosts keep the stock list. Connect with the alias:
ssh legacy-switchUse a dedicated alias per legacy device. Do not put a legacy KexAlgorithms line in a broad Host * block unless you intend to weaken KEX for every SSH session from that account.
Why the error changes after you fix KEX
Do not start by enabling every legacy KEX, host-key, and cipher option you find online. Fix the error currently shown, reconnect, and only address the next negotiation stage if OpenSSH reports another mismatch.
Fixing KEX only clears stage 1. A very old server may still fail at host-key or cipher negotiation:
no matching key exchange method found
↓ fix KexAlgorithms
no matching host key type found
↓ fix HostKeyAlgorithms
no matching cipher found
↓ fix Ciphers (+ MACs if needed)
authentication (password or public key)I reproduced that progression against a container that offered legacy KEX, ssh-rsa host keys, and aes128-cbc only.
Step 1 — KEX failure (start here):
ssh -o BatchMode=yes -p 2233 legacy@203.0.113.10 'echo OK'Unable to negotiate with 203.0.113.10 port 2233: no matching key exchange method found. Their offer: diffie-hellman-group14-sha1Step 2 — enable KEX, host-key failure next:
ssh -o BatchMode=yes -p 2233 -oKexAlgorithms=+diffie-hellman-group14-sha1 legacy@203.0.113.10 'echo OK'Unable to negotiate with 203.0.113.10 port 2233: no matching host key type found. Their offer: ssh-rsaThis is a different stage. Use HostKeyAlgorithms, not another KEX tweak. See sshd ssh-rsa algorithm is disabled for background on why modern clients disabled ssh-rsa host keys by default.
Step 3 — enable host key, cipher failure next:
ssh -o BatchMode=yes -p 2233 \
-oKexAlgorithms=+diffie-hellman-group14-sha1 \
-oHostKeyAlgorithms=+ssh-rsa \
legacy@203.0.113.10 'echo OK'Unable to negotiate with 203.0.113.10 port 2233: no matching cipher found. Their offer: aes128-cbcStep 4 — enable cipher:
ssh -p 2233 \
-oKexAlgorithms=+diffie-hellman-group14-sha1 \
-oHostKeyAlgorithms=+ssh-rsa \
-oCiphers=+aes128-cbc \
legacy@203.0.113.10This completed SSH negotiation and reached authentication in my tests. If OpenSSH next reports a MAC negotiation error, add only the MAC named in that error — for example -oMACs=+hmac-sha1. Fold the options you actually needed into one Host block only when you must keep accessing that device.
When platform crypto policy blocks a legacy algorithm
Some Linux distributions apply a system-wide crypto policy in addition to OpenSSH settings. If ssh -Q kex lists an algorithm but an explicit -oKexAlgorithms=+… still cannot complete a later negotiation stage, inspect your platform's crypto policy.
In my RHEL 10.2 test, the KEX exception worked, but the connection later stopped at the legacy ssh-rsa host-key stage because the platform policy still rejected it. Treat that as a new host-key problem, not a failure of the KEX fix.
If platform policy blocks a legacy algorithm on purpose, prefer upgrading the remote SSH server, switch firmware, or appliance image instead of globally weakening the client policy.
Tested reproduction
I validated the KEX failure and fixes with an isolated legacy SSH server container and two clients:
┌──────────────────────┐
│ Legacy SSH server │
│ KEX: group14-sha1 │
│ port 2234 │
└──────────┬───────────┘
│
┌───────┴────────┐
│ │
┌────▼─────┐ ┌─────▼────┐
│ Ubuntu │ │ RHEL │
│ 26.04 │ │ 10.2 │
│ client │ │ client │
└──────────┘ └──────────┘A default ssh attempt against the kex-only server returned the expected error:
ssh -o BatchMode=yes -p 2234 legacy@203.0.113.10 'echo OK'Unable to negotiate with 203.0.113.10 port 2234: no matching key exchange method found. Their offer: diffie-hellman-group14-sha1Appending +diffie-hellman-group14-sha1 cleared KEX on both clients. The full KEX → host key → cipher progression above used a second container on port 2233. Newer OpenSSH builds may append extension tokens such as ext-info-s to the offer line; the KEX name you need is still the diffie-hellman-… token.
Safer long-term fix: upgrade the remote SSH server
Per-connection +diffie-hellman-group14-sha1 or +diffie-hellman-group1-sha1 is a compatibility bridge, not a target state. OpenSSH disables weak algorithms by default because they are no longer considered safe, while retaining them primarily for legacy access.
Longer term:
- Upgrade the remote SSH server, switch firmware, or appliance image to a release that offers
curve25519-sha256,ecdh-sha2-nistp256, ordiffie-hellman-group14-sha256 - Remove the legacy
KexAlgorithmsline from~/.ssh/configonce the server advertises modern KEX names - Restrict legacy exceptions to named
Hostaliases, never globalHost *defaults - Document which devices still require SHA-1-era algorithms for compliance or sunset planning
If you control the server and only need to support old clients temporarily, prefer enabling a stronger shared KEX on the server side rather than weakening every admin laptop.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
no matching key exchange method found |
No enabled KEX overlap between client and server | Read Their offer:; append one matching name with + |
Offer lists several diffie-hellman-… names |
Server advertises multiple legacy KEX options | Enable one less outdated name (try group14-sha1 before group1-sha1) |
ssh -Q kex lists the name but default ssh fails |
Built in, but not in the algorithms SSH will try by default | Confirm with ssh -G host | grep kexalgorithms; append with + |
KEX fixed, now no matching host key type found |
Different stage; server uses ssh-rsa or other legacy host key |
HostKeyAlgorithms=+ssh-rsa; check platform crypto-policy on RHEL-family hosts |
Host key fixed, now no matching cipher found |
Different stage; server uses CBC ciphers | Ciphers=+aes128-cbc; add MACs=+… only if OpenSSH reports a MAC error next |
| Policy blocks legacy algorithm after KEX fix | System crypto-policy refuses SHA-1-era options | Upgrade remote device; do not weaken client policy globally as a first step |
Permission denied after negotiation errors disappear |
Authentication stage; KEX/host key/cipher are done | Fix keys, password, or account — not KEX |
Summary
The message no matching key exchange method found means your SSH client and the remote server cannot agree on a KEX algorithm for the encrypted session. Read Their offer: first, then append one matching name with -oKexAlgorithms=+…. Do not copy a fix from another article, enable every legacy name at once, or generate a new SSH user key.
Use ssh -Q kex to see what the binary supports and ssh -G host to see what the next connection will actually try. When several algorithms appear in the offer, pick one less outdated compatible name rather than enabling the whole list.
After KEX succeeds, a new error about host keys or ciphers means you moved to the next negotiation stage and need different options. Some platforms add crypto-policy limits on top of OpenSSH. The durable fix is upgrading the remote SSH server or device so it advertises modern KEX and host-key algorithms.
References
- OpenSSH legacy options (
ssh.1) —KexAlgorithmsand the+prefix - OpenSSH release notes — default algorithm changes over time
- Red Hat crypto-policies documentation — system-wide limits on OpenSSH algorithms
Frequently Asked Questions
Does ssh -Q kex mean my client will use every listed algorithm?
No. It only reports algorithms compiled into the ssh binary. The algorithms SSH will actually try are what ssh -G hostname prints in the kexalgorithms line, plus any per-host KexAlgorithms entries in your config.
Should I replace the whole KexAlgorithms list or use +?
OpenSSH recommends appending with + for one legacy name so modern algorithms stay available. Replacing the entire list (-oKexAlgorithms=diffie-hellman-group14-sha1) works for a quick test but is easier to misapply in config files.
Their offer lists three algorithms. Do I enable all of them?
No. Enable one shared algorithm that your client can use, starting with the less outdated name in the list. Reconnect and address only the next error if one appears.
Do I need a new SSH key for diffie-hellman-group1-sha1?
No. KEX algorithms establish the encrypted session before user authentication. Your existing RSA or Ed25519 key is unrelated to this error.
Why did I get a host-key error after fixing KEX?
KEX is only the first negotiation step. Once it succeeds, the client moves on to host-key types. A no matching host key type found message needs HostKeyAlgorithms, not another KEX change.

