Add extra anti-DoS tech to net.Server
This commit is contained in:
parent
aeb9bed63e
commit
38dde9684f
@ -4,21 +4,6 @@ var errors = 0, connections = 0;
|
|||||||
|
|
||||||
var lastClose = 0;
|
var lastClose = 0;
|
||||||
|
|
||||||
function maybeConnect (s) {
|
|
||||||
var now = new Date();
|
|
||||||
if (now - lastClose > 5000) {
|
|
||||||
// Just connect immediately
|
|
||||||
connect();
|
|
||||||
} else {
|
|
||||||
// Otherwise wait a little - see if this one is connected still. Just to
|
|
||||||
// avoid spinning at 100% cpu when the server totally rejects our
|
|
||||||
// connections.
|
|
||||||
setTimeout(function () {
|
|
||||||
if (s.writable && s.readable) connect();
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function connect () {
|
function connect () {
|
||||||
process.nextTick(function () {
|
process.nextTick(function () {
|
||||||
var s = net.Stream();
|
var s = net.Stream();
|
||||||
@ -28,7 +13,7 @@ function connect () {
|
|||||||
s.on('connect', function () {
|
s.on('connect', function () {
|
||||||
gotConnected = true;
|
gotConnected = true;
|
||||||
connections++;
|
connections++;
|
||||||
maybeConnect(s);
|
connect();
|
||||||
});
|
});
|
||||||
|
|
||||||
s.on('close', function () {
|
s.on('close', function () {
|
||||||
|
33
lib/net.js
33
lib/net.js
@ -930,34 +930,57 @@ function Server (/* [ options, ] listener */) {
|
|||||||
// Just in case we don't have a dummy fd.
|
// Just in case we don't have a dummy fd.
|
||||||
if (!self._dummyFD) self._getDummyFD();
|
if (!self._dummyFD) self._getDummyFD();
|
||||||
|
|
||||||
|
if (self._acceptTimer) {
|
||||||
|
// Somehow the watcher got started again. Need to wait until
|
||||||
|
// the timer finishes.
|
||||||
|
self.watcher.stop();
|
||||||
|
}
|
||||||
|
|
||||||
while (self.fd) {
|
while (self.fd) {
|
||||||
try {
|
try {
|
||||||
var peerInfo = accept(self.fd);
|
var peerInfo = accept(self.fd);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.errno == EMFILE) {
|
if (e.errno != EMFILE) throw e;
|
||||||
|
|
||||||
// Output a warning, but only at most every 5 seconds.
|
// Output a warning, but only at most every 5 seconds.
|
||||||
var now = new Date();
|
var now = new Date();
|
||||||
if (now - self._lastEMFILEWarning > 5000) {
|
if (now - self._lastEMFILEWarning > 5000) {
|
||||||
console.error("(node) Hit max file limit. Increase 'ulimit -n'.");
|
console.error("(node) Hit max file limit. Increase 'ulimit -n'.");
|
||||||
}
|
|
||||||
self._lastEMFILEWarning = now;
|
self._lastEMFILEWarning = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
var acceptCount = 0;
|
||||||
|
|
||||||
// Gracefully reject pending clients by freeing up a file
|
// Gracefully reject pending clients by freeing up a file
|
||||||
// descriptor.
|
// descriptor.
|
||||||
if (self._dummyFD) {
|
if (self._dummyFD) {
|
||||||
close(self._dummyFD);
|
close(self._dummyFD); // Free up an fd
|
||||||
self._dummyFD = null;
|
self._dummyFD = null;
|
||||||
|
// Accept and close the waiting clients one at a time.
|
||||||
|
// Single threaded programming ftw.
|
||||||
while (true) {
|
while (true) {
|
||||||
peerInfo = accept(self.fd);
|
peerInfo = accept(self.fd);
|
||||||
if (!peerInfo) break;
|
if (!peerInfo) break;
|
||||||
close(peerInfo.fd);
|
close(peerInfo.fd);
|
||||||
|
|
||||||
|
// Don't become DoS'd by incoming requests
|
||||||
|
if (++acceptCount > 50) {
|
||||||
|
assert(!self._acceptTimer);
|
||||||
|
self.watcher.stop();
|
||||||
|
// Wait a second before accepting more.
|
||||||
|
self._acceptTimer = setTimeout(function () {
|
||||||
|
assert(parseInt(self.fd) >= 0);
|
||||||
|
self._acceptTimer = null;
|
||||||
|
self.watcher.start();
|
||||||
|
}, 1000);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// Reacquire the dummy fd
|
||||||
self._getDummyFD();
|
self._getDummyFD();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
if (!peerInfo) return;
|
if (!peerInfo) return;
|
||||||
|
|
||||||
if (self.maxConnections && self.connections >= self.maxConnections) {
|
if (self.maxConnections && self.connections >= self.maxConnections) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user