Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!


Nginx: proxy forwarding other ports than 80 (e.g. 22)
New on LowEndTalk? Please Register and read our Community Rules.

All new Registrations are manually reviewed and approved, so a short delay after registration may occur before your account becomes active.

Nginx: proxy forwarding other ports than 80 (e.g. 22)

jvnadrjvnadr Member
edited September 2015 in Help

Need some help:
Is it possible to use nginx as proxy forwarding for NAT vps, to other ports than 80? For example, is it possible to configure in sites-enabled, a route that listens to port 22 for specific domain (e.g. example.com) and forwards it to an internal ip (e.g. 192.168.1.50)?
How can this be done without conflicting with ssh listening server on the main node? (getting error nginx: [emerg] bind() to 0.0.0.0:22 failed (98: Address already in use) )
Or mail ports to be used as a normal mail server to a NAT vps.

Thank you

Comments

  • One port, one listening socket.

  • jvnadrjvnadr Member
    edited September 2015

    @deadbeef Yes, but how to use ports that are already used by the host node? Port 22 is being used for ssh the main node and port 25, for example, for the main mail service of the node. What if I want nginx listen to those ports only to forward any request to a specific domain (that is what I want to do)

  • Unless you stop the ssh server from listening to 22, nginx can not listen to it at the same time. Perhaps I am misunderstanding what you are saying.

  • @deadbeef No, that's what I'm asking. If there is a way nginx listens for a port only for specific domain requests. So, only way is to do that is changing ssh port to the main node (something that in any case should be done), so, port 22 is free to be forwarded by nginx to the virtual machines. Is that right?

  • Ah, no. Nginx listens to a port and then based on rules (one of which the server name) does or doesn't do something with a given connection. It can't forward that connection to ssh/mail as far as I know.

  • @deadbeef So, is there a way to forward ports for ssh/mail to a virtual machine by domain request to the main note? I mean, as example.com is redirecting to the internal ip 192.168.1.50 from port 80 to port 80, the same way a ssh request to example com redirecting this request to the internal ip and port 22?

  • mikhomikho Member, Host Rep

    Haproxy?

    Thanked by 1deadbeef
  • perennateperennate Member, Host Rep
    edited September 2015

    Not possible.

    http://serverfault.com/questions/34552/is-there-a-name-based-virtual-host-ssh-reverse-proxy

    It says hostname used by client to connect is not sent in the SSH protocol.

    As suggested in the link above, what you could do is give them a username/password (or keypair) to login to a locked down shell (ideally not full OpenSSH server) in a gateway server from which they can login to their VPS on the internal interface. If you do it well, you can even make it make the connection to internal VPS automatically.

    Thanked by 1ucxo
  • @mikho said:
    Haproxy?

    +1

  • mikho said: Haproxy?

    I am not familiar at all with haproxy, but I should definitely start searching it a bit!

  • perennateperennate Member, Host Rep

    The section relevant to SSH is just this:

    backend foo_bk_ssh
            mode tcp
            option tcplog
    
            # add a nice, long timeout
            # (so that the ssh client doesn't get disconnected every few minutes)
            timeout server 2h
            server foo_srv_ssh 127.0.0.1:22

    So it's just passing SSH connections to a single SSH server.

  • mikhomikho Member, Host Rep

    Dispatching connections to different backends depending on the hostname which the client connected to is impossible to do on the TCP layer.

    Sorry, was thinking of a regular HTTP connection.

  • ClouviderClouvider Member, Patron Provider

    Or iptables forwarding perhaps.

    Thanked by 1doghouch
  • jvnadrjvnadr Member
    edited September 2015

    Clouvider said: Or iptables forwarding perhaps.

    I would like this be done via domain name, not ip tables (I already forward ports to the internal virtual machine).

  • perennate said: Not possible

    So, nginx cannot forward ssh packets only, or it can only forward http/https requests? I mean, can nginx forward mail ports (like 25 etc.) ot it cannot, just like cannot forward ssh port?

  • perennateperennate Member, Host Rep
    edited September 2015

    jvnadr said: So, nginx cannot forward ssh packets only, or it can only forward http/https requests? I mean, can nginx forward mail ports (like 25 etc.) ot it cannot, just like cannot forward ssh port?

    What do you mean? It can certainly forward SSH packets using its TCP mode, however SSH protocol does not include transfer of the hostname so it can't sniff the packets to determine which host the connection should go to. The alternative would be to set up the gateway server as mentioned in the Server Fault discussion I linked.

    As suggested in the link above, what you could do is give them a username/password (or keypair) to login to a locked down shell (ideally not full OpenSSH server) in a gateway server from which they can login to their VPS on the internal interface. If you do it well, you can even make it make the connection to internal VPS automatically.

  • perennate said: What do you mean?

    I got that. I'm asking if this can be done with nginx proxy for ports that are be used for mail. Having a virtual machine with the domain name example.com and use nginx proxy to configure a mail server that is working with the domain name, because it's ip is internal (e.g. 192.168.1.50). So incoming and outcoming mails using domain and packets are forwarded correctly to the virtual machine by nginx.
    I don't know If I am clear, but I tried! :)

  • perennateperennate Member, Host Rep
    edited September 2015

    jvnadr said: I got that. I'm asking if this can be done with nginx proxy for ports that are be used for mail. Having a virtual machine with the domain name example.com and use nginx proxy to configure a mail server that is working with the domain name, because it's ip is internal (e.g. 192.168.1.50). So incoming and outcoming mails using domain and packets are forwarded correctly to the virtual machine by nginx.

    SMTP with haproxy isn't possible either, the host sends data before the client. Of course SMTP is designed to allow relays, all you need to do is set up Postfix/exim/other mail server on the external IP and configure it to relay based on the recipient domain to various IPs.

    In Postfix, you can do this by setting relay_domains to the list of domains, and include transport map that has each domain name mapping to relay:[intenal ip].

    Thanked by 1jvnadr
  • Postfix and SMTP is possible - and they are even a perfect team using the PROXY protocol.
    I wrote about it in my personal blog: https://goo.gl/AqyLgm (This is a Google tanslated version, the original article is written in German, sorry).

    Moreover Nginx can act as a TCP proxy with a plugin: https://goo.gl/OtC8Ze - works great (had no problems with load-balancing multiple IMAP instances).

    Whatever... what you want is simple DNAT'ing. But: You cannot use a TCP proxy with SNI (server name indication). Both act on different layers. When you get to know the server name, you passed the TCP relevant layers already. You can use Guacamole or something like that to "proxy" a SSH server. I do not recommend it anyway...

    Thanked by 2deadbeef jvnadr
  • what you want: two servers listening on the same port on the same IP and forwarding based on hostname is possible only for HTTP and HTTPS as far as I know. So, no, you can't do this. Simple solution is to assign more IPs on your host.

  • BochiBochi Member
    edited September 2015

    This pretty much reminds of this: http://www.lowendtalk.com/discussion/comment/1165606/ :D
    And I think this is quite related to this use case...

  • If you're looking to forward/proxy a general TCP port (i.e, SSH, SMTP, etc) to another server, there's a nginx_tcp_proxy module that can do it. https://github.com/yaoweibin/nginx_tcp_proxy_module

    If you are looking for bind http and other services on the same ip:port, the answer is no, at least not with nginx.

    Thanked by 1jvnadr
  • @jvnadr What I think you are really looking for here, if I understand what your needing, is sslh. Sslh accepts connections on specified ports, and forwards them further based on tests performed on the first data packet sent by the remote client. Sslh acts as a protocol demultiplexer, or a switchboard. Its name comes from its original function to serve SSH and HTTPS on the same port.

    Though I am not sure if this would allow you to have the same ssh port for all vms, but it would allow you to run more than one service on a single port, as in https and openvpn or smtp or ssh, etc.

    Hope this helps.

    Cheers!

    Thanked by 2jvnadr mikho
  • doghouchdoghouch Member
    edited September 2015

    @Clouvider said:
    Or iptables forwarding perhaps.

    Let me help with that:

    iptables -t nat -A PREROUTING -d (other IP):22 dport 22 -j DNAT --to-destination 192.168.1.50
    
    iptables -t nat -A POSTROUTING -o venet0 -j MASQUERADE
    
    service iptables save
    

    You get the idea (if you're not using OpenVZ, change the ethernet adapter accordingly) :)

  • jvnadrjvnadr Member
    edited September 2015

    doghouch said: Let me help with that:

    Thanks but that's not what I am asking. I (of course) already have port forwarding for accessing the NAT boxes and a nginx reverse proxy to point external domain names directly to the internal vm's ip for http. I want to do forwarding based on the domain thru nginx proxy or other method, for other ports/services (mainly ssh and mail server). So, a request for mail should point to the internal virtual machine's postfix/exim passing thru the proxy to the normal ports (e.g. 25) and not using different ports on the main node.

  • SNI is not available on that layer. I guess you want simple TCP forwarding (like DNAT above) routed by a name. Like if server_name ssh.xy.z; then tcp_forward 22; or something like that.

    Thanked by 1jvnadr
  • doghouchdoghouch Member
    edited September 2015

    @jvnadr said:
    Thanks but that's not what I am asking. I (of course) already have port forwarding for accessing the NAT boxes and a nginx reverse proxy to point external domain names directly to the internal vm's ip for http. I want to do forwarding based on the domain thru nginx proxy or other method, for other ports/services (mainly ssh and mail server). So, a request for mail should point to the internal virtual machine's postfix/exim passing thru the proxy to the normal ports (e.g. 25) and not using different ports on the main node.

    My new post to address your problem: http://pastebin.com/C1tn3NWP


    CrapFlare wouldn't let me submit the other one on account of "Possible SQL injection detected, request blocked."

    Thanked by 1jvnadr
  • nginx shouldn't work for that. I would try haproxy or iptables forwarding.

  • Don't use haproxy, it was unreliable in forwarding for me @martinandrino :p

Sign In or Register to comment.