sshs icon indicating copy to clipboard operation
sshs copied to clipboard

Implement sshs config generator from known_hosts files

Open quantumsheep opened this issue 4 years ago • 25 comments

Relates to #6.

quantumsheep avatar Feb 09 '22 01:02 quantumsheep

@jarrodCoombes this is the maximum I can do with known_hosts, using sshs generate --known-hosts it will generate Host, Hostname and Port for each entry.

--known-hosts is required because I though about doing the same thing but for bash/zsh history - not sure yet.

Do you see further improvements that can be made?

quantumsheep avatar Feb 09 '22 01:02 quantumsheep

Ooh! I'll give it a go in a bit, but that sounds exactly like I was thinking and it'll be a great shortcut for getting the list populated.

I do like the idea of getting the info from the bash/zsh history, anything that allows semi-automated generation of the menu is a plus IMO.

Are the changes reflected in the pre-build binaries in the releases?

jarrodCoombes avatar Feb 09 '22 02:02 jarrodCoombes

Are the changes reflected in the pre-build binaries in the releases?

Sadly no, you need to build it yourself. But it's just calling `makeˋ.

quantumsheep avatar Feb 09 '22 08:02 quantumsheep

So I pulled down the source, installed Go, installed the other needed things it called for and compiled it. Running ssh generate --known-hosts spits out an error of unknown flag

sshs -v returns sshs version 1.5.0-2-g38cc2c9

What did I do wrong here?

jarrodCoombes avatar Feb 09 '22 16:02 jarrodCoombes

Did you checkout to branch feature/generator-known-hosts?

quantumsheep avatar Feb 09 '22 21:02 quantumsheep

@jarrodCoombes you can find a built version in the artifacts: https://github.com/quantumsheep/sshs/actions/runs/1828649999

quantumsheep avatar Feb 11 '22 01:02 quantumsheep

I am new to github, so only know how to checkout the master branch, and did not know there was a feature branch. I'll need to look up how to do that. In the meantime, I grabbed the binary and tested it. It works well, but there are some issues.

In the known_hosts file you can actually have a single signature tied to multiple host names/ips.

My entry that looks like this: [server.domain.tld]:222,[xx.xx.xx.xx]:222 ecdsa-sha2-nistp256 <key> Gets parsed like this:

Host server.domain.tld]:222,[xx.xx.xx.xx
  Hostname server.domain.tld]:222,[xx.xx.xx.xx
  Port 222

Also this: server2.domain.tld,server2,yy.yy.yy.yy ecdsa-sha2-nistp256 key Parses to this:

Host server2.domain.tld
  Hostname server2.domain.tld,yy.yy.yy.yy
  Port 22

Other than that, it actually did a great job.

jarrodCoombes avatar Feb 11 '22 17:02 jarrodCoombes

With your example, for instance:

[server.domain.tld]:222,[xx.xx.xx.xx]:222 ecdsa-sha2-nistp256 <key>
server2.domain.tld,server2,yy.yy.yy.yy ecdsa-sha2-nistp256 <key>

It gives this output in the last commit:

Host server.domain.tld:222
  Hostname server.domain.tld
  Port 222

Host xx.xx.xx.xx:222
  Hostname xx.xx.xx.xx
  Port 222

Host server2.domain.tld
  Hostname server2.domain.tld
  Port 22

Host server2
  Hostname server2
  Port 22

Host yy.yy.yy.yy
  Hostname yy.yy.yy.yy
  Port 22

What do you think ?

quantumsheep avatar Feb 11 '22 23:02 quantumsheep

I think that leads to quite a bit of redundancy and clutter.

When given:

[server.domain.tld]:222,[xx.xx.xx.xx]:222 ecdsa-sha2-nistp256 <key>
server2.domain.tld,server2,yy.yy.yy.yy ecdsa-sha2-nistp256 <key>

It should return:

Host "server.domain.tld"
  Hostname server.domain.tld
  User <local signed in user>
  Port 222

Host "server2.domain.tld"
  Hostname server2.domain.tld
  User <local signed in user>
  Port 22

Basically your host and hostname should be everything up to the first comma (minus any port info). The bits in the known_hosts file that are separated by commas are going to almost always be either DNS host names or alternative IPs on that same server, so generating multiple entries based on each line would make the menu really redundant.

I suggest the quotes for the host because it looks like sshs uses that field as the target unless it is in quotes. Not sure if this is deliberate or not, but something I noted when testing this.

jarrodCoombes avatar Feb 14 '22 22:02 jarrodCoombes

I think that leads to quite a bit of redundancy and clutter.

But what do you do for this:

[server.domain.tld]:222,[xx.xx.xx.xx]:222,[server2.domain.tld]:222 ecdsa-sha2-nistp256 <key>

Or even:

[server.domain.tld]:222,[xx.xx.xx.xx]:222,[server.domain.tld]:333 ecdsa-sha2-nistp256 <key>

quantumsheep avatar Feb 14 '22 22:02 quantumsheep

I would assume that if they share a <key>, then they are the same server. I cannot for the life of me think of a situation where you would have the same <key> on different servers, especially since that <key> is generated randomly by sshd when it's installed and is only used to unique identify that system for security reasons. Nor can I think of a reason you'd have sshd responding on multiple ports.

At the very least this would be such a rare edge case, that I am not sure it's reasonably to account for it. I also see this generate option as a kick-start type thing. It'll get you mostly there, but you'll still need to edit the config file to account for your specific need, and anyone who has gone through the trouble of manually setting the <key> for their server is going to be very much aware of their special setup and probably won't use the generate option anyway.

Also, remember that sshd adds all new connections on their own lines, you have to manually edit known-hosts to make entries with commas in them, which is what I did in mine in order to clean it up and shorten it, I don't think most people would be doing this.

jarrodCoombes avatar Feb 15 '22 19:02 jarrodCoombes

Should be better in the last commit (check artifacts at https://github.com/quantumsheep/sshs/actions/runs/1849655613).

I added --known-hosts-allow-single-ip option to allow lines without a valid domain name.

quantumsheep avatar Feb 15 '22 22:02 quantumsheep

Should be better in the last commit (check artifacts at https://github.com/quantumsheep/sshs/actions/runs/1849655613).

I added --known-hosts-allow-single-ip option to allow lines without a valid domain name.

Interesting, not too sure that is really all that necessary. I think this:

1.2.3.4 ecdsa-sha2-nistp256 <key>
5.6.7.8:333 ecdsa-sha2-nistp256 <key>

Should return

Host "1.2.3.4"
  Hostname 1.2.3.4
  User <local signed in user>
  Port 22

Host "5.6.7.8"
  Hostname 5.6.7.8
  User <local signed in user>
  Port 333

This will almost certainly be the majority of all cases that you'll find the known-hosts file, and it makes editing the config file to adjust entries to meaningful names (ie `Host "Name of Server") much quicker and easier.

My use is a little bit of an edge case I think, or at least a power user case, the vast majority of people probably won't have such a neat and organized known-hosts file.

jarrodCoombes avatar Feb 16 '22 02:02 jarrodCoombes

I think this:

5.6.7.8:333 ecdsa-sha2-nistp256 <key>

Should return

Host "5.6.7.8"
  Hostname 5.6.7.8
  User <local signed in user>
  Port 333

We can't set Host to 5.6.7.8 because that would break when having the same IP using the different ports for different servers (that's my case). That's where I'm blocking.

quantumsheep avatar Feb 19 '22 21:02 quantumsheep

We can't set Host to 5.6.7.8 because that would break when having the same IP using the different ports for different servers (that's my case). That's where I'm blocking.

So this config would be considered invalid?

Host "5.6.7.8"
  Hostname 5.6.7.8
  User <local signed in user>
  Port 333

Host "5.6.7.8"
  Hostname 5.6.7.8
  User <local signed in user>
  Port 222

Host "5.6.7.8"
  Hostname 5.6.7.8
  User <local signed in user>
  Port 111

What about this:

Host 5.6.7.8
  Hostname 5.6.7.8
  User <local signed in user>
  Port 333

Host 5.6.7.8
  Hostname 5.6.7.8
  User <local signed in user>
  Port 222

Host 5.6.7.8
  Hostname 5.6.7.8
  User <local signed in user>
  Port 111

This makes me wonder what the difference between host and hostname is for sshs. IMO host should just be the name of the connection, and hostname should be the server IP/DNS name. And duplicate host and hostname entries should be allowed so long as they have different ports.

jarrodCoombes avatar Mar 02 '22 16:03 jarrodCoombes

What about this:

Host 5.6.7.8
  Hostname 5.6.7.8
  User <local signed in user>
  Port 333

Host 5.6.7.8
  Hostname 5.6.7.8
  User <local signed in user>
  Port 222

Host 5.6.7.8
  Hostname 5.6.7.8
  User <local signed in user>
  Port 111

sshs works by calling ssh over an host (E.g. calling ssh "example host"). Multiple SSH hosts with the same name would be handled by ssh but it doesn't make sense in sshs. However if we name them by host:port it's fine for when calling ssh.

quantumsheep avatar Mar 02 '22 20:03 quantumsheep

sshs works by calling ssh over an host (E.g. calling ssh "example host"). Multiple SSH hosts with the same name would be handled by ssh but it doesn't make sense in sshs. However if we name them by host:port it's fine for when calling ssh.

I get that, but from my testing sshs seems to try ssh user@host:port unless host is in quotes, then it appears to use ssh user@hostname:port Hence my confusion/questions. I am not sure if this is by design or not.

Host "My Host 1"
  Hostname 1.2.0.2
  Port 22

Host My Host 2
  Hostname 1.2.0.2
  Port 22

If I select My Host 1 from the list, SSH connects to 1.2.0.2 just fine. If, however, I select My Host 2 I get:

ssh: Could not resolve hostname My Host 2: nodename nor servname provided, or not known

I think that sshs should always use hostname as the server name/ip and host should only be used to name it. And then when SSH is called it would always be called by ssh hostname:port and then multiple entries in the config would not be an issue, though I do note that sshs just ignore subsequent entries with the same Host set, which it probably should not do.

jarrodCoombes avatar Mar 02 '22 20:03 jarrodCoombes

I think that sshs should always use hostname as the server name/ip and host should only be used to name it

There are cases when a host doesn't have an hostname (E.g. ProxyCommand). That's why I rely on Host. Also I believe that Host My Host 2 is invalid.

quantumsheep avatar Mar 02 '22 22:03 quantumsheep

I think that sshs should always use hostname as the server name/ip and host should only be used to name it

There are cases when a host doesn't have an hostname (E.g. ProxyCommand). That's why I rely on Host. Also I believe that Host My Host 2 is invalid.

I feel like I am missing something here. You say you rely on the host field, but then why does sshs skip it if it is in quotes and move onto the hostname instead? This strikes me as unexpected and confusing.

Also Host My Host 2 is invalid in what sense? It appears to be invalid if you use the command ssh My Host 2, but sshs puts it in the menu just fine, and it is selectable, it just hands the wrong thing over to the ssh command.

I am completely confused by why there is a host and a hostname in the config, and that is then compounded by the way sshs treats host different when it has and does not have quotes.

As for cases where a host doesn't have a hostname, how does sshs handle that?

jarrodCoombes avatar Mar 02 '22 22:03 jarrodCoombes

I feel like I am missing something here.

Yes I was, and I apologize for this. I did not realize that the config file was actually a feature of openSSH, and designed to make using ssh easier to use. I understand the issue now.

With my newly acquired knowledge I think I can say that this feature is about as good as it can probably get, but I will do some testing on it.

jarrodCoombes avatar Mar 03 '22 18:03 jarrodCoombes

I did not realize that the config file was actually a feature of openSSH

Sorry I didn't realized, I would have told you :/

but I will do some testing on it

Ok, I'm waiting for your return to decide if we merge it like that or change it.

quantumsheep avatar Mar 04 '22 19:03 quantumsheep

Looks like it's ignoring all my entries in known-hosts that do not have host names (ie are just IPs, I have a mix of both). But the ones it does return all look good.

[server-02.domain.tld]:222,[10.11.12.13]:222 ecdsa-sha2-nistp256 <key>

server-01,server-01.doman.tld,1.2.3.4 ecdsa-sha2-nistp256 <key>

5.6.7.8 ssh-rsa <key>

Returns:

Host server-02.domain.tld:222
  Hostname server-02.domain.tld
  Port 222

Host server-01
  Hostname server-01
  Port 22

jarrodCoombes avatar Mar 04 '22 19:03 jarrodCoombes

[server-02.domain.tld]:222,[10.11.12.13]:222 ecdsa-sha2-nistp256 <key>

server-01,server-01.doman.tld,1.2.3.4 ecdsa-sha2-nistp256 <key>

5.6.7.8 ssh-rsa <key>

Returns:

Host server-02.domain.tld:222
  Hostname server-02.domain.tld
  Port 222

Host server-01
  Hostname server-01
  Port 22

Should we add an a 5.6.7.8 entry ?

quantumsheep avatar Mar 08 '22 14:03 quantumsheep

I think so, to me it makes sense to treat each line in the known_hosts file as a separate host for the config file.

jarrodCoombes avatar Mar 08 '22 18:03 jarrodCoombes

I think so, to me it makes sense to treat each line in the known_hosts file as a separate host for the config file.

It should be good in https://github.com/quantumsheep/sshs/actions/runs/1953959990

quantumsheep avatar Mar 08 '22 21:03 quantumsheep