25

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;
    }
}
2
  • 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. Jun 16, 2016 at 18:26
  • Go check out HAProxy.
    – user38810
    Jul 4, 2016 at 12:41

2 Answers 2

21

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:

15

Since Nginx Version 1.9.0,NGINX support ngx_stream_core_module module, it should be enabled with the --with-stream. When the stream module is enabled, it is possible to ssh protocol via a 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/

4
  • 1
    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 [email protected] and ssh [email protected] - it would be great. It's protocol limitation (SSH won't give out DNS name client uses)
    – stamster
    Jan 26, 2018 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 [email protected] 'ssh [email protected]'.
    – cnst
    Oct 15, 2018 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, 2018 at 10:17
  • @stamster maybe nginx could use the username, but you'd need a unique name for each server. This would be the equivalent to path-based http forwarding.
    – jiggunjer
    Apr 13, 2020 at 17:06

You must log in to answer this question.

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