I'm trying to set up an ssh tunnel layout where:

  1. client A (not ssh-server enabled) initiates ssh connection to server S
  2. socks server is opened on server S:yyyy that tunnels all data via client A
  3. client B connects socks server on server S, and tcp data routes via client A to the Internet

A possible solution would be to add a proxy server on Client A (binded to localhost:xxxx), and then run on client A ssh -R yyyy:localhost:xxxx Server. That would achieve the goal. But that's not as clean as using just ssh.

Is it possible to achieve this with just the ssh client on A and ssh-server on S? it's like reverse-dynamic-port-forwarding on ssh - creating ssh -D from A to S, and then somehow setup on this tunnel a second tunnel of ssh -D from S to A. Somewhat confusing, and not sure if possible.

  • Up to OpenSSH-6.7 I don't think it can be done simply, native socks proxy support works only in the direction ssh->sshd. – mr.spuratic Jan 15 '15 at 14:43

OpenSSH 7.6 introduced reverse dynamic proxy as a native option. It is implemented entirely in the client, so the server does not need to be updated.

ssh -R 1080 server
  • But you still need the SOCKS server, otherwise you just have a reverse tunnel... – David Tonhofer Dec 19 '18 at 19:54
  • 1
    -R isn't dynamic, -D is – OrangeDog Feb 20 '19 at 15:51
  • 9
    Previous comments are incorrect. Had they taken the time to read the release notes provided for OpenSSH 7.6 they would see the the -R flag was updated to also provide reverse dynamic SOCKS. * ssh(1): add support for reverse dynamic forwarding. In this mode, ssh will act as a SOCKS4/5 proxy and forward connections to destinations requested by the remote SOCKS client. This mode is requested using extended syntax for the -R and RemoteForward options and, because it is implemented solely at the client, does not require the server be updated to be supported – NeoVance Mar 14 '19 at 8:17
  • is there a way to do this in th ~/.ssh/config file? – CaffeineAddiction Jul 18 '19 at 20:27

I was just searching for this and came across the same (or similar) question on stack overflow.

On client A ssh -R \*:24680:localhost:12345 serverS and then (still on client A) ssh -D 12345 localhost [1]

You need to the \* bit so it will bind to server S's public IP address and not just localhost.

Then on client B simply connect to the socks server at serverS:24680

[1] EDIT: I just realized that this won't work if client A doesn't have SSH Server because it can't ssh itself. I was thinking of a setup where client A had an SSH Server but was not accessible by Server S. But a similar setup could still work if you can install a socks server on client A and open it on port 12345.

  • It works, great – diyism Dec 16 '15 at 4:57

Don't know whether this helps anyone, here is a diagram for my setup that I managed to construct...

SSH reverse tunnel with SOCKS proxying

You will see two processes on MACHINE_B:

The SSH client connection to MACHINE_A (olive):

ssh -R -i privkey.sshkey -N user_a@machine_a

The SSH client working as SOCKS server on port 4444 (dark green):

ssh -D localhost:4444 -N user_c@localhost

And one processes on MACHINE_A, the one playing server listening on port 22344 (olive).

The light green process on MACHINE_B should appear when the light green process on MACHINE_A asks for a connection...


This is quite straightforward.

On local side (Server S), start your openssh server server. This will start ssh server by default on port 22 - you could change this port in /etc/ssh/sshd_config file, if necessary.

 service ssh start

On remote side (Client A), start a socks proxy AND set a remote port on the local side to connect to the socks proxy.

 ssh -N -D -p 22 <server-s>
 ssh -N -R 2222: -p 22 <server-s>

On local side (Server S), use socks proxy setup on port 2222 via e.g. to connect to Google.

 curl --socks5 https://www.google.com
  • Unfortunately this solution won't work. The Google page might appear, but that's only because you'll be accessing it through Server S; not Client A. You can verify this by launching curlon httpbin.org or icanhazip.com or api.ipify.org instead. Traffic will be routed through the local socks proxy, which essentially sends it to Server S again -- the initial purpose of -D. – AlexandreH Oct 23 '17 at 22:28
  • Indeed the "ssh -D" process must not connect to the SSH server on server-s but must connect to an SSH server on Client A. – David Tonhofer Dec 19 '18 at 20:01

There is a replacement for ssh for this purpose called ssf that allows reverse dynamic socks to be created with the -F flag.

The SSF client -F port option opens the given port on the SSF target server machine and forward SOCKS requests to the SSF client. The SSF client will act as the SOCKS server.


Assuming you have ssfd installed on the remote and ssf on the local you can set this up using ssh like so.

ssh -o"LocalCommand=ssf -F 1234 -p 10000 server" -f user@server ssfd -p 10000

This will allow the use of SOCKS on port 1234 on the remote server to access the internet through the client machine.

  • 1
    If you have OpenSSH 7.6+ client version or can install it Elad's answer is better. – NeoVance Mar 14 '19 at 8:21

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.