Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I frequently need to ssh into an arbitrary computer from a particular cluster (all machines in the cluster are identical). However, the set of available machines in the cluster changes frequently, so I have a script that returns an arbitrary hostname from the cluster that is available and matches my requirements (e.g., online and running the correct OS).

Note also, that I'm using Kerberos (GSSAPIAuthentication) credential forwarding for authentication.

Right now, I ssh in using ssh `get_host`. I would like to instead execute ssh cluster. With a known hostname, this is easy with the following in /ssh/config:

Host cluster
    HostName static_host.cluster.domain.tld
    GSSAPIAuthentication yes
    GSSAPIDelegateCredentials yes

How can I select the HostName dynamically, using my script? (Or does SSH have a different method to support my desired function?) I would like to do something like the following, but it does not work:

Host cluster
    HostName `get_host`   # This does not work
    ...

Grawity showed that the ProxyCommandcan be a script that gets the hostname and forwards the ssh connection to it using netcat or socat. However, this isn't forwarding the Kerberos credentials. Help with this is appreciated as well.

EDIT:

Can't do this with Kerbos, as I would like (see comments in the accepted answer). So, I'm using this script ssh-wrapper as an ssh alias, to do dynamic rewriting on the ssh command-line argument. It's not robust, but works for me.

#!/bin/bash

# Mapping between host aliases and dynamically-generated hostname
declare -A MAP
MAP[cluster]=`gethost`

# Find and replace on all positional args
args=$*
for key in ${!MAP[@]}; do
    replace=${MAP[$key]}
    args=`echo ${args} | sed "s/\(^\|[[:space:]]\)${key}\(\$\|[[:space:]]\)/${replace}/"`
done

# Execute using called-name if not this script
if [ "ssh-wrapper" != "`basename $0`" ]; then
    exec $0 ${args}
# Otherwise, assume ssh and execute
else
    exec ssh ${args}
fi
share|improve this question

1 Answer 1

up vote 4 down vote accepted

~/.ssh/config:

Host cluster
    ProxyCommand ~/bin/cluster-connect

~/bin/cluster-connect:

#!/bin/bash
socat stdio tcp:$(get_host):22
share|improve this answer
    
Thanks. This (or netcat $(get_host) 22) works great for the connection. But, it doesn't seem to pass my kerberos credentials. I've got GSSAPIAuthentication yes and GSSAPIDelegateCredentials yes under Host cluster in my .ssh/config file, and they work if the HostName is given explicity, but not if I route through the ProxyCommand. Thoughts? I'll amend the question as well. –  David B. Sep 21 '11 at 19:20
    
I don't think you can achieve that -- ssh must know the target hostname to get the correct ticket, and there's just no way to provide it dynamically (short of using a wrapper that simply runs ssh $(get_host) "$@", which as I understood you don't want). It may work if all servers in the cluster have the same Kerberos principal, but I don't think anyone ever does that. –  grawity Sep 21 '11 at 19:30
    
Unfortunate, but makes sens. I wrote a quick wrapper to do a dynamic find/replace (added to the question). It'll break in some scenarios, but works for me. –  David B. Sep 21 '11 at 21:00
    
Dynamic find/replace?... –  grawity Sep 21 '11 at 21:03
    
Just a sed substituion on the commandline arguments to ssh, from a host-alise to host-generation-script mapping stored in the script. –  David B. Sep 21 '11 at 21:05

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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