243

Trying to ssh into a computer I control, I'm getting the familiar message:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone could be eavesdropping on you right now (man-in-the-middle attack)! It is also possible that a host key has just been changed. The fingerprint for the RSA key sent by the remote host is [...]. Please contact your system administrator. Add correct host key in /home/sward/.ssh/known_hosts to get rid of this message. Offending RSA key in /home/sward/.ssh/known_hosts:86 RSA host key for [...] has changed and you have requested strict checking. Host key verification failed. 

I did indeed change the key. And I read a few dozen postings saying that the way to resolve this problem is by deleting the old key from the known_hosts file.

But what I would like is to have ssh accept both the old key and the new key. The language in the error message ("Add correct host key") suggests that there should be some way to add the correct host key without removing the old one.

I have not been able to figure out how to add the new host key without removing the old one.

Is this possible, or is the error message just extremely misleading?

6
  • 14
    This is the host key that is generating the error. A host should have one and only one key. This has nothing to do with client or user keys. Do you have one IP address that floats between distinct hosts or something? Commented Oct 13, 2011 at 14:05
  • 5
    In my case I know I'm going to be switching between the two keys a lot in the near future while fiddling with some things. It seems this would also be useful in the one IP with multiple hosts situation you suggest. Mainly I just want to know if this is possible for my own education apart from any particular practical application. Commented Oct 13, 2011 at 14:30
  • @DavidSchwartz +1 about your comment - it would be happening due dynamic IPs in the same LAN Commented Sep 8, 2021 at 16:52
  • Or, which brought me here today, a rescue system of course having a different host key, but, and that's why I do NOT want to delete the "old" key, the old key is not old, it's still valid. Commented Apr 5, 2022 at 15:13
  • 1
    I just did rm ~/.ssh/known_hosts Commented Feb 5, 2024 at 20:55

11 Answers 11

