10

I connect to a number of machines constantly, from different physical locations (and thus different physical machines). Most of this is done though ssh, sometimes a gateway machine or two is required (which I invoke via ProxyCommand in ~/.ssh/config). I'd like to know if there's a method to identify the IP or hostname of the machine that calls the initial connection (ie the machine I'm working on) at the remote end?

  • I don't want to send environment variables as some machines I don't have root to set PermitUserEnvironment.
  • The $SSH_CLIENT environment variable is useful for direct connections, but only lists the most recent gateway.

My current idea for a solution is to grab $SSH_CLIENT, ssh to it, find that machine's $SSH_CLIENT value and repeat until it doesn't exist; then grab the hostname and pull it back somehow.

Seems like a bit of a hack job though; does anyone have a better method?

I'm working in a bash shell mostly, but I'm also happy for any suggestions that don't use it too.

3
  • One of the purposes of ProxyCommand is of course to hide (or forget about) the origin host (which may for example be not routable from the final host anyway) Aug 20, 2013 at 8:14
  • Can you give an example where or why do you need this information? There could be other non-obvious solutions.
    – Manwe
    Aug 21, 2013 at 5:54
  • @Manwe I'll ultimately want to set up locale specific sections in things like my .bashrc. Right now all I want to do is set one of three keyboard layouts automatically in vim depending on what machine I'm working from.
    – Geodesic
    Aug 21, 2013 at 7:26

4 Answers 4

3
+50

I have never tried, but I can think of something that may work: You do not let SSH start your login shell, but take matters in your own hands. You can tell SSH to run arbitrary commands. Instead of

ssh remote_host

you would run something along the lines of

ssh remote_host -t "
    . /etc/profile; 
    . /etc/bash.bashrc; 
    DAT_ORIGIN_HOST=$(ifconfig eth0|grep -Po 't addr:\K[\d.]+') /bin/bash -l -i"

What this does is, it gives SSH something else to do instead of launching a login shell. That something is a string, which will be run as command, remotely. We use this to launch a shell in a very special manner: we give it an environmental variable DAT_ORIGIN_HOST, which contains our ip on eth0 (you may need to change that).

The trick we perform is that we put the command to execute remotely in double qoutes ". The double quotes (at least in Bash) mean, that BEFORE THE STRING IS PASSED TO SSH, our shell scans it and performs expansions/replacements, where appropriate. This means our shell will evaluate the `$(ifconfig ...) part, to our current ip address and pass ssh a string which contains the definition for an environmental variable with our local ip address.

Once logged in to the remote machine, echo $DAT_ORIGIN_HOST should print your IP address.

To develop that call to SSH I shamelessly took from here for extracting the IP address and here for the -t and how to launch something interactive

Disclaimer: I am unsure about the -l and -i option to /bin/bash. Maybe you need to omit them.

2
  • You might be on to something here! I'll play around with it for a bit and get back to you.
    – Geodesic
    Aug 23, 2013 at 7:26
  • I'm marking this answer, as pseudo-tty and remote commands both work. I ultimately solved my particular case with ^E callbacks, based on the remote command suggestion - it ends up being a bit cleaner and general use. Thanks!
    – Geodesic
    Aug 23, 2013 at 8:11
2

Id I understood correctly you are connection directly from origin machine to destination with proxycommand hops. And so here are three hacks for you (third added after comment on usage scenario). First) Use remote port forwarding to allow you to get back to you origin machine with -R remotemachineport:dstonlocalnet:dstportonlocalnet

ssh -R 2222:localhost:22 user@target
# on "target" you can now do this to get back to origin host
ssh user2@localhost -p 2222 

Second) Abuse AcceptEnv LC_* on target. It's not nice but it's quite common to allow LOCALE variables even whan AcceptUserEnviconment is not available. So now you can do:

export LC_SOURCEHOST=my.ip.addr.or:something
ssh user@target
# on tathet:
echo $LC_SOURCEHOST

Third) Use ssh remote forward to identify host or host type.

# Here is an example what you can use on target machine. 
# This will modify your PS1 variable (prompt) based on source host (port forwarding)
# Add this to .bash_profile

function checkHost {
  RET=""
  ## loop over test port numbers 17891-17895 in my example
  for x in $(seq 1 5); do 
    # if netstat is not available test port some other way like with nc or something
    ## && RET= will set RET = 1-5
    /bin/netstat -lnt|/bin/grep -q 127.0.0.1:1789$x && RET=$x;
  done
  # return RET
  # please note that if you have multiple open connections with different port numbers
  # this method cannot not distinguish between them 
  echo $RET
}

# get 1-5 number from function above
VAL=$(checkHost)
# do something like set PS1 var or map vim file or something
export PS1='\[\033k\033\\\]\u@\h: \w\$ '$VAL

Now connect with port forwarding:

### this will still enable ssh forwarding back. Change 22 to something else like 
### 24 to disable it (if nothing is listening on your source machines 24 port)
ssh -R 17891:localhost:22 user@target
3
  • Thanks for the suggestions, but neither work to my full satisfaction just yet. The remote port forward is not a bad idea, but a necessary assumption is that you have the same username on all hosts. That's not the case here nor something I can change. Second: I couldn't get this to work. Are you saying that AcceptEnv LC_* is generally allowed, but not a standard, on by default setting?
    – Geodesic
    Aug 21, 2013 at 7:22
  • Well the LC_ is hit and miss. I cannot comment on how prevalent that is, but it's something that might work.. (remember to export LC_SOURCEHOST before ssh connection).
    – Manwe
    Aug 21, 2013 at 12:22
  • Tested LC_* and it works. It can be any variable listed in the AcceptEnv directive in /etc/ssh/sshd_config. Remember to restart sshd if this file gets changed. Aug 8, 2017 at 7:20
1

You can type who -m on the remote end to get information on the currently logged in user (including the hostname). who gives you information on logged in users, and the -m switch shows you "only hostname and user associated with stdin".

1
  • This is only useful if I'm not tunneling through a gateway machine though.
    – Geodesic
    Aug 23, 2013 at 7:21
0

did you try the following?

 netstat -an | grep " 22 "
1
  • This method is only useful for one hop connections, so isn't useful for me.
    – Geodesic
    Aug 26, 2013 at 1:28

You must log in to answer this question.

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