mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 12:20:27 +01:00
http: prevent slowloris with keepalive connections
Fixes: https://github.com/nodejs-private/security/issues/214 PR-URL: https://github.com/nodejs-private/node-private/pull/162 Reviewed-By: Rod Vagg <rod@vagg.org> Reviewed-By: Sam Roberts <vieuxtech@gmail.com> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
This commit is contained in:
parent
06a208d316
commit
b13b4a9ffb
|
|
@ -489,6 +489,10 @@ function connectionListener(socket) {
|
|||
|
||||
incoming.push(req);
|
||||
|
||||
if (self.keepAliveTimeout > 0) {
|
||||
req.on('end', resetHeadersTimeoutOnReqEnd);
|
||||
}
|
||||
|
||||
// Set to zero to communicate that we have finished parsing.
|
||||
socket.parser.parsingHeadersStart = 0;
|
||||
|
||||
|
|
@ -640,3 +644,14 @@ function socketOnWrap(ev, fn) {
|
|||
|
||||
return res;
|
||||
}
|
||||
|
||||
function resetHeadersTimeoutOnReqEnd() {
|
||||
debug('resetHeadersTimeoutOnReqEnd');
|
||||
|
||||
var parser = this.socket.parser;
|
||||
// Parser can be null if the socket was destroyed
|
||||
// in that case, there is nothing to do.
|
||||
if (parser !== null) {
|
||||
parser.parsingHeadersStart = nowDate();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
58
test/parallel/test-http-slow-headers-keepalive.js
Normal file
58
test/parallel/test-http-slow-headers-keepalive.js
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const http = require('http');
|
||||
const net = require('net');
|
||||
|
||||
const headers =
|
||||
'GET / HTTP/1.1\r\n' +
|
||||
'Host: localhost\r\n' +
|
||||
'Connection: keep-alive' +
|
||||
'Agent: node\r\n';
|
||||
|
||||
let sendCharEvery = 1000;
|
||||
|
||||
const server = http.createServer(common.mustCall((req, res) => {
|
||||
res.writeHead(200);
|
||||
res.end();
|
||||
}));
|
||||
|
||||
// Pass a REAL env variable to shortening up the default
|
||||
// value which is 40s otherwise this is useful for manual
|
||||
// testing
|
||||
if (!process.env.REAL) {
|
||||
sendCharEvery = common.platformTimeout(10);
|
||||
server.headersTimeout = 2 * sendCharEvery;
|
||||
}
|
||||
|
||||
server.once('timeout', common.mustCall((socket) => {
|
||||
socket.destroy();
|
||||
}));
|
||||
|
||||
server.listen(0, () => {
|
||||
const client = net.connect(server.address().port);
|
||||
client.write(headers);
|
||||
// finish the first request
|
||||
client.write('\r\n');
|
||||
// second request
|
||||
client.write(headers);
|
||||
client.write('X-CRASH: ');
|
||||
|
||||
const interval = setInterval(() => {
|
||||
client.write('a');
|
||||
}, sendCharEvery);
|
||||
|
||||
client.resume();
|
||||
|
||||
const onClose = common.mustCall(() => {
|
||||
client.removeListener('close', onClose);
|
||||
client.removeListener('error', onClose);
|
||||
client.removeListener('end', onClose);
|
||||
clearInterval(interval);
|
||||
server.close();
|
||||
});
|
||||
|
||||
client.on('error', onClose);
|
||||
client.on('close', onClose);
|
||||
client.on('end', onClose);
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user