293

I've written this small utility script:

for h in $SERVER_LIST; do ssh $h "uptime"; done

When a new server is added to $SERVER_LIST, the script is stopped with:

The authenticity of host 'blah.blah.blah (10.10.10.10)' can't be established.
RSA key fingerprint is a4:d9:a4:d9:a4:d9a4:d9:a4:d9a4:d9a4:d9a4:d9a4:d9a4:d9.
Are you sure you want to continue connecting (yes/no)?

I've tried yes:

for h in $SERVER_LIST; do yes | ssh $h "uptime"; done

with no luck.

Is there a way to parametrize ssh to automatically accept any new key?

1
  • 6
    Lekensteyn's answer is excellent and correct, but I just wanted to note that since ssh is expecting "yes" and yes outputs "y", you might have had better luck with for h in $SERVER_LIST; do yes yes | ssh $h "uptime"; done (note the extra yes, which tells yes what to say instead of "y"). Apr 18, 2012 at 17:54

7 Answers 7

351

Use the StrictHostKeyChecking option, for example:

ssh -oStrictHostKeyChecking=no $h uptime

This option can also be added to ~/.ssh/config, e.g.:

Host somehost
    Hostname 10.0.0.1
    StrictHostKeyChecking no

Note that when the host keys have changed, you'll get a warning, even with this option:

$ ssh -oStrictHostKeyChecking=no somehost uptime
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    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
31:6f:2a:d5:76:c3:1e:74:f7:73:2f:96:16:12:e0:d8.
Please contact your system administrator.
Add correct host key in /home/peter/.ssh/known_hosts to get rid of this message.
Offending RSA key in /home/peter/.ssh/known_hosts:24
  remove with: ssh-keygen -f "/home/peter/.ssh/known_hosts" -R 10.0.0.1
Password authentication is disabled to avoid man-in-the-middle attacks.
Keyboard-interactive authentication is disabled to avoid man-in-the-middle attacks.
ash: uptime: not found

If your hosts are not often reinstalled, you could make this less secure (but more convenient for often-changing host keys) with the -oUserKnownHostsFile=/dev/null option. This discards all received host keys so it'll never generate the warning.


