正常に動作する小さな Socket.IO サーバーを作成しました。接続でき、メッセージを送受信できるので、すべて正常に動作しています。コードの関連部分のみをここに示します。
var RedisStore = require('socket.io/lib/stores/redis');
const pub = redis.createClient('127.0.0.1', 6379);
const sub = redis.createClient('127.0.0.1', 6379);
const store = redis.createClient('127.0.0.1', 6379);
io.configure(function() {
io.set('store', new RedisStore({
redisPub : pub,
redisSub : sub,
redisClient : store
}));
});
io.sockets.on('connection', function(socket) {
socket.on('message', function(msg) {
pub.publish("lobby", msg);
});
/*
* Subscribe to the lobby and receive messages.
*/
var sub = redis.createClient('127.0.0.1', 6379);
sub.subscribe("lobby");
sub.on('message', function(channel, msg) {
socket.send(msg);
});
});
サーバーに接続し、setInterval 関数で接続を生成する以下のスクリプトも作成しました。これは、10 ミリ秒ごとに新しい接続を生成するため、かなり多くの接続が生成されます。
#!/usr/bin/env node
var io = require('socket.io-client');
var reconn = {'force new connection': true};
var sockets = [];
var num = 1000;
function startSocket(i) {
sockets[i] = io.connect("http://127.0.0.1:8080", reconn);
sockets[i].on('connect', function() {
console.log("Socket["+i+"] connected.");
});
sockets[i].on('message', function(msg) {
console.log("Socket["+i+"] Message received: "+msg);
});
}
/*
* Start number of sockets.
*/
for(var i=0; i<num; i++) {
startSocket(i);
}
/*
* Send messages forever.
*/
setInterval(function() {
for(var i=0; i<num; i++) {
sockets[i].send("Hello from socket "+i+".");
}
}, 10);
このスクリプトは、サーバーへの 1000 接続を生成するベンチマーク ツールですが、数分間実行すると、次のエラー メッセージが表示されてサーバーが停止します。
node.js:0 // 著作権は Joyent, Inc. およびその他のノード コントリビューターに帰属します。^ RangeError: 最大呼び出しスタック サイズを超えました
十分なスタック スペースがないため、例外が発生してプロセスが終了することはわかっていますが、 --stack-size 変数を使用してスタックを拡大しても、実際には問題は解決しません。これにより、最終的にサーバーが強制終了されます。
私の質問は、どうすればこれを防ぐことができるかです。これは効果的な DoS シナリオであり、誰でもこの小さなスクリプトをハッキングしてノード サーバーを強制的に終了させることができますが、私はこれが起こらないようにしたいと考えています。メッセージをゆっくりと処理するだけで、ノードサーバーが終了しないようにします。
これを防ぐことができるかどうかのアイデア。IP をブロックするかどうかはわかりません。多くの携帯電話が同じ IP を使用するシステムにログインするようにしたいので、ノード サーバーは DoS が 1 つだけ導入されていると誤って判断する可能性があります。モバイル ネットワークの動作を停止し、その IP をブロックします。
ありがとうございました