How can I force ssh to accept a new host fingerprint from the command line?
Asked Answered
D

10

142

I'm getting the standard

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

error message. However, the system (Appworx) that executes the command (sftp I think, not that it matters) is automated and I can't easily accept the new key, even after checking with the third party vendor that it is a valid change. I can add a new shell script that I can execute from the same system (and user), but there doesn't seem to be a command or command-line argument that will tell ssh to accept the key. I can't find anything in the man page or on Google. Surely this is possible?

Democritus answered 27/1, 2014 at 14:47 Comment(0)
M
62

Here's how to tell your client to trust the key. A better approach is to give it the key in advance, which I've described in the second paragraph. This is for an OpenSSH client on Unix, so I hope it's relevant to your situation.

You can set the StrictHostKeyChecking parameter. It has options yes, no, and ask. The default is ask. To set it system wide, edit /etc/ssh/ssh_config; to set it just for you, edit ~/.ssh/config; and to set it for a single command, give the option on the command line, e.g.

ssh -o "StrictHostKeyChecking no" hostname

An alternative approach if you have access to the host keys for the remote system is to add them to your known_hosts file in advance, so that SSH knows about them and won't ask the question. If this is possible, it's better from a security point of view. After all, the warning might be right and you really might be subject to a man-in-the-middle attack.

For instance, here's a script that will retrieve the key and add it to your known_hosts file:

