0

When connecting to a host via SSH, I'd like to be able to simply type ssh hostname to connect.

However, the setup we have currently means that I must type a fairly long suffix to connect, similar to hostname.hosts.companyname.com.

Is it possible to set up SSH to cycle through several hostnames before giving up a connection without adding them to my hosts file? For example. if I type in ssh hostname, I would like SSH to:

  1. Attempt to SSH to hostname, if that fails after a short timeout:
  2. Attempt to SSH to hostname.hosts.companyname.com, if that fails after a short timeout:
  3. Attempt to SSH to hostname.companyname.com, and if that fails then it should print the error.

However, we have >1000 hosts and I would rather not add an alias to everything. I would prefer this to be default behaviour.

The above is a short example. I would prefer the ability to add something in the range of 30 potential domains to this list, which is why resolv.conf search is not an option (as it's limited to 6 domains).

  • Is your DNS zone not set up to search unqualified host names in the local zone? When I run host foobar inside the network of my university faculty it will find foobar.my-faculty.my-university.de (assuming that host name exists). Alternatively you set up host name aliases in the SSH client configuration. – David Foerster Dec 17 '17 at 22:57
  • @DavidFoerster It's not no. I wasn't sure if that was going to be the best way to set it up or if there was a decent way of doing it via SSH config only. – Connor Bell Dec 17 '17 at 22:58
  • What is in your /etc/resolv.conf regarding search domain(s) ? That could fix it for you... – ivanivan Dec 18 '17 at 0:24
  • 1
    As you connect to hosts, they (their public key) will get added to known_hosts locally and a base autocompletion system uses that file, meaning that if you do ssh hostname[TAB][TAB] will show you options, without having to define specifically each host. – Patrick Mevzek Dec 19 '17 at 1:40
  • @ivanivan See my comment on roaima's answer. – Connor Bell Dec 19 '17 at 10:54
2

Update your DNS /etc/resolv.conf according to these two steps:

  1. There may be a line domain or search. If there is, replace domain with search in the file, and continue to the next step.
  2. Append hosts.companyname.com companyname.com to the search list. If there was no search (or domain) directive, create one with these two values.

Example result

nameserver 192.168.1.254
nameserver 192.168.2.254
search hosts.companyname.com companyname.com

This will allow unqualified names to be resolved through /etc/hosts and DNS according to your criteria.

  • I'd like to use the search part of resolv.conf, but it's limited to 6 domains and 256 characters. I'd like more like 30 domains and 500+ characters. As I understand it that isn't possible without recompiling. It's also a bit annoying to get resolv.conf changes to work properly with resolvconf, but that's a different problem. – Connor Bell Dec 19 '17 at 10:53
  • @ConnorBell your question requests support for only two (or three) different suffixes. It would be well worth updating your question to explain to would-be answerers the scale of your production environment requirements. I wouldn't have suggested a change to /etc/resolv.conf if I'd know you wanted completion across ~30 domains. – roaima Dec 19 '17 at 12:13
  • Edited, apologies. Out of interest, do you think a dig axfr is a potential workaround for this? Create an alias to a function that does an axfr then check for the presence of the search string at the beginning each entry? – Connor Bell Dec 19 '17 at 13:27
1

There are at least two options:

config file

You generate an ~/.ssh/config file with the aliases:

Host hostname
    HostName hostname.hosts.companyname.com

Assuming the correct hostnames are static. Of course, this is somehow similar to changing the /etc/hosts file.

shell function

You define a shell function for the command name ssh or something you have to call explicitly like ssh-hosts.

ssh () {
        hostname="$1"
        test -z "$hostname" && return 128

        for suffix in "" .hosts.companyname.com .companyname.com ; do
                test_hostname="$hostname$suffix"
                if [ -n "$(ssh-keyscan "$test_hostname" 2>/dev/null)"; then
                        ssh "$test_hostname"
                        return $?
                fi
        done
}

Of course, you could use this approach for generating the config file, too. If you do not have a list of all the host names then you could even use the shell function for adding new Host blocks to the config file and check the file before running ssh-keyscan.

  • Thanks for the answer - I'm trying to avoid having to write down aliases for every host I need to connect to, I'd rather have it cycle through or check the existence via dig or something prior to trying to connect. – Connor Bell Dec 17 '17 at 22:59
  • @ConnorBell See my edit. – Hauke Laging Dec 17 '17 at 23:10
  • Ooh, that shell function looks exactly like what I wanted. I'll give that a go tomorrow. Thank you! – Connor Bell Dec 17 '17 at 23:22
  • I don't care to elaborate on this, but, assuming OpenSSH, one might create one or many sections in ~/.ssh/config which uses ProxyCommand to cycle through various FQDNs, based on the hostname when connecting to the remot host. That way you don't need to wrap ssh and you would end up with a procedure that is employed only for specific hostnames, or patterns. – Bananguin Dec 17 '17 at 23:50
  • This looks good, with one exception: on my platform at least, ssh-keyscan always returns 0 (success) regardless of whether or not it actually succeeded matching a hostname. – roaima Dec 19 '17 at 16:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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