2

I want to determine the target address of an SSH connection with a function call that generate the address to connect to. All of the examples using ProxyCommand that I can find online use the -W flag to hop to a second machine. I tried that with localhost for the second machine, and that worked but required SSH authentication twice which I didn't like.

I am trying to call ssh inside of the ProxyCommand without forwarding to second hop. Right now, I have in my .ssh/config file:

Host test
    ProxyCommand ssh user@address

When I do ssh test, it seems to connect okay but after connecting there is a blank prompt that does not respond to input, so it seems stdin/stdout must not be directed properly.

Related questions:

Use a dynamically obtained hostname with an ssh config entry

How to get HostName from executable script in SSH config file?

Dynamically generate SSH Host entries in ~/.ssh/config

  • See man ssh_config – Valentin Bajrami Jun 10 '15 at 17:56
  • 1
    The point of -W is to forward the existing connection instead of opening a new one. You were asked to authenticate twice precisely because you didn't use -W. Anyway, it isn't clear what you want to do and how that differs from using -W. – lcd047 Jun 10 '15 at 17:56
  • No, I was asked to authenticate twice when I did use -W. I want ssh test to connect as though as I had entered ssh user@address when I have the given block in .ssh/config. (And I can't just put address in the HostName entry because I want to replace it with $(generate_address) that will generate the address dynamically when ssh is called. – ws_e_c421 Jun 10 '15 at 18:00
  • Use ssh-agent then. – lcd047 Jun 10 '15 at 18:02
  • If you want to go from machine A to B to C, you need to add the address of machine B to HostName, and the address of machine C to the ssh command in the ProxyCommand line. – lcd047 Jun 10 '15 at 18:06
3

Since you don't pass a command to ssh, it runs a shell, which expects commands on its standard input. But you aren't passing it shell commands, you're passing it SSH traffic. Hilarity ensues.

Tunnelling is the whole point of ProxyCommand. This example tunnels an SSH connection inside an SSH connection. If you don't want to tunnel, ProxyCommand is not what you're looking for.

Since OpenSSH 6.4, you can use a Match directive with the exec keyword to include blocks conditionally based on a run-time directive. A typical use case is to have different actual host names or proxy commands depending on where your laptop is. Each Match block replaces a Host block, and you can't use the output of the command to determine the host name, only the fact that it exited with status 0.

# Connection inside ACME network
Match host foo exec on-acme-network
HostName foo.acme.local

# Connection from outside ACME
Host foo
HostName foo.example.com

Proxying is another option. To make a connection to a host name and port that are determined at connection time, you can use netcat to set up the TCP connection.

Host foo
ProxyCommand nc $(determine-target-host-name) 22

If you want a fully dynamic .ssh/config, you can make it a named pipe and ensure that a process is always writing to it. Or put it on scriptfs.

  • I'd rather call that the old way of doing it. Prior to the ssh client supporting the -W switch, it was the normal way of doing things, but I think it makes sense to mention the ProxyCommand ssh -W %h:%p user@address form for cases where ssh -W is available. Personally I prefer the latter method always, because not on all jump hosts will I have nc or the rights to install it, but ssh is often recent enough. – 0xC0000022L Jun 10 '15 at 23:14
  • @0xC0000022L Yes, good point, thanks. I tend to forget about this newfangled 21st century stuff... – Gilles Jun 10 '15 at 23:24
  • Isn't your suggestion just the standard way to do a two-hop ssh connection? I want to do just one hop but I want that hop to be to an address that is looked up at run time (see comments under the question). I added links to some other questions I found asking basically the same thing. From those, it seems like this is not possible without writing a wrapper around ssh (doesn't work well with programs that call ssh) or using local DNS (hard since I don't have root access on the server where I want to ssh from), unless -W is passed localhost but it requires entering a password twice. – ws_e_c421 Jun 11 '15 at 3:26
  • 1
    @ws_e_c421 Ah, ok. Your question was confusing because the whole point of ProxyCommand is to do a two-hop connection. I've changed my answer to address your actual question. – Gilles Jun 11 '15 at 7:10
  • @Gilles: are you suggesting to pass the ProxyCommand stanza with the command substitution on the command line (-o) or is it actually possible to put this into the ~/.ssh/config file? I'm asking because Paramiko for one doesn't handle this syntax in its OpenSSH config parsing. – 0xC0000022L Jun 11 '15 at 7:22

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.