ssh -o 'StrictHostKeyChecking no' hostname cat /etc/ssh/ssh_host_dsa_key.pub >>~/.ssh/known_hosts
Mandle answered 27/1, 2014 at 15:12 Comment(8)
I'm not trying to suppress the warning. I've already gotten it, I will get more in the future. I want a script that, after I've received the warning, I can run the script and have it answer "yes" without it being interactive. I have no way of typing "yes". I was hoping there was a "connect to this host, answer yes, and disconnect" argument to ssh, or some way of accomplishing the same.Democritus
Your command works, though I'm not sure what it's doing. Thank you. I've also added Batchmode to it, so that it exits when it gets to the password prompt. Much appreciated.Democritus
Auto-answering yes is a security vulnerability. It leaves you open to be phished. Unless you are in a private dev environment. Then this can be very helpful. You should verify the fingerprint + password/username or use an ssh public/private key.Avisavitaminosis
I'm trying to bypass the check one-time only, as I'm trying to connect to my server is rescue mode (therefore I'm actually connecting to a different OS, with a one-time password for the SSH login). I want to retain the current keys.Graphite
terrible idea. check other answers and comments to lean why and better alternatives. tldr: use StrictHostKeyChecking=accept-new instead.Aranyaka
StrictHostKeyChecking=accept-new nicely solved my problem of deploying a new host key on 45 servers in one command when, for obscure reasons, ssh-keyscan didn't help. Of course in my case, I will only run it once, and then use standard private key logons.Curve
@Aranyaka It's not a terrible idea, you just have terrible reading comprehension. This was years ago for me, but I did not have a way to interactively use the system. I could not go in and manually update the key to the new one. And in my situation, I had verified with the external host (over the phone and email) that this was indeed just an inevitable system issue on their end. I was also able to write a script that could execute as a substitute to me sitting there and using the keyboard to confirm I wanted this. It wasn't automated, I had to invoke the script. No one offered an alternative.Democritus
Worked with dockerEupatorium
S
165

The answers here are terrible advice. You should never turn off StrictHostKeyChecking in any real-world system (e.g. it's probably okay if you're just playing on your own local home network – but for anything else don't do it).

Instead use:

ssh-keygen -R hostname

or if not using the default port 22:

ssh-keygen -R '[hostname]:port'

That will force the known_hosts file to be updated to remove the old key for just the one server that has updated its key.

Then when you use:

ssh user@hostname

It will ask you to confirm the fingerprint – as it would for any other "new" (i.e. previously unseen) server.

Sublett answered 7/12, 2018 at 15:52 Comment(10)
Please all note: This is the only correct answer! Use StrictHostKeyChecking no for example on local development Docker containers that change their host key on every update of the image, but don't use it for live servers! Really, you don't want that!Hegelianism
This describes adding the key interactively. As such, it isn't the only answer, because you can provide the actual key instead. That's better because you use a known-good copy. It also allows automation.Mandle
You can also use StrictHostKeyChecking accept-new to accept new keys but still refuse to connect when the saved key conflicts.Annoying
I agree most of the time it's a bad idea, but in my case I am using SSH to run a remote script from CI. The deploy key is restricted so the only thing it can do is run that script, and the script doesn't take any arguments. Even if there were a man-in-the-middle attack, there is no information being transmitted that could be corrupted or used to advantage. In this case, I think disabling host key checking is pretty reasonable. Perhaps there is some security implication that I have missed?Microgamete
@RadonRosborough the MITM will be able to read the instructions and data from the script. And they will be able to test how well the key is restricted. Better to update the known_hosts: ssh-keyscan $target_host >> ~/.ssh/known_hosts. Too easy to fix the issue, no reason to not do it.Cyprinid
running both those lines isn't, in fact, exactly the same as the accepted one liner though? why is it so terrible advice then?Aranyaka
@Aranyaka - disabling StrictHostKeyChecking disables the validation that the system really is the one that you're expecting to connect to. It's relatively easy (by messing with DNS for example) to direct someone to an imposter server – which could be used to steal credentials for example. It's essentially the same idea as HTTPS / TLS for a browser – which not only secures the connection, but also validates that the wenserver really is your_bank.com, etc.Sublett
i read it all over, including your comments reply, and still couldn't get it... but when writing this reply, i got it! even if StrictHostKeyChecking=no only happens during the one run, it will not only replace the current host (which is what those 2 command here do) but also it won't do the actual check that's done by the 2nd command here. if that's indeed the case, i couldn't agree more with the hate over the other answers. 😘Aranyaka
still, by all means, do check the new StrictHostKeyChecking=accept-new on the one newer answer there.Aranyaka
Ok but what about specifically for localhost? Is there any security concern with using StrictHostKeyChecking=no when the host is localhost?Pouf
B
112

While common wisdom is not to disable host key checking, there is a built-in option in SSH itself to do this. It is relatively unknown, since it's new (added in Openssh 6.5).

This is done with -o StrictHostKeyChecking=accept-new.

WARNING: use this only if you absolutely trust the IP\hostname you are going to SSH to:

ssh -o StrictHostKeyChecking=accept-new mynewserver.example.com

Note, StrictHostKeyChecking=no will add the public key to ~/.ssh/known_hosts even if the key was changed. accept-new is only for new hosts. From the man page:

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. If this flag is set to ask (the default), new host keys will be added to the user known host files only after the user has confirmed that is what they really want to do, and ssh will refuse to connect to hosts whose host key has changed. The host keys of known hosts will be verified automatically in all cases.

Why -o StrictHostKeyChecking=no is evil?

When you do not check the host key you might land with an SSH session on a different computer (yes, this is possible with IP Hijacking). A hostile server, which you don't own can be then used to steal a password and all sort of data. Accepting a new unknown key is also pretty dangerous. One should only do it if there is an absolute trust in the network or that the server was not compromised. Personally, I use this flag only when I boot machines in a cloud environment with cloud-init immediately after the machine started.

Braeunig answered 22/5, 2020 at 2:1 Comment(5)
accept-new only works for new hosts, not in cases where the host-key changed - which is what this question is about.Smirk
In docker I got this error: command-line line 0: unsupported option "accept".Eupatorium
Which docker image is this? how did you call the command?Braeunig
"accept-new" not in openssh 7.4Re
Which Linux distro are you using that delivers that version? OpenSSH 7.4 was released on 2016-12-19.Braeunig
M
62

Here's how to tell your client to trust the key. A better approach is to give it the key in advance, which I've described in the second paragraph. This is for an OpenSSH client on Unix, so I hope it's relevant to your situation.

You can set the StrictHostKeyChecking parameter. It has options yes, no, and ask. The default is ask. To set it system wide, edit /etc/ssh/ssh_config; to set it just for you, edit ~/.ssh/config; and to set it for a single command, give the option on the command line, e.g.

ssh -o "StrictHostKeyChecking no" hostname

An alternative approach if you have access to the host keys for the remote system is to add them to your known_hosts file in advance, so that SSH knows about them and won't ask the question. If this is possible, it's better from a security point of view. After all, the warning might be right and you really might be subject to a man-in-the-middle attack.

For instance, here's a script that will retrieve the key and add it to your known_hosts file:

ssh -o 'StrictHostKeyChecking no' hostname cat /etc/ssh/ssh_host_dsa_key.pub >>~/.ssh/known_hosts
Mandle answered 27/1, 2014 at 15:12 Comment(8)
I'm not trying to suppress the warning. I've already gotten it, I will get more in the future. I want a script that, after I've received the warning, I can run the script and have it answer "yes" without it being interactive. I have no way of typing "yes". I was hoping there was a "connect to this host, answer yes, and disconnect" argument to ssh, or some way of accomplishing the same.Democritus
Your command works, though I'm not sure what it's doing. Thank you. I've also added Batchmode to it, so that it exits when it gets to the password prompt. Much appreciated.Democritus
Auto-answering yes is a security vulnerability. It leaves you open to be phished. Unless you are in a private dev environment. Then this can be very helpful. You should verify the fingerprint + password/username or use an ssh public/private key.Avisavitaminosis
I'm trying to bypass the check one-time only, as I'm trying to connect to my server is rescue mode (therefore I'm actually connecting to a different OS, with a one-time password for the SSH login). I want to retain the current keys.Graphite
terrible idea. check other answers and comments to lean why and better alternatives. tldr: use StrictHostKeyChecking=accept-new instead.Aranyaka
StrictHostKeyChecking=accept-new nicely solved my problem of deploying a new host key on 45 servers in one command when, for obscure reasons, ssh-keyscan didn't help. Of course in my case, I will only run it once, and then use standard private key logons.Curve
@Aranyaka It's not a terrible idea, you just have terrible reading comprehension. This was years ago for me, but I did not have a way to interactively use the system. I could not go in and manually update the key to the new one. And in my situation, I had verified with the external host (over the phone and email) that this was indeed just an inevitable system issue on their end. I was also able to write a script that could execute as a substitute to me sitting there and using the keyboard to confirm I wanted this. It wasn't automated, I had to invoke the script. No one offered an alternative.Democritus
Worked with dockerEupatorium
A
58

Since you are trying to automate this by running a bash script on the host that is doing the ssh-ing, and assuming that:

  • You don't want to ignore host keys because that's an additional security risk.
  • Host keys on the host you're ssh-ing to rarely change, and if they do there's a good, well-known reason such as "the target host got rebuilt"
  • You want to run this script once to add the new key to known_hosts, then leave known_hosts alone.

Try this in your bash script:

# Remove old key
ssh-keygen -R $target_host

# Add the new key
ssh-keyscan $target_host >> ~/.ssh/known_hosts
Akihito answered 6/8, 2019 at 3:49 Comment(0)
T
7

Just adding the most 'modern' approach.
Like all other answers - this means you are BLINDLY accepting a key from a host. Use CAUTION!

HOST=hostname; ssh-keygen -R $HOST && ssh-keyscan -Ht ed25519 $HOST >> "$HOME/.ssh/known_hosts"

First remove any entry using -R, and then generate a hashed (-H) known_hosts entry which we append to the end of the file.

As with this answer prefer ed25519.

Thingumajig answered 12/11, 2022 at 5:22 Comment(0)
B
5

You just have to update the current fingerprint that's being sent from server. Just Type in the following and you'll be good to go :)

ssh-keygen -f "/home/your_user_name/.ssh/known_hosts" -R "server_ip"
Brunhilda answered 18/11, 2019 at 6:55 Comment(1)
That is the wayCinch
R
1

Get a list of SSH host IPs (or DNS name) output to a file > ssh_hosts

Run a one-liner to populate the ~/.ssh/known_hosts on the control node (often do this to prepare target nodes for Ansible run)

NOTE: Assume we prefer ed25519 type of host key

# add the target hosts key fingerprints
while read -r line; do ssh-keyscan -t ed25519 $line >> ~/.ssh/known_hosts; done<ssh_hosts

# add the SSH Key('s) public bit to target hosts `authorized_keys` file
while read -r line; do ssh-copy-id -i /path/to/key -f user@$line; done<ssh_hosts
Rubbish answered 20/4, 2021 at 2:11 Comment(0)
J
0
ssh -o UserKnownHostsFile=/dev/null user@host
Josefjosefa answered 3/2, 2023 at 11:14 Comment(3)
A code-only answer is not high quality. While this code may be useful, you can improve it by saying why it works, how it works, when it should be used, and what its limitations are. Please edit your answer to include explanation and link to relevant documentation.Pentobarbital
If only i can reply this with a simple 'k'..Rudolph
ssh -o 'StrictHostKeyChecking no' ... from the accepted answer would be better. Why open the null file-descriptor, if no file is required.Thingumajig
H
0

It's not StrictHostKeyChecking that is the problem, it's a poorly maintained knows_hosts file which is. Sure you can ignore it when you don't wish to enjoy the benefit it was intended for (maximum protection against Man-In-The-Middle attacks). But the S in SSH was for security, not? And security comes at the expense of at least some dicipline.

One real solution I'm missing here is avoiding it by automating it:

put SSHFP records in your DNS and this in your clients .ssh/config

VerifyHostKeyDNS        yes

This article of APNIC provides a nice howto:

https://blog.apnic.net/2022/12/02/improving-sshs-security-with-sshfp-dns-records/

Further it seems also working when connecting to IP's i.c.w. putting the SSHFP DNS records in your .arpa zones.

Hemihedral answered 17/1 at 15:59 Comment(0)
C
-5

Add following file

~/.ssh/config

and this in the file as content

StrictHostKeyChecking no

This setting will make sure that ssh will never ask for fingerprint check again. This should be added very carefully as this would be really dangerous and allow to access all fingerprints.

Coontie answered 14/7, 2017 at 0:45 Comment(10)
private internet, mb. I agree. Don't do this in a real world environment.Avisavitaminosis
Obviously, It is only for private network host within your internet VPC/network. A public facing host should not have this.Coontie
This is very risky advice since it doesn't have a qualifier that this is a huge security hole and the instructions would add it globally rather than within, say, a Host block.Annoying
@ChrisAdams I hope you saw my previous comment about when it should be added.Coontie
@vishalsahasrabuddhe That's an important qualifier which is not in the original comment and it's still reckless because that will affect every SSH connection so you're gambling that nobody will ever change the usage patterns or copy that config somewhere else. It's safer to recommend either StrictHostKeyChecking accept-new or using Host to only weaken security for the intended servers.Annoying
@ChrisAdams added the warning with the comment.Coontie
@ChrisAdams not sure. How should I convey the message, I added solution and provided a warning too.Coontie
perhaps my comments on other answers can help, but this is indeed a huge "don't even think of doing it".Aranyaka
You pretty much need something like this if you're targeting an embedded Linux system, with a read-only user directory, and where the embedded device changes fingerprint on every reboot. I found the ssh-keygen -R solution does the trick but generates some unwanted output noise.Shine
It is heartbreakng how many people advocate doing this without a big warning.Kizzykjersti

© 2022 - 2024 — McMap. All rights reserved.