2

I have a bunch of Linux machines behind 2 gateways. To connect to set one I do

ssh -o ProxyCommand="ssh gateway1 nc %h %p" machines_behind_1
ssh -o ProxyCommand="ssh gateway2 nc --proxy %h %p --proxy-type socks4" machines_behind_2

To simplify this process, I thought I would create a environment variable to hold the proxycommand and simply use that. So I did

export PGWA='-o ProxyCommand="ssh gateway1 nc %h %p"'
export PGWB='-o ProxyCommand="ssh gateway2 nc --proxy %h %p --proxy-type socks4"'

Then, depending on the machine I want to connect, I would do

ssh $PGWA machine_behind_1
ssh $PGWB machine_behind_2 

But I get this error -

/bin/bash: -c: line 0: unexpected EOF while looking for matching `"'
/bin/bash: -c: line 1: syntax error: unexpected end of file

Any idea why?

I can't use any ssh_config tricks, because I don't know the hostnames ahead of time. I might create a new VM behind gateway1 , and I will need to use the first proxy command.

The only thing I can think of is create a new alias, a function or a shell script which basically does ssh -o foo $@ and use that instead. But then, I need to remember to create an alias/shell script or function for scp as well, which too I use regularly. I would rather be able to do it automatically.

I kinda hoped I could do something like ssh gw1-host and do some manipulation inside the config file to convert it to ssh -o foo host through the first gateway, but that kind of regex manipulation is not allowed inside the ssh_config.

Any way I can achieve what I want without individual ssh / scp alias/script/function?

EDIT: I had made a mistake with the quoting when I copy-pasted the environment variable into stack exchange here.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255

1 Answers1

5

When you write $PGWA without quotes, this splits the value of PGWA at whitespace¹. Quote characters have no special meaning there, so you end up with the words -o, ProxyCommand="ssh, gateway1, nc, %h and %p".

See Why does my shell script choke on whitespace or other special characters? for more explanations.

A variable expansion outside of double quotes is almost always a mistake. It's always a mistake unless you know why you need to leave the double quotes off.

What you need to do is to pass two arguments to the SSH command: -o and ProxyCommand=ssh gateway2 nc --proxy %h %p --proxy-type socks4.

In zsh, you could just set PGWA to an array:

PGWA=(-o 'ProxyCommand=ssh gateway2 nc --proxy %h %p --proxy-type socks4')
ssh $PGWA …

In other shells such as bash and ksh, this requires more typing, because of their design misfeature that unquoted variable expansions undergo splitting and because of their explicit syntax for arrays:

PGWA=(-o 'ProxyCommand=ssh gateway2 nc --proxy %h %p --proxy-type socks4')
ssh "${PGWA[@]}" …

A method that would work in any sh-like shell and wouldn't require much typing would be to define functions.

pgwa () {
  typeset c="$1"; shift
  "$c" -o 'ProxyCommand=ssh gateway2 nc --proxy %h %p --proxy-type socks4' "$@"
}
pgwa ssh …

But I think the best solution would be to put all of these definitions in your .ssh/config where they belong. This way you wouldn't need any shell tricks and the configurations would work in other programs (rsync, sshfs, GUI file transfer programs, etc.). If you add a new VM behind gateway1, either add an entry to .ssh/config or use ssh -o HostName=new-vm something-behind-gateway1 …

¹ Plus other things that don't matter here.