With Ubuntu 18.04, since [OpenSSH>=7.6] (https://www.openssh.com/txt/release-7.6), there's a new possibility:

StrictHostKeyChecking=accept-new

From man ssh_config :

If this flag is set to “accept-new” then ssh will automatically
add new host keys to the user known hosts files, but will not
permit connections to hosts with changed host keys.  If this flag
is set to “no” or “off”, ssh will automatically add new host keys
to the user known hosts files and allow connections to hosts with
changed hostkeys to proceed, subject to some restrictions.
4
  • 12
    This isn't the best solution as it bypasses built-in security tools. ssh-keyscan is preferable, if it's available on your system. Nov 11, 2015 at 19:06
  • 3
    @StefanLasiewski It allows man in the middle attacks if you are on untrusted networks. For accepting new keys to fixed hosts, the ssh-keyscan approach is more sane. For local virtual machines and other hosts in trusted networks with dynamic/reused IP addresses, the described approach is good enough.
    – Lekensteyn
    Nov 11, 2015 at 22:49
  • 14
    Just to clarify the difference between the two solutions: The ssh-keyscan solution is only prone to a man-in-the-middle attack the one time ssh-keyscan is being run. The -oStrictHostKeyChecking=no solution is prone to a man-in-the-middle attack every time ssh is being run. Aug 25, 2016 at 13:03
  • 1
    OpenSSH<7.6 is uncommon by now. I suggest to remove the (obsolete) part of this answer. Sep 24, 2022 at 10:05
149

You can use the following command to add the fingerprint for a server to your known_hosts

ssh-keyscan -H <ip-address> >> ~/.ssh/known_hosts
ssh-keyscan -H <hostname> >> ~/.ssh/known_hosts

NOTE: Replace < ip-address > and < hostname > with the IP and dns name of the server you want to add.

The only issue with this is that you will end up with some servers in your known_hosts twice. It's not really a big deal, just mentioning. To ensure there are no duplicates, you could remove all the servers first by running the following first:

ssh-keygen -R <ip-address>
ssh-keygen -R <hostname>

So you could run:

for h in $SERVER_LIST; do
    ip=$(dig +search +short $h)
    ssh-keygen -R $h
    ssh-keygen -R $ip
    ssh-keyscan -H $ip >> ~/.ssh/known_hosts
    ssh-keyscan -H $h >> ~/.ssh/known_hosts
done

One thing to keep in mind when removing just to re-add, you are essentially removing the security of verifying the fingerprint. So you would definitely not want to run this script before each execution of your utility script.

3
  • 1
    running it through sort | uniq and then looking for duplicate host using awk after would make the script capable of detecting changed hosts and warn users only about those, since same host with different keys could mean trouble May 21, 2015 at 19:52
  • 3
    You might want to add a note that -H hashes hostnames and addresses.
    – user283933
    Oct 7, 2016 at 19:27
  • 1
    When I run ssh-keyscan on Ubuntu 18.04, I get output for several key formats and an undesired comment for each. Since I'm only interested in adding ssh-rsa, I use: ssh-keyscan -t rsa -h HOSTNAME 2>/dev/null >> ~/.ssh/known_hosts Dec 1, 2020 at 22:14
30

I'm a bit late with this response, but the sensible way would be to do a ssh-keyscan on the new machine before you run the uptime gathering.

ssh-keyscan  <newhost> >> ~/.ssh/known_hosts

Disabling the sanity check for convenience sake sounds like a bad plan, even if you think you're totally in control of the environment.

2
  • running the above command and not actually checking the host keys against fingerprints you acquired out of band is vulnerable in the exact same way as StrictHostKeyChecking no
    – code_monk
    Apr 4, 2017 at 20:17
  • 3
    @code_monk : no, it isn't. I opens a one-off opportunity for failure (accepting a key from a wrong host to be added to known hosts). StrictHostKeyChecking no will allow repeat accepts for other machines.
    – tink
    Apr 4, 2017 at 20:20
5

Add this entry into ~/.ssh/config file

Host *
    StrictHostKeyChecking no

If it complains about access permission for ~/.ssh/config, then try

$ chmod 644 ~/.ssh/config
3

I tried the approaches suggested in this thread. Best fit to my needs is summarized below: ssh -o StrictHostKeyChecking=accept-new -o ConnectTimeout=10 -i <filepath to .pem RSA key> <user>@<ip>

2

In order to add a list of servers automatically we can do below:

Add servers IP in file servers-list

The IPs should be added in below format.

Output of cat servers-list

123.1.2.3
124.1.2.4
123.1.2.5

Change above IPs by replacing yours.

Below command will add all servers from the list.

ssh-keyscan -H "`cat servers-list`" >> ~/.ssh/known_hosts
1
  • 2
    This will work better for most people if you remove the -p61 since ssh is generally not listening on port 61. Dec 1, 2020 at 22:11
0

Though it's too late to answer this, wanted to share my contribution.

I just made a quick bash script to ease my life.

Basically, whenever you ssh into a machine, it removes the old host key and adds the new key. Add that as an alias to ssh, then you no longer need to worry about ssh keys not matching. The script will rotate them on every login.

#!/bin/bash
{
    ip=$(cut -d  "@" -f2 <<< $1) && ssh-keygen -R $ip 2> /dev/null && ssh -o StrictHostKeyChecking=accept-new $1 2> /dev/null
} || { 
    ssh $1 
}

# For Windows users (to add permanent alias to cmd):
# Create a file called Alias.bat (preferrably in C:\Bin) 
# Enter this inside Alias.bat: doskey ssh=bash rotate_ssh_key.sh $1
# Add the totate_ssh_keys.sh (This gist) in the same location as Alias.bat
# Goto Registry editor
# Goto HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor
# Add a String valid called Autorun and set the value to the absolute path of Alias.bat
# Done.
# Windows Alias taken from this post: https://superuser.com/a/238858


# For Linux/ Mac Users:
# add this to your .bashrc or .zshrc file:
# alias ssh="bash /path/to/rotate_ssh_keys.sh"
# Done

Example Usage
bash script.sh ubuntu@10.10.1.10

Code Explanation
The code takes the hostname@ip as argument and splits it into hostname and ip using the cut command with @ as delimiter.

Then it removes the ip address from the known_hosts file using the ssh-keygen command.

Then it runs the ssh command with one additional option -o StrictHostKeyChecking=accept-new. This allows it to automatically accept the new key.

I have also added a try-catch sequence to it, so that in case of errors, it falls back to the default behaviour of ssh command.

1
  • 1
    Why not post the script in your answer? If the repository gets removed, your answer may not be as useful. Sep 16, 2021 at 4:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.