Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expand SSH hostname to IP where necessary (telnet for example) #2123

Open
7 of 10 tasks
drws opened this issue Jul 27, 2020 · 13 comments
Open
7 of 10 tasks

Expand SSH hostname to IP where necessary (telnet for example) #2123

drws opened this issue Jul 27, 2020 · 13 comments

Comments

@drws
Copy link

drws commented Jul 27, 2020

  • I have read through the manual page (man fzf)
  • I have the latest version of fzf
  • I have searched through the existing issues

Info

  • OS
    • Linux
    • Mac OS X
    • Windows
    • Etc.
  • Shell
    • bash
    • zsh
    • fish

Problem / Steps to reproduce

SSH hosts configuration file ~/.ssh/config is parsed when the fzf "host" completion is used. The configured names of hosts and their respective addresses (IP/domain) are parsed into two separate fuzzy completion hits. However, the configured names cannot be used with non-SSH commands as they do not use the SSH config file (telnet being an example) and so these fuzzy completion hits are not useful. It would be a practical feature if in these cases fzf expanded SSH names into addresses (after selecting the name from the list of hits).

Such a solution could be implemented with a new "host_sshexpand" completion mode, but if this is not desired, the existing "host" one could be refit for this purpose and provide the described expansion by default. And then the SSH-type commands (ssh, scp, dbclient, ...) could be treated as special cases where this additional expansion is not necessary.

@moshiba
Copy link

moshiba commented Feb 21, 2021

It would be a practical feature if in these cases fzf expanded SSH names into addresses (after selecting the name from the list of hits).

Such a solution could be implemented with a new "host_sshexpand" completion mode, but if this is not desired, the existing "host" one could be refit for this purpose and provide the described expansion by default.

You should customize telnet completion instead.
After all hosts in ssh configs aren't for stuff like telnet anyway, you should set these in places like /etc/hosts.

Repurposing a semi-public function hurts backward compatibility and people who use _fzf_host_completion probably won't be grateful about this surprise.

@drws
Copy link
Author

drws commented Feb 21, 2021

I use fzf also because there is no need to edit /etc/hosts, so this would be counterproductive. Primarily I suggested an additional function (_fzf_hostssh_completion for example) that would expand SSH hosts into IPs after calling _fzf_host_completion and receiving input. There is no need to break compatibility.

@antofthy
Copy link

antofthy commented Feb 22, 2021

You may like to have a look at...
#2316

You can then DIY your own hostname completion handler, using fzf via normal BASH TAB hostname completion.

@drws
Copy link
Author

drws commented Feb 22, 2021

It seems as the proper way to DIY, but the referenced case is about using custom list (hostname source) and so at least partially-custom implementation is probably inevitable there. The case here would be to improve default completion capabilities so all host-autocompletion output would be cross-compatible between default-set command autocompletions. Another example besides telnet being unable to use expanded SSH hostnames is ping. Wouldn't it be cool if one could ping SSH hosts by their hostname?

@calestyo
Copy link
Contributor

calestyo commented Sep 27, 2023

TBH, I don’t quite understand this issue.

Any valid host (be it a name or an address literal) should be usable with telnet (and ssh, etc. pp.). Of course, whether something listens there, is a completely different question.

The only exception to this would be if one creates "fake" hostnames in ssh_config like I do e.g.:

Host VNC_foo.example.org
        HostName                foo.example.org
        LocalForward            localhost:51000 localhost:5900

then SSH could work with VNC_foo.example.org (because it knows a real name via HostName), but other's couldn't.

Is that what you mean?

