Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NGinx forward websocket from 80 to websocket port

I am using Nginx as a web host and proxy for a websocket running on the same device listening on port 8888. Trying to find a way to have nginx listen on 80 and forward the websocket requests to the internal port. Without exposing a new port to the outside. Is this even possible?

UPDATE:

This is my current configuration:

error_log       /var/log/nginx/error_log.log    warn;

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

upstream websocket {
    server localhost:8888;
}


server {
    listen 80;
    #listen [::]:80 default_server;

    # SSL configuration
    #
    # listen 443 ssl default_server;
    # listen [::]:443 ssl default_server;
    #
    # Self signed certs generated by the ssl-cert package
    # Don't use them in a production server!
    #
    # include snippets/snakeoil.conf;

    root /var/www/html/EncoderAdmin;

    # Add index.php to the list if you are using PHP
    index index.php index.html index.htm index.nginx-debian.html;

    server_name _;

    location / {
            # First attempt to serve request as file, then
            # as directory, then fall back to displaying a 404.
            try_files $uri $uri/ =404;
            auth_basic "Restricted Content";
            auth_basic_user_file /etc/nginx/.htpasswd;


    }

    location /ws {
            proxy_pass              http://localhost:8888;
            proxy_http_version      1.1;
            proxy_set_header        Host $http_host;
            proxy_set_header        X-Real-IP $remote_addr;
            proxy_set_header        Upgrade $http_upgrade;
            proxy_set_header        Connection "upgrade";
    }

}

When I try to connect to it with ws://[address]/ws I get:

WebSocket connection to 'ws://[address]/ws' failed: Error during WebSocket handshake: Unexpected response code: 400

like image 537
Aaron Rumford Avatar asked Feb 27 '17 17:02

Aaron Rumford


People also ask

Does WebSocket use port 80?

Although they are different, RFC 6455 states that WebSocket "is designed to work over HTTP ports 443 and 80 as well as to support HTTP proxies and intermediaries", thus making it compatible with HTTP.

Can NGINX handle WebSockets?

NGINX supports WebSocket by allowing a tunnel to be set up between both client and back-end servers. NGINX will send the Upgrade request from the client to the back-end server, the Upgrade and Connection headers must be set explicitly. Once this is done, NGINX deals with this as a WebSocket connection.

Do WebSockets port forward?

Port Forwarding is only needed if one client wants to directly connect to the other client. But if all of your websocket messages are being relayed through a public server, then Port Forwarding is not needed.

How does Nginx handle WebSocket?

NGINX listens on port 8020 and proxies requests to the backend WebSocket server. The proxy_set_header directives enable NGINX to properly handle the WebSocket protocol.

What ports do WebSockets use?

For example, WebSocket applications can use the standard HTTP ports 80 and 443, thus allowing the use of existing firewall rules. A WebSocket application keeps a long‑running connection open between the client and the server, facilitating the development of real‑time applications.

Can Nginx work on port 80 for Node JS?

Nginx works on port 80 and Node JS on 8080. I created new subdomain: cdn.domain.com for nodejs app. Currently I can access to Node JS application only like cdn.domain.com:8080/. What I want to do is to configure Nginx so that, when I enter to cdn.domain.com I can get app working on port 80. I think it can be done using nginx upstream.

What is HTTP Upgrade in WebSocket?

A WebSocket application keeps a long‑running connection open between the client and the server, facilitating the development of real‑time applications. The HTTP Upgrade mechanism used to upgrade the connection from HTTP to WebSocket uses the Upgrade and Connection headers.


1 Answers

Yes, it's possible assuming you can distinguish the normal HTTP requests and the socket ones.

The simplest solution is to match the socket uri with location, for example all the requests to /ws will be redirected to localhost:8888, any other url to localhost:8889. Here it is an example of configuration

server {
    server_name  _;

    location /ws {
        proxy_pass http://localhost:8888;
        # this magic is needed for WebSocket
        proxy_http_version  1.1;
        proxy_set_header    Upgrade $http_upgrade;
        proxy_set_header    Connection "upgrade";
        proxy_set_header    Host $http_host;
        proxy_set_header    X-Real-IP $remote_addr;
    }

    location / {
        proxy_pass http://localhost:8889;
    }
}

You should also remember to bind the websocket server to localhost:8888 and not to 0.0.0.0:8888. This step is not needed but with it the original port is not exposed!

like image 185
Edoardo Morassutto Avatar answered Oct 24 '22 05:10

Edoardo Morassutto