15
I have NGINX configured like this as a reverse proxy for http requests:

server {
    listen 80;
    server_name 203.0.113.2;

    proxy_set_header X-Real-IP  $remote_addr; # pass on real client IP

    location / {
        proxy_pass http://203.0.113.1:3000;
    }
}

I also want to proxy ssh (Port 22) requests. Can I add another server block like this to the same configuration file:

server {
    listen 22;
    server_name 203.0.113.2;

    proxy_set_header X-Real-IP  $remote_addr; # pass on real client IP

    location / {
        proxy_pass http://203.0.113.1:22;
    }
}

Such that the end result is this:

server {
    listen 80;
    server_name 203.0.113.2;

    proxy_set_header X-Real-IP  $remote_addr; # pass on real client IP

    location / {
        proxy_pass http://203.0.113.1:3000;
    }
}
server {
    listen 22;
    server_name 203.0.113.2;

    proxy_set_header X-Real-IP  $remote_addr; # pass on real client IP

    location / {
        proxy_pass http://203.0.113.1:22;
    }
}

TIA,
Ole

  • 2
    nginx is acting as a http proxy. If you set it to reverse proxy port 22 it won't allow you to pass SSH traffic - only http traffic to the SSH server, which will obviously fail. – garethTheRed Jun 16 '16 at 18:26
  • Go check out HAProxy. – user38810 Jul 4 '16 at 12:41
12

The ssh protocol is not based on HTTP, and, as such, cannot be proxied through the regular proxy_pass of ngx_http_proxy_module

However, recently, starting with nginx 1.9.0 (released as stable with 1.10.0 on 2016-04-26), nginx did gain support for doing TCP stream proxying, which means that if you have a recent-enough version of nginx, you can, in fact, proxy ssh connections with it (however, note that you wouldn't be able to add anything like the X-Real-IP to the proxied connection, as this is not based on HTTP).

For more information and examples, take a look at:

8

Since Nginx Version 1.9.0,NGINX support ngx_stream_core_module module, it should be enabled with the --with-stream. When stream module is enable they are possible to ssh protocol tcp proxy

stream {
    upstream ssh {
        server 192.168.1.12:22;
    }
        server {
        listen        12345;
        proxy_pass    ssh;

    }

}

https://www.nginx.com/resources/admin-guide/tcp-load-balancing/

  • That's all nice feature of nginx - but IMHO it's useless when you want to have real reverse proxy like nginx does perfect job for HTTP. The thing is streams approach is simple NAT - so I'd rather do that task on edge router. What I would want/like to have here - is exact same feature set as HTTP reverse proxy. In other words, I have only one public IP address - thus port 22 is avail only for one machine - but if there was a way to distinguish requests in a form ssh me@srv1.my.net and ssh me@srv2.my.net - it would be great. It's protocol limitation (SSH won't give out DNS name client uses) – stamster Jan 26 '18 at 18:40
  • @stamster, you can already do almost the same thing, by either using different port numbers (e.g., 122 for srv1 and 222 for srv2), or by using nested ssh sessions, where you first ssh into the public server/IP, and from there, ssh into the leaves; e.g., ssh user@example.org 'ssh user@192.168.5.1'. – cnst Oct 15 '18 at 15:33
  • 1
    No, the requirement/idea is to use default port (22 or any other service..) as destination port, and then to route traffic depending of DNS name or so. Just like we're all using nginx as a reverse web http proxy server, so each domain targets default ports 80, 443, and then nginx routes traffic depending on proxy rules. Of course client has HOST header so it's easy to distinguish which site it targets... Nested SSH sessions are sort of solution but a messy one - that works though. I ended up with different ports on our edge network - good old NAT as the most KISS and reliable solution. – stamster Oct 18 '18 at 10:17

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.