I, personally, don't think that there's really a generic way in which fzf could solve this, other than allowing you to filter the host lists generated by __fzf_list_hosts(), in the various users of these (like _fzf_host_completion() and _fzf_complete_ssh().

One could perhaps offer something like what I propose in #3454 (comment), e.g. a FZF_COMPLETION_HOSTNAME_POSTPROCESS_CMD, where the user could then run a command to filter as he likes, in the example above e.g. via FZF_COMPLETION_HOSTNAME_POSTPROCESS_CMD="grep -v '^[A-Z]'".

Of course, one would then need different FZF_COMPLETION_HOSTNAME_POSTPROCESS_CMD and FZF_COMPLETION_SSH_HOSTNAME_POSTPROCESS_CMD.

See also #3454 (comment)

@drws
Copy link
Author

drws commented Oct 1, 2023

Is that what you mean?

It's almost spot on. What you described actually already works with SSH commands since they handle the ssh_config hosts natively. What is proposed here is that the same functionality would also work for non-SSH commands through fzf. Considering your case this would mean that you were able to ping VNC_foo.example.org for example (which would get expanded into ping foo.example.org).

@calestyo
Copy link
Contributor

calestyo commented Oct 1, 2023

Hmm, I see.

Though I wonder, whether this would be even desirable?

I mean if someone makes up "fake" hostnames via SSH (which makes sense in some cases), then I still see why one wants to filter them out from non-SSH completions… but expanding such to some "real" name or IP feels conceptually a bit wrong, as the fake name is in principle something purely SSH internal.

I'd also think it's difficult to do:

Consider someone sets up a fake name in SSH (or anything similar) that is also a real domainname with IP.

So even if you say you go all the way down to IP addresses (an not just to the "resolved" (I mean within e.g. ssh_config) hostname: which IP address would you take? The one that ssh_config maps to or the one from DNS?

@calestyo
Copy link
Contributor

calestyo commented Oct 1, 2023

And, expanding all the way down to an IP address seems even more problematic, considering that hostnames may have attached several of them (A and AAAA RRs) and even other things like SRV RRs, which a tool like telnet might use.

Again here, which of all these should the expansion use? One would loose e.g. round robin functionality and things like that, if simply one is chosen by chance.

@drws
Copy link
Author

drws commented Oct 2, 2023

Though I wonder, whether this would be even desirable?

To be fair the fzf completions are configurable, this would just be another available option. Personally I'd find it very useful to be able to ping SSH hosts.

the fake name is in principle something purely SSH internal.

The name itself yes, in principle, but the function would expand it to a valid host address from ssh_config, which should be resolvable and not purely SSH-internal.

And, expanding all the way down to an IP address seems even more problematic, considering that hostnames may have attached several of them (A and AAAA RRs) and even other things like SRV RRs, which a tool like telnet might use.

Again here, which of all these should the expansion use? One would loose e.g. round robin functionality and things like that, if simply one is chosen by chance.

The fzf's function would be to expand known SSH hosts to a ssh_config HostName value, nothing more, nothing less. This expansion would take precedence before DNS resolution is performed by the command itself, if necessary. If the user sets and uses this expansion wrongly, it is their problem, like with other available expansions.

@calestyo
Copy link
Contributor

calestyo commented Oct 2, 2023

The fzf's function would be to expand known SSH hosts to a ssh_config HostName value, nothing more, nothing less. This expansion would take precedence before DNS resolution is performed by the command itself, if necessary. If the user sets and uses this expansion wrongly, it is their problem, like with other available expansions.

Still, as said above, what if the expanded name is a normal valid hostname? It might be in ssh_config like so:

Host example.org
   Hostname 10.10.10.10

And at the same time be in /etc/hosts as:

10.10.10.10 example.org
10.10.10.20 example.org

which even makes sense, if some services are available via both IPs, but SSH only via one.

At least if fzf would now expand example.org per default and even for non-SSH to 10.10.10.10, other commands may no longer work as expected.

Another difficulty, I guess, might be if e.g. Match is used, in which case the same hostname can be mapped to different Hostname values.

@drws
Copy link
Author

drws commented Oct 2, 2023

Still, as said above, what if the expanded name is a normal valid hostname?

The normal valid hostname gets overridden due to the expansion, but that is user's problem. It'd be user's responsibility to know what they're doing (setup unique fake names). It's the same as with local DNS servers, hosts file configurations, ad blockers, ...

other commands may no longer work as expected.

The primary purpose of the expansion would be to help users with numerous SSH hosts that know what they're doing (and keep their SSH host names unique). I'm not worried about users with messy ssh_config, everybody needs to learn sometime. If your software starts to handle all possible user mistakes, there will be no end. And fzf is more of a power user thing anyway.

There will always be a guy that will find it funny to name his router locally google.com and we should definitely allow such aspiring brilliant minds to experience the results of their experiments rather than to wrap them in cotton wool :)

So a user has an option to set the ssh_config correctly in a way that both DNS and SSH hosts can be resolved, or wrongly, just as with any other setting in any other piece of software. Also, it would probably also not be the first expansion in fzf that could be used wrongly.

Another difficulty, I guess, might be if e.g. Match is used, in which case the same hostname can be mapped to different Hostname values.

Only exact Host matches would work. If you're talking about multiple HostNames under a single Host, then there's also really only one option. fzf cannot possibly know more than the user and the first HostName is the only one guaranteed, so it simply picks the first one. I believe this is the sole and only KISS solution here.

Picking the first HostName doesn't cover every edge case in the world, but is deterministic, which is much more important.

@calestyo
Copy link
Contributor

calestyo commented Oct 3, 2023

It's the same as with local DNS servers, hosts file configurations, ad blockers, ...

Well I wouldn't consider this to be exactly the same situation. If I set up my own DNS server, but configure it in /etc/resolv.conf it's obvious that everything will use it (and potentially break things).

If, however, I make some config in ssh_config one can reasonable expect that only ssh and tools that use ssh will use it. So IMO it's not really to be expected that this may affect other things as well, which it then (with that expansion on completion) would however.

Don't get me wrong, I have nothing against the feature per se, I just think it may be quite tricky to implement properly and may cause behaviour that is not necessarily to be expected.

So nice if it would be implemented, but I think it should be an opt-in functionality that's disabled per default.

One idea that I had (for another use case) might actually help with yours, too:

What I'd like fzf to be able to do (well maybe it actually can already do it and I've been just to lazy to RTFM ;-) ):

  • If I complete e.g. ssh **<TAB> I want to see hostnames. I guess so far that makes sense.
  • If I then select a hostname an press Enter I want ssh selected.hostname.org. Should be still fairly reasonable.
  • If instead of Enter I do say e.g. <Shift-Tab>, I'd like to see another selection "pop-up" (within fzf), that prints me usernames for which I have access on the currently selected hostname (so that varies from selected host to host - and of course there needed to be some way where I store the information and fzf would need some way to get that list). If I then do Enter, I want the ssh [email protected]. If I do e.g. Esc I'd like to just go back and leave the "pop-up".

