Nginx – Reverse SSH Tunnel

iptablesnginxsshssh-tunneltunneling

I am trying to forward web traffic from a remote server to my local machine in order to test out some API integration (tropo, paypal, etc). Basically, I'm trying to setup something similar to what tunnlr.com provides.

I've initiated the ssh tunnel with the command

$ssh –nNT –R :7777:localhost:5000 user@server

Then I can see that server is now listening on port 7777 with

user@server:$netstat -ant | grep 7777

tcp        0      0 127.0.0.1:7777          0.0.0.0:*               LISTEN     
tcp6       0      0 ::1:7777                :::*                    LISTEN  


$user@server:curl localhost:7777
Hello from local machine

So that works fine. The curl request is actually served from the local machine.

Now, how do I enable server.com:8888 to be routed through that tunnel?

I've tried using nginx like so:

upstream tunnel {
    server 0.0.0.0:7777;
}
server {
  listen 8888;
  server_name server.com;
  location / {
    access_log /var/log/nginx/tunnel-access.log;
    error_log /var/log/nginx/tunnel-error.log;
    proxy_pass http://tunnel;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_redirect off;
  }
}

From the nginx error log I see:

[error] 11389#0: *1 connect() failed (111: Connection refused)

I've been looking at trying to use iptables, but haven't made any progress. iptables seems like a more elegant solution than running nginx just for tunneling. Any help is greatly appreciated. Thanks!

EDIT (adding server info)

Server details: Ubuntu 10.10 maverick (standard install)

EDIT (nginx option)

The nginx options worked by changed 0.0.0.0:7777 to 127.0.0.1:7777 as @Marcel G suggested. Still looking for non-nginx solution though.

EDIT (update on final solution)

As @sciurus pointed out, make sure that GatewayPorts yes in your sshd_config file. I initially had this line in the config file, but I needed to issue a /etc/init.d/ssh reload instead of restart (at least it seems that way on ubuntu).

Final command used on the local machine:
ssh -nNT -R '*:8888:localhost:5000' user@server

Then the server should indicate it is listening on *:8888 with lsof -i tcp:888

user@server:~$ sudo lsof -i tcp:8888
COMMAND   PID     USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
sshd    14711 user    8u  IPv4 1791013      0t0  TCP *:8888 (LISTEN)
sshd    14711 user    9u  IPv6 1791014      0t0  TCP *:8888 (LISTEN)

Best Answer

There is no need to use nginx.

In your ssh daemon configuration (it should be /etc/ssh/sshd_config) set GatewayPorts to clientspecified and reload it. This is necessary for other systems to be able to connect to your tunnel. Without it, only programs running on your server will be able to use it.

Now all you need to do is modify your ssh command to listen on port 8888 instead of port 7777. This could look like

ssh -nNT -R '*:8888:localhost:5000' user@server

The asterisk tells sshd to listen to port 8888 on all interfaces, rather than just the loopback interface. This would fail if you haven't changed GatewayPorts.