Accessing localhost web server via reverse SSH tunnel and URL

networkingsshtunnel

I have a web server running on a local machine and it is easily accessible to all machines on the LAN. I also have a remote server with a public IP address/URL pointing to it (example.com). I cannot access my local server from outside of my network because I'm stuck behind my ISP's NAT (they won't grant public IP or port forward anything), so I'm trying to configure a reverse SSH tunnel to grant public access.

I am running ssh -R 8080:localhost:80 jemeadows@example.com -i $SSH_KEY -N on the local server to try to create the tunnel.

Using eLinks on the remote server, I can access 127.0.0.1:8080, and it correctly displays the sites on the local server. However, visiting example.com:8080 in the browser does not show anything. I've tried using local port forwarding to redirect incoming traffic to 127.0.0.1:8080 but that doesn't work. Any other ideas to redirect incoming traffic from a web browser into my SSH tunnel?

Best Answer

-R 8080:localhost:80 is usually not enough. See man 1 ssh [emphasis mine]:

-R [bind_address:]port:host:hostport
[…]

Specifies that connections to the given TCP port or Unix socket on the remote (server) host are to be forwarded to the local side.

[…]

By default, TCP listening sockets on the server will be bound to the loopback interface only. This may be overridden by specifying a bind_address. An empty bind_address, or the address *, indicates that the remote socket should listen on all interfaces. Specifying a remote bind_address will only succeed if the server's GatewayPorts option is enabled (see sshd_config(5)).

Your tries with 127.0.0.1:8080 on the server indicate the listening socket is bound to the loopback interface. Most likely it is not bound to any other interface.

You need to explicitly specify bind_address or to use * or to use an empty string as bind_address. The option with an empty bind_address looks like this (note the leading :):

-R :8080:localhost:80

Additionally the state of GatewayPorts in the sshd_config on the server is important. From man 5 sshd_config:

GatewayPorts

Specifies whether remote hosts are allowed to connect to ports forwarded for the client. By default, sshd(8) binds remote port forwardings to the loopback address. This prevents other remote hosts from connecting to forwarded ports. GatewayPorts can be used to specify that sshd should allow remote port forwardings to bind to non-loopback addresses, thus allowing other hosts to connect. The argument may be no to force remote port forwardings to be available to the local host only, yes to force remote port forwardings to bind to the wildcard address, or clientspecified to allow the client to select the address to which the forwarding is bound. The default is no.

To achieve what you want the option must not be no. Note no is the default value, so unspecified GatewayPorts still means no. The value of yes will make -R 8080:localhost:80 work like -R :8080:localhost:80.

I advise GatewayPorts clientspecified in the server config and ssh -R :8080:localhost:80 … on the client.


Possible additional problems:

Related Question