2

Normally there is an SSH client that connects to an SSH server. The client then places commands that are executed on the server. Now, is there a way to do it the other way around? So that the client connects to the server, but the server also connects to the client and is able to execute commands on the client. Is that possible?

The reason I am looking for this is that I have two servers (A and B) in two different networks, both networks connected to the Internet. Server A can be accessed through port forwarding, but server B cannot. Since server A does all the work I'd like server B to connect to server A and just do whatever server A wants it to do.

Are reverse connections like this possible? Or maybe bidirectional SSH connections?

EDIT:

As an example I'd like to do the following. Being on server A and knowing that server B is SSH-connected to me, I'd like to connect to connect to server B and place a command like

echo "This is test content." > /home/myuser/mytestfile`

After that I'd like to find a file

/home/myuser/mytestfile

in server B.

8
  • 1
    Could you add a bit more details on what kind of commands you want to run? Should it be an interactive login or some automated process? In principle you should be able to do everything using ssh (reverse) port forwarding (options -L and -R for ssh) May 4, 2018 at 10:42
  • @SebastianStark Edited the posting.
    – Socrates
    May 4, 2018 at 10:48
  • @SebastianStark Do you have an example syntax for -L and -R?
    – Socrates
    May 4, 2018 at 10:49
  • 1
  • 1
    I don't understand. If you are on serverA and want to run a command on serverB, then you can do ssh serverB echo "This is test content." > /home/myuser/mytestfile. The mytesfile will be created on serverA but the command will be run on serverB. Isn't that what you want?
    – terdon
    May 4, 2018 at 11:35

1 Answer 1

2

As @terdon said you can use the following command to execute something on the remote server through SSH and save (redirect) the output to the local instance:

UserA@HostA:~$  ssh UserB@HostB ls ~ > /home/UserA/ls-of-home-UserB.txt

Also you can use the following command to execute something on the local instance and pipe the output to the remote server and save it by the command tee:

UserA@HostA:~$  ls ~ | ssh UserB@HostB tee /home/UserB/ls-of-home-UserA.txt

I'm agree with @Sebastian Stark you are probably asking how to create revers tunnel with SSH port forwarding. The SSH connection allows to bind port on the remote server to port on the local by using the option -R. And vice versa you can bind local port to remote port by -L.

In your case should be applied the first scenario by using the option -R:

UserA@HostA:~$  ssh UserB@HostB -R 2222:localhost:22

This command will establish connection from HostA to HostB as usual and will bind port 2222 on HostB to port 22 on the loopback interface on HostA. That means when you request something on port 2222 on HostB the request will be handled by the service that listen on port 22 on HostA, usually this is the SSH server. At this point you could be able to use some of the following commands to connect back from HostB to HostA:

UserB@HostB:~$  ssh UserA@HostB -p 2222
UserB@HostB:~$  ssh UserA@localhost -p 2222

Or you can use the above commands, for example:

UserB@HostB:~$  ls ~ | ssh UserA@localhost -p 2222 tee /home/UserA/ls-of-home-UserB.txt

Note you should have installed SSH server on HostA!


One interesting usage is that you can bind remote port on HostB to port on other instance in the local network of HostA:

UserA@HostA:~$  ssh UserB@HostB -fTN -R 3389:192.168.100.115:3389

Where 192.168.100.115 is the IP address on any Windows computer in the LAN of HostA, let's call it HostC. The options -fTN will push the ssh connection into the background and you will have just a tunnel from HostB:3389 through HostA to HostC:3389.


I'm using this by combination with autossh to keep the connection alive. For example I have the next line in my crontab:

@reboot sleep 15 && autossh remote-server-with-public-ip -fTN

Where remote-server-with-public-ip is a Host defined in my ~/.ssh/config file on HostA:

Host remote-server-with-public-ip
    HostName hostB
    IdentityFile ~/.ssh/hostB/id_rsa
    User userB
    Port 22
    RemoteForward 2223 127.0.0.1:22
    RemoteForward 8080 127.0.0.1:80
    RemoteForward 6900 127.0.0.1:5900
    RemoteForward 3389 192.168.100.115:3389

The ports 2223, 6900, 3389 on HostB are not public and I can access them only through another SSH connection - for example from HostD that is somewhere on Internet. But to access 8080 I'm using Apache with reverse proxy on HostB :-) and the virtual host's configuration file looks as this:

<VirtualHost _default_:443>

    ServerName forward.example.com
    # Other configuration directives

    SSLEngine on
    # SSL certificate files

    ProxyRequests Off
    <Proxy *>
        Order deny,allow
        Allow from all
    </Proxy>

    ProxyPass "/"  "http://localhost:8080/"
    ProxyPassReverse "/"  "http://localhost:8080/"

    <Location />
        Order allow,deny
        Allow from all
    </Location>

</VirtualHost>
  • The Apache's modules proxy and proxy_http are required.

Further reading:

1
  • Thanks for this extensive answer. Quite a few options. And I must admit, that I was quite surprised about the possibility to bind another local host to the remote host using -fTN. Although, killing that connection is a bit tricky. I solved it a bit dirty using sudo pkill ssh. Apparently there is an ssh -S option, but I coudn't get it to work. It asks for some socket I don't know where to get from. As for me, the answer to my matter is the ssh -R, binding a port on the remote host (2222) to myself (22).
    – Socrates
    May 4, 2018 at 22:32

Not the answer you're looking for? Browse other questions tagged or ask your own question.