46

I regularly ssh into a computer which is a dual-boot OS X / Linux computer. The two OS instance do not share the same host key, so they can be seen as two host sharing the same IP and DNS. Let's say the IP is 192.168.0.9, and the names are hostname and hostname.domainname

As far as I understood, the solution to be able to connect to the two host is to add them both to the ~/.ssh/know_hosts file. However, it is easier said than done, because the file is hashed, and has probably several entries per host (192.168.0.9, hostname, hostname.domainname). As a consequence, I have the following warning

Warning: the ECDSA host key for 'hostname' differs from the key for the IP address '192.168.0.9'

Is there an easy way to edit the known_hosts file, while keeping the hashes. For example, how can I find the lines corresponding to a given hostame? How can I generate the hashes for some known hosts?

The ideal solution would allow me to connect to seamlessly to this computer with ssh, no matter whether I call it 192.168.0.9, hostname or hostname.domainname, nor if it uses its Linux hostkey or its OSX hostkey. However, I still want to receive a warning if there is a real man-in-the middle attack, i.e. if another key than these two is used.

6
  • What is it that you want to do? Edit it for what?
    – Rhyuk
    Jul 5, 2012 at 13:56
  • @Rhyuk: Edit it to be able to recognize as valid both the OSX and the linux host key for the IP address, the hostname and hostname.domainname. Jul 5, 2012 at 14:52
  • @Rhyuk: I've edited th question. Is it more clear now ? Jul 5, 2012 at 15:06
  • 2
    Have you simply considered making both installations have the same key?
    – Zoredache
    Jul 5, 2012 at 16:17
  • 5
    There are a few cases when it is reasonable to use one IP address to access multiple entities (each with individual SSH host keys) and still maintain strict control that ONLY those host keys are the ones seen by the SSH client. E.g some high availability setups where a cluster of units are accessed using one shared IP address but where (for some reason) the SSH host key seen by clients changes depending on which cluster unit it is that currently is active. Another case is when multiple SSH hosts are behind a NATed firewall and accessed from the outside, they all will seem to have the same IP.
    – IllvilJa
    Apr 2, 2015 at 14:57

8 Answers 8

17

The most straightforward solution here is just to use the same host keys for Linux and OS X. That is, pick one set of /etc/ssh/ssh_host_*_key* files and copy them over to the other OS. Then the same host key will presented to an SSH client regardless of which OS you've booted into, and the SSH client will be none the wiser.

6
  • I'd prefer a client version, but I'll try this one if I don't find one. By the way, the OSX (non-standard) localization of the files is /private/etc/ssh_host*, not /etc/ssh/ssh_host*. Jul 5, 2012 at 17:03
  • Copying the files over from one machine to another (two linux machines) did not work for me. Although file contents were identical the hash was not so I was still getting the problem (maybe the modification time?). The solution below is much better.
    – stav
    Dec 5, 2017 at 11:50
  • sshd loads the host keys once at startup, so you most likely need to restart sshd. I'll add that to the answer. As for other solutions being better, it depends on your situation. I would argue that the major pros of this method is that it requires only one-time setup and is more likely to work with multiple SSH client implementations.
    – jjlin
    Dec 5, 2017 at 19:05
  • Curiously, it seems my relatively recent OpenSSH 7.4p1 sshd loads host keys on each new connection. Maybe it has been this way a long time and I just assumed host keys were treated like other sshd configuration. So anyway, that may or may not be your issue.
    – jjlin
    Dec 5, 2017 at 19:43
  • 1
    @FrédéricGrosshans: OS X (and now macOS) always has a symlink from /etc to /private/etc so you don't need to worry about that difference.
    – iconoclast
    Apr 6, 2022 at 20:29
29

As @Izzy suggested in an above comment, ssh tells you the offending line, and by removing that line, (saving it elsewhere), accepting the new key, and then copying the removed line back, you wind up with two keys for the same host, and ssh will accept either.

(You can also use ssh-keygen -H -F <hostname> to find lines in your known_hosts file that match that hostname. Running this after copying the removed line back should list two entries.)

If anyone knows how to get PuTTY to do the same thing, I'd be very interested to hear about it.

2
  • 7
    Actually, if you have a linux client, you don't even need to remove the offending line, you only have to comment it out with a hash ('#') character at front. Then, once you have accepted the new key, you can just edit the known_hosts file and uncomment the line with the old key. But yes, this would be useful in Putty as well.
    – IllvilJa
    Apr 2, 2015 at 15:13
  • 1
    If there are two hosts with the same name, but different IP address and different host key, this workaround also works: Comment out (or temporarily delete) then both lines for that host (the one based on IP address and the one based on host name), connect to the not-yet-known host, and then re-add the lines, that were commented out or deleted.
    – Kai Petzke
    Oct 13, 2015 at 19:34
20

I found this that may help you with what you want to achieve.

Source: https://stackoverflow.com/questions/733753/how-to-handle-ssh-host-key-verification-with-2-different-hosts-on-the-same-but

Create a config file in your .ssh directory as follows:

Host server1
  Hostname x1.example.com
  HostKeyAlias server1
  CheckHostIP no
  Port 22001
  User karl

Host server2
  Hostname x2.example.com
  HostKeyAlias server2
  CheckHostIP no
  Port 22002
  User karl

Explanation Below (from man ssh_config)

CheckHostIP

If this flag is set to "yes", ssh(1) will additionally check the host IP address in the known_hosts file. This allows ssh to detect if a host key changed due to DNS spoofing. If the option is set to "no", the check will not be executed. The default is "yes".

HostKeyAlias