Of course, there would need to be quite some additional functionality (e.g. a way to tell fzf that it should combine the two selections to <selection from pop up>@<main selection>... but well.. it's just an idea so far. ^^

Anyway... this might be a nice way for what you want, just that the "pop-up" doesn't show usernames, but all possible mappings for the current hostname (which is possibly a fake hostname).
And of course in your case, fzf would need to be told to return just <selection from pop up>.

@antofthy
Copy link

antofthy commented Oct 3, 2023

I also did not want to have to deal with usernames.
So I have wrapper script around 'ssh' I call 'r' which looks up the username to use if I don't give one.

So if I type r -x l
It executes something like ssh -x [email protected] (example only not my real account)

This wrapper expands the destination 'l' account using.

  • host aliases EG: l -> lamia
  • DNS look ups... lamia -> lamia.staff.example.org don't even rely on '/etc/resolve' domains
  • and a account list for the username lookup, created originally for updating my homes on 500+ servers!

The wrapper handles normal ssh options, and if I actually give it a [email protected].
It also handles special cases like getting to specific machines via intermediate jump hosts if needed.

For more information look at my ssh notes....
https://antofthy.gitlab.io/info/apps/ssh.txt
and search for 'SSH Command wrapper -- Why do it?'

that file also has sections on...
'Calling your SSH Wrapper from another program'
for information on how to get programs like "rsync", "scp", "cssh" etc., to call a wrapper script
'Parsing SSH options'
for information on parsing the ssh options so you can get the destination option reliably.
and so you can handle -l username.

I built this system a little at a time over 30 year! Starting back in the days of telnet and rsh (may they rest in peace). Every so often something else was added, abstracted away, re-factored, or simplified.

The 'r' script for example is NOT the only script that uses account names, so much of the 'lookups' was actually in other scripts that can be used by other scripts. For example I have a 'find_acct' script to do the username lookup, and 'find_host' script to do the DNS lookup using personal host aliases file and a list of domains the host might be in. But the scripts are optimized for my own use and the files I have created, and not something I would share.

NOW... That is NOT to say I don't use fzf I do.
See... #2316
I just found using a ssh wrapper is a much better solution for some problems, like usernames.

However that does not mean you couldn't use 'fzf' to search against a verbose list of accounts and usernames you own, however you have them stored!

Shells are a tool, and we are its carpenters.
Sometimes we need a hammer and sometimes a screwdriver.   -- John Navarra

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants