1

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).

6
  • 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. Commented Dec 17, 2017 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. Commented Dec 17, 2017 at 22:58
  • What is in your /etc/resolv.conf regarding search domain(s) ? That could fix it for you...
    – ivanivan
    Commented Dec 18, 2017 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. Commented Dec 19, 2017 at 1:40
  • @ivanivan See my comment on roaima's answer. Commented Dec 19, 2017 at 10:54

2 Answers 2

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.

3
  • 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. Commented Dec 19, 2017 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. Commented Dec 19, 2017 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? Commented Dec 19, 2017 at 13:27
2

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.

6
  • 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. Commented Dec 17, 2017 at 22:59
  • @ConnorBell See my edit. Commented Dec 17, 2017 at 23:10
  • Ooh, that shell function looks exactly like what I wanted. I'll give that a go tomorrow. Thank you! Commented Dec 17, 2017 at 23:22
  • 1
    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
    Commented Dec 17, 2017 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. Commented Dec 19, 2017 at 16:49

You must log in to answer this question.

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