1

I have two machines, m1 and m2, and machine m2 can connect to m1 using SSH. There is a machine m1bis that can only connect to m1, and there is a machine m2bis to which only m2 can connect. I would like to make it possible for m1bis to reach machine m2bis on some port q, by connecting to some port p of machine m1. Let's say that both p and q are unprivileged ports, i.e., they are greater than 1024. In pictures:

+-------+   q   +----+   SSH   +----+   p   +-------+
| m1bis | ----> | m1 | <------ | m2 | ----> | m2bis |
+-------+       +----+         +----+       +-------+

I have shell access to m1 and m2. The usual way I would do this would be with an SSH reverse port forwards, by running the following on m2:

ssh -R *:q:m2bis:p m1

This makes the SSH daemon on m1 listen on port q on all interfaces, and relay any incoming connections to port p of machine m2bis. That way, when m1bis connects to port q of machine m1, the connection is routed by SSH from m1 to m2, and the connection actually happens on port p of machine m2bis. So far, so good.

The problem is that this requires the setting GatewayPorts=yes to be enabled in the SSH server configuration on m1. However, it is not enabled, and I am not root on m1 so I cannot enable it.

However, it seems to me like there's nothing really preventing me from working around this and doing my port forwarding nevertheless: I have shell access to m1, I can have an SSH connection between m1 and m2, I can run a process on m1 that listens on port q on all interfaces (instead of having the SSH daemon do the listening) and that routes the connection through SSH. So essentially I have all necessary permissions to build my own port forward.

Can I actually do this, and is there an easy way to do it?

Additional requirements:

  • As I'm not root on m1, I'd prefer a solution without complicated dependencies, ideally some bash script with common utilities like netcat, socat, etc., or some self-contained C program.
  • I'm root on m2, if it helps (but in principle I don't think I should need this either).
  • I do not trust the connection between m1 and m2, so the forwarding should be encrypted between m1 and m2 (i.e., it should really go over SSH).
5

A solution that works fine is to run your own SSH daemon on m1, which is doable without root. Here's how to run the SSH daemon while being a normal user.

First generate the host keys:

ssh-keygen -f test_host_rsa -N  '' -t rsa
ssh-keygen -f test_host_dsa -N  '' -t dsa
ssh-keygen -f test_host_ed25519 -N  '' -t ed25519

Then write a config file for your sshd, where 2222 is some unprivileged port which is not used on m1 and to which m2 can connect, and where you need also to indicate the absolute path to the current folder:

cat >sshd_config <<EOF
Port 2222
HostKey /folder/where/the/files/are/test_host_rsa
HostKey /folder/where/the/files/are/test_host_dsa
HostKey /folder/where/the/files/are/test_host_ed25519
GatewayPorts yes

Now run your SSH daemon:

/usr/sbin/sshd -f sshd_config

Now, m2 can connect to port 2222 of m1 and run the reverse port forward because GatewayPorts is enabled on your SSH daemon. In other words, on m2 you can run:

ssh -p 2222 -R *:q:m2bis:p m1
2

A friend suggested another solution: if the socat command is installed on m1, you can do the SSH reverse port forward while listening on the loopback address, on some port q2, i.e., running the following on m2:

ssh -R q2:m2bis:p m1

And use socat on m1 as follows, which will redirect incoming connections on port q to the port forwarding which is listening on the loopback address:

socat tcp-listen:q,reuseaddr,fork tcp:localhost:q2

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.