An easier, quicker way to edit the known_hosts file when an SSH server changes its host key
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:
- Copy it into your
~/.bash_aliases
file (or your~/.profile
if you don’t use.bash_aliases
) - Source the
.bash_aliases
file by entering this & pressing Enter:source ~/.bash_aliases
- When you want to delete a line from
known_hosts
, enterknownhosts
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 existingknown_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
Usesed
to delete the line you passed to the function via the command line (that comes in from the$1
). Normally you delete lines withsed
by enteringsed -e "8d" file
, which would delete line 8 from the file.$1
is a variable that takes the number right afterknownhosts
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 oldknown_hosts
with the newknown_hosts
. -
chmod 644 ~/.ssh/known_hosts
Set the correct permissions on theknown_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.