Specifies an alias that should be used instead of the real host name when looking up or saving the host key in the host key database files. This option is useful for tunneling SSH connections or for multiple servers running on a single host.

The Username and Port line avoids you having to give those options on the command line, too, so you can just use:

% ssh server1
% ssh server2
4
  • I saw this article, but it does not corresponds to my case : the two servers are distinguished by port number in the article, not in my case. Furthermore, I'd like to keep the extra layers of security brought by the salted hashes in known_hosts and CheckHostIP. Jul 5, 2012 at 15:53
  • 2
    @FrédéricGrosshans, I check checked. You don't have to have seperate ports, and the HashKnownHosts option works fine with HostKeyAlias.
    – Zoredache
    Jul 5, 2012 at 19:47
  • The down side to this, unless I'm wrong is, this is configured on a per client basis vs the accepted answer is configured only on the accepting ssh servers. Nov 23, 2016 at 20:37
  • Just what I was searching for, was tired of removing keys Oct 18, 2022 at 13:56
3

The easiest way to solve your issue is to give each host an own/distinct IP address. With 253 addresses available in your (private) net and IPv4, that should be no big deal. Give them fixed IPs (as a DHCP server would identify the machine based on the network cards MAC address, and both would get the same address). I do not see any other solution if you want to keep the security measures (which I wouldn't drop for that little "comfort", either).

4
  • Actually, the IP address is not 192.168.0.xx and is not private. It is a 'real' IPv4 address, given by my university which I'm not free to change. Jul 5, 2012 at 16:40
  • 1
    If you check with Wikipedia, you will see 192.168.0.0 - 192.168.255.255 (your question specified 192.168.0.9, which falls into this range) belongs to the "Private IPv4 address spaces". So by "private" I didn't refer to you "owning" it, but to the specs of the IETF. In your question you did not indicate you cannot change the IP, sorry -- but with the input given, my answer was fitting.
    – Izzy
    Jul 6, 2012 at 9:31
  • 1
    Sorry for the badly phrased question. I did not downvote. Jul 6, 2012 at 12:18
  • No prob, and tnx for letting me know -- makes the downvote less discouraging. But another idea: I'm not sure where the known_hosts file takes the hostname from, reverse DNS or offered by client. You could try renaming one of your "hosts" so it presents a different hostname. Or to have both host keys added: ssh tells you the "offending line" in your known_hosts file (when #1 is contained ynd you connect with #2). So you then could copy that line to another file, remove it from known_hosts, let #2 connect and add its line, and add the removed line back. Not sure if it works, but you can try.
    – Izzy
    Jul 6, 2012 at 12:49
3

I don't run into that problem when connecting to various VPS boxes sharing the same IP because each has a different SSH port (20022,30022, etc) so they are registered as known hosts with different keys.

Could that be a workaround for you?

3
  • Hi @Pyheme, welcome to Super User! Notice that this question is nearly 4 years old. There's nothing wrong with answering it, but keep in mind it's possible you don't get a response.
    – Hewbot
    Apr 9, 2016 at 17:16
  • I don't have any OS X machine any more, but your answer might be useful for someone else. That's the whole point of stack exchange Apr 9, 2016 at 18:45
  • @Hewbot... indeed, I see it now. Don't know why, it appeared in the list of recent questions...
    – Pyheme
    Apr 10, 2016 at 15:32
3

Another article, which describes several ways for handling your problem:

The second method uses two openSSH parameters: StrictHostKeyChecking, and UserKnownHostsFile. This method tricks SSH by configuring it to use an empty known_hosts file, and NOT to ask you to confirm the remote host identity key.

$ ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no [email protected]
2
  • 1
    This paper is about disallowing key-checking. I want to keep the key checking, and I don't want to disallow it each time hostname is rebooted into Linut or OSX Jul 5, 2012 at 15:57
  • 1
    Welcome to Super User! Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference. I've included a short part, but it might not be what you intended... Jul 10, 2012 at 1:09
1

Since you want to keep the strict host key checking, I would have them use different known_hosts files. To do this, set up your ~/.ssh/config file (or the /etc/ssh/ssh_config file if you need this to work on multiple local user accounts) like this:

Host myserver.osx
  UserKnownHostsFile ~/.ssh/known_hosts.dual.osx
  # default is ~/.ssh/known_hosts
  Hostname $REALHOSTNAME

Host myserver.linux
  UserKnownHostsFile ~/.ssh/known_hosts.dual.linux
  Hostname $REALHOSTNAME

, replacing $REALHOSTNAME with the actual hostname or IP address, of course. (It doesn't matter which you choose, just as long as you choose something after "Hostname" that would resolve to the IP address, but I'd use the host name in preference to an IP address, just on general principles.)

Then ssh myserver.linux and ssh myserver.osx can thus have different host keys, but you still get the checking. If it's Linux that's up and you type OS X (or vice versa), you'll get the warning (which I believe is the desired affect).

If I had this problem, I'd make sure there was something completely wrong in the main known_hosts file that doesn't match either either one, so that if you type $REALHOSTNAME instead of myserver.osx you get the warning. :-) I'd do that by putting something like

<ip-address-of-github.com> $REALHOSTNAME

in my /etc/hosts, then doing an ssh $REALHOSTNAME and accepting the new key, then taking that entry out.

0

YMMV (different distros?) but I've had success by doing a quick SSH to the direct IP (to auto-populate that key into known_hosts) and then modify that line to reflect "fully.qualified.domain.name,hostname,IP_address" instead of just the IP and so far that seems to work for my clustered servers which share a DNS listing but have differing IP addresses. I'm still testing whether this can also resolve connecting to a shared IP address owned by several nodes in a cluster with different keys. Changing the keys is not an option for me.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .