5

I have linux-based device (let's say a Raspberry Pi) that hosts a HTTP server. This device regularly changes WiFi access point and is often not publicly accessible due to NAT and/or firewall.

I want to setup a reverse ssh tunnel using a publicly available server (rpi.example.com below) such that rpi behind NAT establish a tunnel to rpi.example.com at boot. rpi.example.com will then forward any HTTP request to the rpi behind NAT.

Sequence diagram:

HTTP client       rpi.example.com     rpi behind NAT
     +                   +                   +
     |                   |       ssh -R      |
     |                   | <-----------------+
     |    GET /temp      |                   |
     +-----------------> |                   |
     |                   +-----------------> |
     |                   |   [SSH tunnel]    |
     |                   | <-----------------|
     |  HTTP/1.1 200 OK  |                   |
     | <-----------------+                   |
     |                   |                   |

How to setup a reverse SSH tunnel like that? Is there a better alternative?

  • I tried ssh -NR 8080:localhost:80 user@rpi.example.com from rpi behind NAT with AllowTcpForwarding yes on sshd_config of rpi.example.com. – DurandA Mar 14 '17 at 13:07
3

I think a VPN (e.g. openVPN or an IPSEC solution like strongswan) might work better.

You can absolutely use SSH, with the -R switch:

-R remote_socket:local_socket

Specifies that connections to the given TCP port or Unix socket on the remote (server) host are to be forwarded to the given host and port, or Unix socket, on the local side. This works by allocating a socket to listen to either a TCP port or to a Unix socket on the remote side. Whenever a connection is made to this port or Unix socket, the connection is forwarded over the secure channel, and a connection is made to either host port hostport, or local_socket, from the local machine.

You would just need something on your Pi to initiate the connection, and re-start it if it fails. The NAT here is irrelevant, because the tunnel would be directly between your public host and Pi - on your host, you would in effect have a listener (e.g. 127.0.0.1:9999), and would configure your webserver to use that listener as an upstream.

Most likely, you would want to have a dedicated user to create this forwarding (since your Pi would need to be able to authenticate to your server, which almost certainly means you would need a passwordless private key). You would also need to create one forwarded connection per port, if you ever needed more than one.

I suspect a VPN would be easier to make work reliably, and would require less scripting, essentially. Both approaches would work, though.

  • 3
    I made it using ssh -NR 8080:localhost:80 user@rpi.example.com. The trick is to add AllowTcpForwarding yes and GatewayPorts yes to sshd_config. I can then automate it using autossh. I also found this Gist to bind sub-domains with ssh tunnels using nginx. – DurandA Mar 14 '17 at 15:46

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.