I have a server in my home network (cannot port forward) and a VPS on the WAN. I need requests on a certain port, to, not from, the VPS to be forwarded to my home server. I have an SSH tunnel which works fine if I send the request to localhost on VPS. However I want requests forwarded to VPS's localhost from internet be sent to my home server through the tunnel. And it needs to be bi-directional.

I have seen this question, however it doesn't work for me. It is quite possible that I did something incorrectly.

My exact procedure:
On server a, my home server, I ran this command to set up the tunnel:

ssh -v -N -R 2222:localhost:22 [email protected]

I ran the following command on server b (VPS):

iptables -t nat -A PREROUTING -p tcp --dport 2223 -j DNAT --to-destination

And tried to ssh from another machine:

ssh [email protected] -p 2223

I set GatewayPorts yes in sshd_config however I am still finding the same problem:
ssh: connect to host server-b.com port 2223: Connection refused.

  • 1
    It would be useful documenting in your own post exactly what was done Mar 3, 2019 at 13:32
  • You might want to look at the GatewayPorts setting on the VPS server sshd_config. This can allow the remote port 2222 to bind to all IP addresses and so be visible without NATting. Mar 3, 2019 at 16:39
  • @StephenHarris I'll check that out. Thanks
    – Jachdich
    Mar 3, 2019 at 17:05
  • @StephenHarris sorry for the inactivity but it didn't work. I set GatewayPorts to yes however it is still not functioning.
    – Jachdich
    Mar 8, 2019 at 18:46

1 Answer 1


Set GatewayPorts yes and AllowTcpForwarding yes in sshd_config on server b. With GatewayPorts clientspecified explicitly mention IP or * on server a to create reverse tunnel. So that sshd on server b accepts connections from public too:

ssh -NTR *:2222:localhost:22 [email protected]

Otherwise sshd listens on loopback interface only as is the case with GatewayPorts no.

Now ssh from another machine to port 2222:

ssh [email protected] -p 2222

You'll be logged in to server a after authentication.
No need to set up iptables forwarding. Btw, avoid user root for remote logins, if possible.

If you don't want to set GatewayPorts option, then you need to forward traffic from some other port, say 2223, to localhost:2222.

  • This can be done with iptables on server b:

    iptables -t nat -I PREROUTING -p tcp -m tcp --dport 2223 -j DNAT --to-destination

    * REDIRECT works only for same interface

    But routing to loopback interface isn't allowed unless:

    echo 1 | sudo tee /proc/sys/net/ipv4/conf/all/route_localnet

    Now ssh from another machine to port 2223:

    ssh [email protected] -p 2223

Another option is to setup some minimal local forwarding server from port 2223 to 2222 using tools like ssh, socat, netcat, *inetd etc.

  • On server b, with socat:

    socat TCP-LISTEN:2223,fork TCP:
  • Or with netcat:

    nc -l -p 2223 -c "nc 2222"
  • Or with ssh:

    ssh -4gfNTL 2223:localhost:2222 localhost

Any of the above can be combined with reverse tunnel to do a double forwarding from server a in a single step:

ssh -TR *:2222:localhost:22 [email protected] "ssh -4gfNTL 2223:localhost:2222 localhost"
  • Thanks, I shall try this soon. About root, I've just been too lazy to make a normal user account. Probably should do that soon.
    – Jachdich
    Mar 25, 2019 at 6:36
  • OH MY GOD IT WORKS! I cannot thank you enough. I've been searching for this for months and it is everything I need. Thanks again
    – Jachdich
    Mar 25, 2019 at 18:08
  • You are welcome. I have extended the answer to include other possible options, including iptables if you want to go for that. Mar 25, 2019 at 21:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .