Как сделать ограничение скорости API на основе IP в режиме кластера node.js? - PullRequest
0 голосов
/ 13 мая 2019

Я запускаю приложение node.js / express / socket.io в режиме кластера. Я запускаю внешний сервер для мастер-процесса и внутренние серверы для рабочих, как показано в следующем коде.

if (cluster.isMaster) {

var workers = [];

var spawn = function(i) {
    workers[i] = cluster.fork();

    // Optional: Restart worker on exit
    workers[i].on('exit', function(code, signal) {
        console.log('Process exited! respawning worker no: ', i);
        spawn(i);
    });
  };

  // Spawn workers.
for (var i = 0; i < numCPUs; i++) {
    spawn(i);
}


var worker_index = function(ip, len) {
    return farmhash.fingerprint32(ip) % len; // Farmhash is the fastest and works with IPv6, too
};

// Create the outside facing server listening on our port.
var server = net.createServer({ pauseOnConnect: true }, function(connection) {

  //!!!! the connection.remoteAddress causes issues with reverse proxy, however here not important as socket.io is used only for a global signalling to all clients
  // console.log(connection.remoteAddress);
    var worker = workers[worker_index(connection.remoteAddress, numCPUs)];
    worker.send('sticky-session:connection', connection);
}).listen(port);

console.log('***************************************');
console.log('listening EXTERNALLY http://localhost:' + port);
console.log("This system has " + numCPUs + " virtual or real CPUs");
console.log('***************************************');
connection.remoteAddress // --> this is 127.0.0.1

} else {

// all worker processes enter the app from server.js
require("./server.js");
}

А затем в server.js, который запускается в соответствии с количеством ядер, доступных в системе.

const rateLimit = require('express-rate-limit');
...
app.enable("trust proxy"); // only if you're behind a reverse proxy (Heroku, Bluemix, AWS ELB, Nginx, etc)
...
app.use('/api/', apiLimiter); // --> this does not work as the real IP is not available
...

//startup the HTTP server
 server.listen(0, 'localhost', function(err) {
     console.log('***************************************');
console.log('***************************************');
  console.log('listening INTERNALLY http://localhost:0');
console.log('***************************************');


});

В этом коде ограничение API (express-rate-limit) из node.js не работает. Я подозреваю, что это потому, что IP-адрес всегда одинаков на внутреннем сервере (127.0.0.1, localhost).

После создания http-сервера я могу получить реальный IP с помощью следующей команды:

req.headers['x-real-ip'] ||  req.connection.remoteAddress;

Но это не работает до создания http-сервера, но мне нужно это, чтобы включить ограничитель API.

Почему-то мне нужно передать IP-адрес с внешнего сервера, который, похоже, является TCP-сервером. Есть ли способ получить реальный IP в самом начале до создания http-сервера?

...