Feature proposal: ProxyUseFdpass-like behavior for a regular ssh session

Spencer Baugh sbaugh at catern.com
Thu May 27 10:43:56 AEST 2021

Peter Stuge <peter at stuge.se> writes:
> Spencer Baugh wrote:
>> In short, I'd like to implement a mode for running an ssh session which
>> functions like ProxyCommand+ProxyUseFdpass: the specified command is
>> passed a socketpair, and is then expected to pass out a file descriptor;
>> IO from the client will then be forwarded to and from that file
>> descriptor.
>> This is similar to -W, except that instead of forwarding stdin to a
>> socket connected to a specified host and port, stdin is forwarded to an
>> arbitrary file descriptor as passed out by the command.
> So you know that ProxyCommand executes on the client before the session
> starts while -W opens a "direct-tcpip" channel inside the session making
> the peer sshd create a TCP connection to the -W host and port parameters,
> right?
> To me, these two don't compare at all well.
> Since "direct-tcpip" is a standardized channel type it's reasonable
> to expect widespread support in servers and -W/-J work widely.

Yes - -W and ProxyCommand are completely different things. I only
mentioned ProxyCommand because the protocol that ProxyUseFdpass is the
same protocol I'm proposing here. Other than that, ProxyCommand is
completely unrelated and irrelevant to what I'm proposing.

>> I'm not an expert on the SSH protocol, but I believe this would require
>> a protocol change; a new @openssh.com channel type, perhaps called
>> fdpass at openssh.com.
> If you want sshd itself to implement this then yes.
> But couldn't you achieve what you want with a subsystem configured in
> existing sshd_config and invoked through ssh -s on clients?

Maybe I'm totally confused about subsystems, but isn't a subsystem
invoked in the same way as any command? i.e., sshd creates some pipes
and passes them into the subsystem - same as with a user-specified

There's no way to (AFAIK) define a subsystem such that:
1. sshd will run the subsystem with a Unix domain socketpair
2. the subsystem will send a fd over that socketpair
3. sshd will receive a fd from the socketpair (with mm_receive_fd)
4. sshd then forward data on that channel to and from that fd.

That's necessary to avoid the overhead of the subsystem process reading
data from the sshd-created pipes and just copying it over to another fd,
adding extra copies and userspace transitions for no benefit.

For example, if the subsystem or command was to make a network
connection, then the process running for the subsystem would be
pointless extra overhead after the connection is established. That
overhead can be eliminated by passing the fd out with the protocol
described above (which is also the protocol that ProxyUseFdpass uses).

>> - -W-style socket forwarding for AF_UNIX and other socket families.
>> This is useful for, among other things, accessing remote daemons
>> without extra overhead.
> Which software is AF_UNIX client in that use case?

nc -F -U
(well, ignoring the fact that BSD nc doesn't actually support -F and -U
being used together)
Or, a simple Python script which does the same thing.

> Do you envision the original daemon client utility transparently using
> the SSH channel? If so, how?

I'm not sure what you mean by this, but no, I don't (think I) envision

>> - More customization of AF_INET socket parameters for -W, including
>> customization of the source address. This could be achieved with an
>> invocation of "ssh -XXX nc -f -s". (I see this was
>> coincidentally requested on this list a few weeks ago)
> Right, direct-tcpip doesn't permit the client to dictate what address
> the sshd TCP client binds to for the outgoing connection.

Indeed, and my suggestion does permit that.

>> - Implementation of other more dynamic forwarding modes, without added
>> overhead, and without requiring OpenSSH to support them. As a concrete
>> example, I'd like to use TCP forwarding like -L, but with a listening
>> socket pre-created by the user and passed in to ssh; this is useful when
>> using chroot/container/network namespacing features, where ssh might be
>> running in a separate container from the listening socket. This could be
>> achieved with minimal overhead by a simple user-written script which
>> accepts connections on the listening socket and runs "ssh -XXX nc -f
>> 1234" for each connection.
> How is the socket passed out of the container/namespace? In a pipe? Which?

There are a number of ways to get sockets/file descriptors out of a
container - basic file descriptor passing over Unix domain sockets is
one way (note that this is completely unrelated to my suggestion of
using this in ssh), and another is using setns(2) on Linux.

>> - In general, zero-extra-overhead usage of SSH channels. With this
>> fd-passing behavior, the user is able to determine the file descriptors
>> used by OpenSSH on both sides, and OpenSSH simply forwards data from the
>> user-controlled file descriptors on one side to the other side.
>> Zero-overhead access to SSH channels like this has many uses in
>> application programming.
> Is this also a subsystem candidate?
>> user-controlled minimal-overhead access to SSH channels
> A subsystem is pretty much that..?

A subsystem is run with file descriptors created by sshd; see my
description above ("That's necessary to avoid the overhead...") for why
that's insufficient.

>> which are maintained by OpenSSH
> What does that actually mean?

I mean as opposed to writing their own ssh client, which I don't think
should be necessary just to get low-overhead access to SSH channels.

>> without the user having to implement the SSH protocol.
> Hm, why would they have to?

Well, this is probably very obscure, but one could avoid a lot of the
work in writing an ssh client by using MUX_C_PROXY with OpenSSH. I
wanted to pre-empt any suggestion of that.

> I'm sorry - as you can tell I'm pretty confused. Can you help me out?

Yes, that's understandable. Hopefully my explanation clarifies a bit?
Again, ProxyCommand has nothing to do with my suggestion, except in that
ProxyUseFdpass has some functionality/speaks a protocol that I want to
also use in another part of OpenSSH.

More information about the openssh-unix-dev mailing list