How to make proxy traffic on the website in the nginx config? http://nginx.org/ru/docs/http/websocket.html

Suppose if our site is located on port 80, and the web socket is located at ws: //site.ru: 2000

    2 answers 2

    The question was solved simply:

    in http {} we add

    map $http_upgrade $connection_upgrade { default upgrade; '' close; } upstream websocket { server ваш_ип:2000; } 

    in server {} we add

     location /websocket { proxy_pass http://websocket; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } 

    in nginx.conf we add

     keepalive_timeout 604800; proxy_connect_timeout 604800; proxy_send_timeout 604800; proxy_read_timeout 604800; 

    we open the web socket in this way

     var socket = new WebSocket("ws://ваш_ип_или_домен/websocket"); 
    • 3
      proxy_set_header Connection "Upgrade"; need to be replaced with proxy_set_header Connection $connection_upgrade; otherwise the map declaration above does not make sense. The whole point of this map is just to use the same upstream for websocket connections as well as for ordinary http connections. The principle of operation as a result is this: if there is a non-empty Upgrade header in the original request, then transfer the Connection header to the upstream with the value of upgrade , otherwise transfer the Connection header to the upstream with the value of close . - Ruslan Stelmachenko

    Such config does not work. I get an error in the browser console:

    WebSocket connection to ws: //site.com/ws failed: Error during WebSocket handshake: Unexpected response code: 200

    There are a lot of questions in all forums about this error, but not a single answer. It seems that nginx ws cannot really be proxied. The problem is treated easily, you just need to establish a connection with ws in the js code with an explicit indication of the port

     var socket = new WebSocket("ws://ваш_ип_или_домен:9999"); 

    In this case, everything works right away.

    Hence the question: why bother ws proxying through nginx at all?

    Check Origin (host from which connect to ws) can easily ws server itself. Only one thing comes to mind: it is necessary to proxy in order to avoid a la ddos ​​attacks on the ws port, so that the messages are first filtered by nginx and then the ws server. Because in theory, the ws server will fill up much faster than nginx.

    Does it make sense to protect the ws server in this way? Who can justify?

    • This is an answer box! Ask a new question if you have few existing answers. - AivanF.
    • you just need to establish a connection with ws in the js code with an explicit indication of the port ... if the port is not 80, or, for wss , not 443. See RFC6455 . As usual, there is everything in the documentation, just deeper than expected. - D-side
    • one
      We also need nginx to forward us to the port on which the ws server is listening, that is, to 9999. Instead, nginx says: honey, I'm fine, here’s your answer is http 200, what other sockets?)) - faecker
    • It already turns out to bypass nginx, because of which the whole essence of the venture is lost, for whatever TSU needs it. If you want to ask about the appropriateness of this, ask a separate question. - D-side