2

I have a Nodejs server app with Express and Socket.io (Ubuntu 18.04). It always worked fine until nGinx (1.14) reverse proxy entered the scene. The nginx server is running on a different machine of Node.js apps, each app on it's own vm, inside the same network.

Server and Client on version 2.1.1.

The nginx server is responsible for multiple app redirects.

I tried several configuration combinations but nothing works.

Here what I've tried (examples for "company1"):

default.conf in /etc/nginx/conf.d

location /company1-srv/ {
     proxy_http_version 1.1;
     proxy_set_header Upgrade $http_upgrade;
     proxy_set_header Connection "Upgrade";
     proxy_set_header Host $host;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header X-Forwarded-Proto $scheme;
     proxy_set_header X-NginX-Proxy true;
     proxy_redirect off;
     proxy_pass http://172.16.0.25:51001/;
}

Then in the client code I connect using "path" options because socket.io misplace it's library path.

// companySrv and URL is actually returned by another service (following code is for illustrative purposes):
let companyUrl = 'https://api.myserver.com/company1-srv';
let companySrv = '/company1-srv'; 

socket(companyUrl, {
      path: companySrv + '/socket.io/'
});

I also tried to remove the path option and configured a specific /location for the socket.io stuff (for testing purposes):

location /socket.io/ {
   proxy_http_version 1.1;
   proxy_set_header Upgrade $http_upgrade;
   proxy_set_header Connection 'upgrade';
   proxy_set_header Host $host;
   proxy_cache_bypass $http_upgrade;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Forwarded-Proto $scheme;
   proxy_set_header X-NginX-Proxy true;
   proxy_redirect off;
   proxy_pass http://172.16.0.25:51001/socket.io/;
}

Nothing worked.

It connects, but does'n emits anything. And after a short while (a minute or so), it becomes unavailable, raising the "disconnect" (reason: transport close) client event.

Server:

const io = require('socket.io')(https || http, {
   transports: ['polling', 'websocket'],
   allowUpgrades: true, 
   pingInterval: 60000*60*24, 
   pingTimeout: 60000*60*24
});

I also tried to edit the nginx.conf and write the "upstream socket_nodes { ..." and use the proxy_pass http://socket_nodes. It didn't make sense as I need a exact redirect depending on the company, but for the sake of tests I did, but it doesn't work as well.

What I need to do?

Thanks

1 Answer 1

2

We as well use socket.io with reverse-proxy from ngnix. I can share a little bit of our setup, maybe it helps to rule things out.

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
        worker_connections 768;
}

stream {
        log_format      basic   '$time_iso8601 $remote_addr '
                                '$protocol $status $bytes_sent $bytes_received '
                                '$session_time $upstream_addr '
                                '"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
        
        access_log /var/log/nginx/stream.log basic;
}

http {

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        gzip on;

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;

        ##
        # Server Blocks 
        ##


        # DOMAINEXAMPLE A
        server {
                server_name exampleA.domain.com;
                location / {
                        proxy_set_header        X-Forwarded-For $remote_addr;
                        proxy_set_header        Host $http_host;
                        proxy_pass              http://192.168.21.105:5050;
                 }
        }

        # DOMAINEXAMPLE B
        server {
                server_name exampleB.domain.com;
                location /api {
                        proxy_set_header        X-Forwarded-For $remote_addr;
                        proxy_set_header        Host $http_host;
                        proxy_pass              http://192.168.21.106:5050;
                }
        }

     
}

The most interesting part here are probably the server blocks

        # DOMAINEXAMPLE A
        server {
                server_name exampleA.domain.com;
                location / {
                        proxy_set_header        X-Forwarded-For $remote_addr;
                        proxy_set_header        Host $http_host;
                        proxy_pass              http://192.168.21.105:5050;
                 }
        }

        # DOMAINEXAMPLE B
        server {
                server_name exampleB.domain.com;
                location /api {
                        proxy_set_header        X-Forwarded-For $remote_addr;
                        proxy_set_header        Host $http_host;
                        proxy_pass              http://192.168.21.106:5050;
                }
        }

Domain Example A

For location / at http://192.168.21.105:5050 we have a NodeJS process running, including the setup for socket.io

const express = require('express');
const http    = require('http');
const app     = express();
const server  = http.createServer(app);
const io      = require('socket.io')(server);

Domain Example B

For location /api at http://192.168.21.106:5050 we have another NodeJS process running, including a slightly different setup for socket.io

const express  = require('express');
const http     = require('http');
const app      = express();
const server   = http.createServer(app);
const io       = require('socket.io')(server, {path: '/api/socket.io'});

In both cases socket.io works perfectly fine for us

Connecting from Client (Example B)

What we actually do on the server side here is creating a namespace for socket.io, like

const io= require('socket.io')(server, {path: '/api/socket.io'});
const nsp = io.of('/api/frontend');

and then on the client side , connect to it like

import io from 'socket.io-client'
const socket = io('https://exampleB.domain.com/api/frontend', {path: "/api/socket.io"});
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for sharing Pascal. What's the version of socket.io are you using? And on example B, on the client side, you connect with the path option, is that right? io.connect(serverUrl, { path: '/api/socket.io' })
On the server socket.io": "^2.3.0" and on the client "socket.io-client": "^2.3.0". Yes {path: "/api/socket.io"} to connect in the client . I'll update my answer how I connect from client .
@Lacoste were you able to find something ? I am curious and solving your problem would probably help us to understand this more better as well :)
@EduMüller Socket.io updated their documentation quite a bit this year, you might find an answer here This is because the HTTP long-polling transport sends multiple HTTP requests during the lifetime of the Socket.IO session. - so I guess you're assuming it right, it keeps sending requests. They also updated the docs for Reverse Proxy
@PascalLamers You're right. I was testing with the default transport configured ["polling", "websocket"]. When I put it to operate without the reverse proxy, these various requests didn't occur, but when I put it with the reverse proxy. Reading a little more about it, I realized that this was normal, as my configuration for websocket on the reverse proxy was invalid, so only long-polling was being used. Anyway, thanks for your reply.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.