I'm trying to understand how ProxyCommand works,

%> ssh -oProxyCommand='ls' root@ubuntu
ssh_exchange_identification: Connection closed by remote host

%> ssh -oProxyCommand='useradd' root@ubuntu
/bin/bash: line 0: exec: useradd: not found
ssh_exchange_identification: Connection closed by remote host

I also tried builtin commands like env, but it also has no output.

Any ideas, why can't I execute arbitrary command?


I know I can execute command like ssh host $command, I'm just trying to figure out why ProxyCommand can't just run any command, don't really know why people down vote it.


The ProxyCommand option is not an arbitrary command to run on a remote system, but a command for proxying some stream of data. From the manual page for ssh_config (emphasis added):


Specifies the command to use to connect to the server. The command string extends to the end of the line, and is executed using the user's shell ‘exec’ directive to avoid a lingering shell process.

In the command string, any occurrence of ‘%h’ will be substituted by the host name to connect, ‘%p’ by the port, and ‘%r’ by the remote user name. The command can be basically anything, and should read from its standard input and write to its standard output. It should eventually connect an sshd(8) server running on some machine, or execute sshd -i somewhere.

If you simply want to run a command on a remote system, provide it at the end of the ssh command line, as

ssh root@ubuntu ls

The ProxyCommand you specify is not executed on the remote host. It is run on the local (client) side as an alternative connection method to opening a TCP connection (typically port 22) to the remote host. The executable run by ProxyCommand is expected to communicate with the local ssh client through stdout and stdin as a proxy to the socket's own recv() and send(), but otherwise should behave from the client's perspective as a byte for byte replacement of a TCP session to an actual ssh server.

Typically the usage of ProxyCommand is to setup a ssh tunnel through one server to connect to a secondary server that otherwise would not be able to establish a direct connection. Using the ssh client with a netcat (nc) command can accomplish this, where netcat handles the linking of stdout to send() on the socket side, and stdin to recv().

When you invoke a ProxyCommand that does not establish stdout and stdin to match what the SSH protocol expects in order to negotiate a proper SSH transport, the client bails out with the error: ssh_exchange_identification: Connection closed by remote host.

If what you actually intend is for the command to be executed on the remote host after the ssh session is established and authenticated, you can include it at the end of the ssh command line (without ProxyCommand) and the ssh client will invoke that command on the remote host, instead of an interactive shell.

Try ssh root@ubuntu ls instead.

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.