222
  1. get the rsa key of your server, where server_ip is your server's IP address, such as 192.168.2.1:

    $ ssh-keyscan -t rsa server_ip 

    Sample response:

    # server_ip SSH-2.0-OpenSSH_4.3 server_ip ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwH5EXZG... 
  2. and on the client, copy the entire response line server_ip ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwH5EXZG..., and add this key to the bottom of your ~/.ssh/known_hosts file:

    server_ip ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAqx9m529...(the offending key, and/or the very bottom of the `known_hosts` file) server_ip ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwH5EXZG... (line you're adding, copied and pasted from above) 
9
  • 18
    This worked! However, I'm using "HashKnownHosts", so the entry looked a little out of place. Luckily ssh_config(5) pointed me to ssh-keygen(1) which explained that I can use "ssh-keygen -H" to hash the unhashed entries. Thank you! Commented Oct 13, 2011 at 15:49
  • 3
    This "works" but you are not verifying the key, so you are vulnerable to mitm attacks... Commented Sep 23, 2013 at 7:22
  • 3
    @JasperWallace, as long as first step is done over secure connection (for example using localhost) it should be pretty secure, I think Commented Oct 3, 2013 at 20:38
  • 3
    Is there any way to gather all key types from server? Sometimes you don't know if they are RSA, DSA, ECDSA, RSA1... etc. Commented Mar 4, 2016 at 15:40
  • 5
    @SopalajodeArrierez the same manpage also says you can separate types with commas, so do ssh-keyscan -t rsa1,dsa,rsa,ecdsa,ed25519 server_ip -- but the only reason to find rsa1 and dsa keys is to identify servers that need to be upgraded/reconfigured Commented Apr 12, 2016 at 20:31
162

Remove that the entry from known_hosts using:

ssh-keygen -R *ip_address_or_hostname* 

This will remove the problematic IP or hostname from known_hosts file and try to connect again.

From the man pages:

-R hostname
Removes all keys belonging to hostname from a known_hosts file. This option is useful to delete hashed hosts (see the -H option above).

6
  • 21
    "how to add the new host key without removing the old one." Commented Feb 9, 2013 at 16:29
  • 5
    Your question comes up second when I google for "git ssh update host key automatically". This answer is what I was looking for. Opening a new question with exactly what I want might get it closed as a duplicate. Commented Nov 15, 2015 at 12:15
  • Hostname works too Commented Jul 6, 2018 at 20:28
  • 1
    Perfect - switched a host on aws behind an elastic IP and this did the trick. No need to edit anything. Commented Jul 22, 2020 at 22:23
  • 1
    This one works for me on Debian 10 Commented Aug 26, 2021 at 1:37
32

A very simple way is:

cp ~/.ssh/known_hosts ~/.ssh/known_hosts.bak 

Then edit known_hosts to clear the original key and SSH to the host again. It'll add the new key automatically.

Next compare the two files. A program such as meld is a nice comparison tool. Then merge the files to make known_hosts contain both keys. (apt-get / yum install name is simply meld)

My 'reason' for keeping two keys is that the destination system is multiboot. Even though I dare say there's a way of synchronizing the keys across the installations, it seems more straightforward to allow multiple keys.

Edit 2015-06

Temporarily comment the known_hosts entry

Revisiting it now, I notice an even simpler way, as long as the entry is identifiable—normally from the hostname / IP address, quite aside from the error message referencing its specific location;

  1. Edit known_hosts to temporarily add # at the start of the 'old' entry.
  2. SSH to the host, agreeing to the prompt to add the new key 'automatically.'
  3. Then re-edit known_hosts to remove the #.

Force a temporary host alias

There's even the option HostKeyAlias, as in

ssh -o HostKeyAlias=mynewaliasforthemachine name@computer 

Your SSH client will add the new key under the alias. Then, you can either edit known_hosts to substitute the 'real' hostname/IP address for the alias, or connect to that incarnation of that host with the alias option evermore.

2
  • I did a variant of your suggestion which worked well - instead of cp, mv, then ssh, then cat ~/.ssh/known_hosts.bak ~/.ssh/known_hosts > tmp; mv tmp ~/.ssh/known_hosts Commented Jun 30, 2017 at 11:31
  • Great, commenting out old host entry allows the new one to be added. Commented Sep 5 at 17:50
8

If both your client and server have OpenSSH 6.8 or newer, you can use the UpdateHostKeys yes option in your ssh_config or ~/.ssh/config. For example:

Host * UpdateHostKeys yes 

This makes SSH store all host keys that the server has to known_hosts, and when a server changes or removes one host key, the key is also changed or removed in your known_hosts.

1
  • This is by far the most useful answer! Although it doesn't explicitly offer a way to resolve the original question if a host key was already changed, all the other answers are insecure since they don't verify the new host key. This option allows you to do secure rollover to new host keys. Commented Jul 5, 2017 at 20:03
6

I have the same issue with a raspberry pi which I boot with several different systems (dev system for compiling arm binaries, project, xbmc, etc.) and have run into the same problem. They use DHCP on a local network and my router always reused the same IP since the MAC address was the same. I've solved it by using different domain names in my hosts file:

10.10.10.110 pi-dev 10.10.10.110 pi-xbmc 10.10.10.110 pi-etc 

The known_hosts file saves fingerprints by host name so even though it is the same IP address, each unique host name gets a different entry.

I got sick of adding the names to hosts files every time I used a new system so I came up with an even lazier way by using leading zeros on ip addresses like:

$ ssh [email protected] $ ssh [email protected] $ ssh [email protected] 

Each variation of the (uncanonicalized) ip address gets it's own entry in known_hosts.

2
  • 1
    The OpenSSH folks got wise to me, this loophole no longer works in more recent versions. Commented Dec 8, 2015 at 3:32
  • 1
    You can use CheckHostIP no in ~/.ssh/config to be able to still use the loophole. You can even define your aliases there so you don't have to fiddle with /etc/hosts and define CheckHostIP no only for this 3 hostnames. Commented Dec 4, 2017 at 18:12
1

I don't see why you want to work with two keys, but you can certainly add more than one valid key to the ~/.ssh/known_hosts file, but you will have to do it manually.

Another solution might be to use the StrictHostKeyChecking=no option for this specific host:

ssh -o StrictHostKeyChecking=no user@host 

which you could put into an alias in your ~/.profile or something similar.

alias hc=ssh -o StrictHostKeyChecking=no user@host 
3
  • StrictHostKeyChecking does not seem to help in this case; apparently it only specifies the behavior when the host is not in the known_hosts file. Mentioned here: gossamer-threads.com/lists/openssh/dev/45349#45349 Commented Oct 13, 2011 at 15:41
  • It works here. You will get the warning, but the login continues. Commented Oct 13, 2011 at 15:53
  • That's odd. Are you using password authentication? Are you using OpenSSH? Commented Oct 13, 2011 at 16:07
1

If you only ssh onto a local network then...

A simple solution is to wipe the old key file and replace it with a blank one. This will allow you to reauthorise all of your connections with new keys. If you have ssh keys stored for sites outside your local network, then you need to ensure that your initial connection is safe as you did the first time you connected to that server.

eg

cp known_hosts known_hosts.old rm known_hosts nano known_hosts 

Then press space, backspace cntl+x and 'y' to save the new buffer (file). Its bad practise but okay providing you aren't regularly ssh'ing outside your local network (eg a uni or work server)

On a secure local network this is safe because you simply cant get a man in the middle attack.

Its always better to use code you understand!

2
  • 5
    Wiping the entire known_hosts file each time is going to negate most of the security otherwise provided by ssh. Commented Jun 15, 2014 at 22:23
  • Indeed, I would argue that on a secure internal network, it is safer to understand your code and circumvent the security than to mindlessly copy code. On an external network then the situation would be different. Commented Jun 30, 2014 at 20:50
1

So many answers, but so many that give up protection by turning off strict host checking totally, or destroying unrelated host info or just forcing the user to interactively accept keys, possibly at a later point, when it is unexpected.

Here's a simple technique to allow you to leave strict host checking on, but update the key in a controlled way, when you expect it to change:

  • Remove the old key and update in one command

    ssh-keygen -R server.example.com && \ ssh -o StrictHostKeyChecking=no server.example.com echo SSH host key updated. 
  • Repeat with IP address(es) or other host names if you use them.

The advantage of this approach is that it rekeys the server exactly once. Most versions of ssh-keygen seem to not return an error if the server you try to delete doesn't exist in the known hosts file, if this is a problem for you, use the two commands in sequence.

This approach also verifies connectivity and emits a nice message for logs in the ssh command (which logs in, updates the host key, and outputs SSH host key updated then immediately exits.

If your version of ssh-keygen returns a non-zero exit code, and you prefer to handle this without error, regardless or prior connection, simply use the two commands in sequence, ignoring any errors on the ssh-keygen command.

If you use this technique, you never need to vary your ssh command, or turn off host checking except during that one ssh command. You can be sure that future ssh sessions will work without conflict or needing to explicitly accept a new key, as long as the ssh command above ran without error.

0
0

you need to remove old key from client server

ssh-keygen -R 192.168.0.25 #1st remove on client server 

then re generate key

ssh -o HostKeyAlias=192.168.0.25 [email protected] #on client server 

check new line is there

nano ~/.ssh/known_hosts 
-3

I had the same problem.

All I did was sudo nano /home/user/.ssh/ host_allow and erased the key.

When I ssh back to the server it added a new key.

1
  • 2
    Some more information around why this happens would be helpful to the answer. Commented May 18, 2014 at 14:56
-4

Use sed command to do remove the offending line

OUTPUT: as show in above example Offending key in /home/user/.ssh/known_hosts:86 

Remove the line 86 as mentioned in known hosts.

CODE: sed -i '86d' /home/user/.ssh/known_hosts 

Next time when accessing using ssh, system will automatically add new key.

newer versions of ssh

use:

ssh-keygen -R <hostname|ip address> 

It will remove the hostname entry and take backup of old .known_host as known_hosts.old

1
  • 4
    "But what I would like is to have ssh accept both the old key and the new key." Your answer does not do this. Commented Jun 14, 2012 at 15:42

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.