12

When connecting to a host with SSH, usually three "pipes" are provided between host and guest, for stdin, stdout, and stderr.

Is there a command-line option to create forwards for additional file descriptors (3 and onward)?

For example, I'd like to do

ssh --forwardfd=10:3 remotehost 'echo test >&3'

which would print 'test' to the locally-opened file descriptor 10.

  • 2
    Probably not without tricky source edits, given the various closefrom(STDERR_FILENO + 1) calls under the OpenSSH source code. What are you trying to do that demands this? – thrig Aug 31 '15 at 17:59
  • The protocol supports tunneling additional streams besides stdin/out/err, but AFAIK, no server/client provides support in any way that feature. – salva Feb 15 '17 at 8:08
  • @thrig Not OP, and it's been a long time, but in case you're still curious what this could be useful for, what I was hoping to find here was a clue on how to pipe through ssh, a script for bash and the stdin for that script. Something akin to: infinite-output-cmd | ssh user@host bash /proc/self/fd/3 3< local-script-to-execute-remotely.sh – JoL Sep 17 '18 at 22:08
  • @thrig It occurs to me that something like --forwardfd shouldn't even be needed. ssh could check out what the open file descriptors are before opening any other thing, and forward them automatically to the same file descriptors on the remote side. It could be totally transparent like my example. I wonder how difficult it would be to patch ssh for that. Like you said, it could be tricky depending on the reasons behind those closefrom(STDERR_FILENO + 1). – JoL Sep 17 '18 at 22:23
6

You can do this using socket forwarding, which is available since openssh-6.7. This is some kind of pipe. This technique is described for example here: http://www.25thandclement.com/~william/projects/streamlocal.html

You will gain two-direction route for your data. There is example with mysql:

Proxy MySQL client connections on a remote server to your local instance:

ssh -R/var/run/mysql.sock:/var/run/mysql.sock \
    -R127.0.0.1:3306:/var/run/mysql.sock somehost 
1

I'm sure it ought to be possible. I can only suggest a hack where you use extra ssh connections to each carry another pair of file descriptors. E.g. the following proof of concept script does a first ssh to run a dummy command (sleep) to connect up local fds 5 and 6 to remote stdin and stdout, presuming these fds are the ones you want to add to the usual 0,1,2.

Then the real ssh is done, and on the remote it connects up remote fds 5 and 6 to the stdin and stdout of the other ssh.

Just as an example, this script passes a gzipped man page through to the remote, which unzips and runs it through man. The stdin and stdout of the real ssh are still available for other things.

#!/bin/bash
exec 5</usr/share/man/man1/ssh.1.gz 6>/tmp/out6 # pretend need 5 and 6

ssh remote 'echo $$ >/tmp/pid; exec sleep 99999' <&5 >&6 &
sleep 1 # hack. need /tmp/pid to be set

ssh remote '
  pid=$(</tmp/pid) 
  exec 5</proc/$pid/fd/0 6>/proc/$pid/fd/1
  echo start
  gzip -d <&5 | man /dev/stdin >&6
  echo stop
  kill -hup $pid
'
wait
less /tmp/out6

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.