If you SSH to servers that change a lot (they’re hosted at Amazon Web Services, for instance), you may see this warning when you try to connect1:

$ ssh user@server.com
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@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 the RSA host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
7c:a5:20:20:00:d7:b0:74:7e:b2:4a:00:57:e6:55:02.
Please contact your system administrator.
Add correct host key in /Users/user/.ssh/known_hosts to get rid of this message.
Offending key in /Users/user/.ssh/known_hosts:160
RSA host key for 1.2.3.4 has changed and you have requested strict checking.
Host key verification failed.

The host key has changed because the server has changed, & I need to fix this so I can connect. The important line is this one:

Offending key in /Users/user/.ssh/known_hosts:160

That tells me that line 1602 of the known_hosts file is the problem. If you open that file up (& it’s always located at ~/.ssh/known_hosts), you’ll see line after line that looks like this:

192.168.1.67 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEArlii7a+8Uy7ccsr4RtOVSIBsbDpkO1gShGmS72hs21ofKsoez/ZQ8vtZTLgJdKZW+Ro6pEocKwHdSX+ypfiHEAT6b7Yh3IEuvEPEo1Xl8Vwh/JobTqxmLiDN3C/HYZVdttth8HPj/6PT20gcF9NcvbvNHJ6V6q6SeuqIoSGkb4DzPVkc3veakYHFoO1lL3fkFhMLk/aK71WJ/Vj002c6itGe3CCKIVGXoMqBEVhs13sQEz7Axxu6hiDSZFwvAbN6RyjWiqb9pHvir6sIwChEf3Dr+7K2wGSR9lhKvjwu/a3QXScb2NvYOWlkM+yirpXoPWihwviXJbpzB13iwIaiKQ==
70.237.208.170 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0TMdCqPN/WTTrJ3mn/a3u8TsFzU2eFKnSLPnn3Ot2+uAlHSpl4yQK3gtcXKQsOy2srSr5hQ55pjlZr7vVAhXoIB1yZH1nrPfY7sq4VmBHUw2Wpx8KpZVWeyunXQP1s1ZANAY7FdsgSO0hMcaM4yIRDlXdNkstkqkBu01En4R3xaAtRgpN5Ftkywb7cJP6CyCI/IcOlc1lw+Ssc+jafTXl2dIPor1ebwGaUluxL+KWvaukXIfofj7qlbudmCzxfG9wnX5987ovOzdjVWI89mOxhW+zKAG0McfiPnQDN8p0E2DUeXo4YAxZPpvM2vgM+MO+33eU6aL5GxJJSxrh4PZJw==

Each of those has the IP address of the server along with the key for that server. In this case, line 160 has the problematic host key for the server I was trying to connect to, so I’m supposed to delete that line, save the known_hosts file, and try to SSH to it again. When I do that, I’ll see this:

$ ssh user@server.com
The authenticity of host 'server.com (1.2.3.4)' can't be e</code>stablished.
RSA key fingerprint is 17:8c:be:70:a4:33:b8:c7:6b:1c:22:e4:eb:84:cd:ae.
Are you sure you want to continue connecting (yes/no)?

I enter yes & this then appears:

Warning: Permanently added 'server.com,1.2.3.4' (RSA) to the list of known hosts.

And now I can SSH to that server again without any warnings, since the correct host key is now in known_hosts.

However, I got lazy the other day & wrote a little function to make the process of deleting the line from known_hosts a bit easier.

knownhosts () {
  cp ~/.ssh/known_hosts ~/.ssh/known_hosts_$(date +%Y%m%d-%H%M%S) ; 
  sed -e "$1d" ~/.ssh/known_hosts > ~/.ssh/known_hosts_new ; 
  mv ~/.ssh/known_hosts_new ~/.ssh/known_hosts ; 
  chmod 644 ~/.ssh/known_hosts
}

To use it, do this:

  1. Copy it into your ~/.bash_aliases file (or your ~/.profile if you don’t use .bash_aliases)
  2. Source the .bash_aliases file by entering this & pressing Enter: source ~/.bash_aliases
  3. When you want to delete a line from known_hosts, enter knownhosts followed by the line number. So, for instance, if line 6 is a problem, you’d delete it like this:
knownhosts 6

You could then immediately try again to connect to the SSH server. You’ll be prompted to accept the new key, & then you’re golden.

The name of the function is knownhosts, without the underscore. If you want to call it something else, be my guest. Here’s what each part does:

  • cp ~/.ssh/known_hosts ~/.ssh/known_hosts_$(date +%Y%m%d-%H%M%S)
    Make a backup of the existing known_hosts file just in case. The backup will have today’s date & the current time appended to it, giving it a name like this: known_hosts_20120406-175028.

  • sed -e "$1d" ~/.ssh/known_hosts > ~/.ssh/known_hosts_new
    Use sed to delete the line you passed to the function via the command line (that comes in from the $1). Normally you delete lines with sed by entering sed -e "8d" file, which would delete line 8 from the file. $1 is a variable that takes the number right after knownhosts and inserts that instead.

    Normally sed writes to STDOUT, but instead we want to redirect it to another file, which in this case is ~/.ssh/known_hosts_new.

  • mv ~/.ssh/known_hosts_new ~/.ssh/known_hosts
    Overwrite the old known_hosts with the new known_hosts.

  • chmod 644 ~/.ssh/known_hosts
    Set the correct permissions on the known_hosts file.

That’s it. I hope it’s helpful. This little function has helped me be even more lazy, & that’s always a good thing.

  1. I’ve changed the names & numbers to anonymize things, so no, I’m not SSHing to 1.2.3.4 with the user name of user

  2. Yes, I connect to a lot of SSH servers!