Workaround for #724
This commit is contained in:
parent
60f77d4eb9
commit
9886f648f2
|
@ -2,7 +2,7 @@
|
|||
"author": "Calvin Montgomery",
|
||||
"name": "CyTube",
|
||||
"description": "Online media synchronizer and chat",
|
||||
"version": "3.51.5",
|
||||
"version": "3.51.6",
|
||||
"repository": {
|
||||
"url": "http://github.com/calzoneman/sync"
|
||||
},
|
||||
|
|
|
@ -21,7 +21,19 @@ import http from 'http';
|
|||
|
||||
const LOGGER = require('@calzoneman/jsli')('ioserver');
|
||||
|
||||
// WIP, not in use yet
|
||||
const rateLimitExceeded = new Counter({
|
||||
name: 'cytube_socketio_rate_limited_total',
|
||||
help: 'Number of socket.io connections rejected due to exceeding rate limit'
|
||||
});
|
||||
const connLimitExceeded = new Counter({
|
||||
name: 'cytube_socketio_conn_limited_total',
|
||||
help: 'Number of socket.io connections rejected due to exceeding conn limit'
|
||||
});
|
||||
const authFailureCount = new Counter({
|
||||
name: 'cytube_socketio_auth_error_total',
|
||||
help: 'Number of failed authentications from session middleware'
|
||||
});
|
||||
|
||||
class IOServer {
|
||||
constructor(options = {
|
||||
proxyTrustFn: proxyaddr.compile('127.0.0.1')
|
||||
|
@ -65,6 +77,7 @@ class IOServer {
|
|||
|
||||
const bucket = this.ipThrottle.get(socket.context.ipAddress);
|
||||
if (bucket.throttle()) {
|
||||
rateLimitExceeded.inc(1);
|
||||
LOGGER.info('Rejecting %s - exceeded connection rate limit',
|
||||
socket.context.ipAddress);
|
||||
next(new Error('Rate limit exceeded'));
|
||||
|
@ -74,6 +87,8 @@ class IOServer {
|
|||
next();
|
||||
}
|
||||
|
||||
/*
|
||||
TODO: see https://github.com/calzoneman/sync/issues/724
|
||||
ipConnectionLimitMiddleware(socket, next) {
|
||||
const ip = socket.context.ipAddress;
|
||||
const count = this.ipCount.get(ip) || 0;
|
||||
|
@ -84,12 +99,45 @@ class IOServer {
|
|||
}
|
||||
|
||||
this.ipCount.set(ip, count + 1);
|
||||
console.log(ip, this.ipCount.get(ip));
|
||||
socket.once('disconnect', () => {
|
||||
console.log('Disconnect event has fired for', socket.id);
|
||||
this.ipCount.set(ip, this.ipCount.get(ip) - 1);
|
||||
});
|
||||
|
||||
next();
|
||||
}
|
||||
*/
|
||||
|
||||
checkIPLimit(socket) {
|
||||
const ip = socket.context.ipAddress;
|
||||
const count = this.ipCount.get(ip) || 0;
|
||||
if (count >= Config.get('io.ip-connection-limit')) {
|
||||
connLimitExceeded.inc(1);
|
||||
LOGGER.info(
|
||||
'Rejecting %s - exceeded connection count limit',
|
||||
ip
|
||||
);
|
||||
socket.emit('kick', {
|
||||
reason: 'Too many connections from your IP address'
|
||||
});
|
||||
socket.disconnect(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
this.ipCount.set(ip, count + 1);
|
||||
socket.once('disconnect', () => {
|
||||
const newCount = (this.ipCount.get(ip) || 1) - 1;
|
||||
|
||||
if (newCount === 0) {
|
||||
this.ipCount.delete(ip);
|
||||
} else {
|
||||
this.ipCount.set(ip, newCount);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parse cookies
|
||||
cookieParsingMiddleware(socket, next) {
|
||||
|
@ -132,6 +180,7 @@ class IOServer {
|
|||
promises.push(verifySession(auth).then(user => {
|
||||
socket.context.user = Object.assign({}, user);
|
||||
}).catch(error => {
|
||||
authFailureCount.inc(1);
|
||||
LOGGER.warn('Unable to verify session for %s - ignoring auth',
|
||||
socket.context.ipAddress);
|
||||
}));
|
||||
|
@ -153,6 +202,12 @@ class IOServer {
|
|||
}
|
||||
|
||||
handleConnection(socket) {
|
||||
// TODO: move out of handleConnection if possible
|
||||
// see: https://github.com/calzoneman/sync/issues/724
|
||||
if (!this.checkIPLimit(socket)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER.info('Accepted socket from %s', socket.context.ipAddress);
|
||||
counters.add('socket.io:accept', 1);
|
||||
socket.once('disconnect', () => counters.add('socket.io:disconnect', 1));
|
||||
|
@ -176,7 +231,7 @@ class IOServer {
|
|||
io.use(this.ipProxyMiddleware.bind(this));
|
||||
io.use(this.ipBanMiddleware.bind(this));
|
||||
io.use(this.ipThrottleMiddleware.bind(this));
|
||||
io.use(this.ipConnectionLimitMiddleware.bind(this));
|
||||
//io.use(this.ipConnectionLimitMiddleware.bind(this));
|
||||
io.use(this.cookieParsingMiddleware.bind(this));
|
||||
io.use(this.ipSessionCookieMiddleware.bind(this));
|
||||
io.use(this.authUserMiddleware.bind(this));
|
||||
|
@ -209,12 +264,12 @@ function patchSocketMetrics() {
|
|||
|
||||
Socket.prototype.onevent = function patchedOnevent() {
|
||||
onevent.apply(this, arguments);
|
||||
incomingEventCount.inc(1, new Date());
|
||||
incomingEventCount.inc(1);
|
||||
};
|
||||
|
||||
Socket.prototype.packet = function patchedPacket() {
|
||||
packet.apply(this, arguments);
|
||||
outgoingPacketCount.inc(1, new Date());
|
||||
outgoingPacketCount.inc(1);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -278,7 +333,7 @@ function emitMetrics(sock) {
|
|||
let closed = false;
|
||||
let transportName = sock.client.conn.transport.name;
|
||||
promSocketCount.inc({ transport: transportName });
|
||||
promSocketAccept.inc(1, new Date());
|
||||
promSocketAccept.inc(1);
|
||||
|
||||
sock.client.conn.on('upgrade', newTransport => {
|
||||
try {
|
||||
|
@ -298,7 +353,7 @@ function emitMetrics(sock) {
|
|||
try {
|
||||
closed = true;
|
||||
promSocketCount.dec({ transport: transportName });
|
||||
promSocketDisconnect.inc(1, new Date());
|
||||
promSocketDisconnect.inc(1);
|
||||
} catch (error) {
|
||||
LOGGER.error('Error emitting disconnect metrics for socket (ip=%s): %s',
|
||||
sock.context.ipAddress, error.stack);
|
||||
|
|
|
@ -37,7 +37,7 @@ Callbacks = {
|
|||
|
||||
// Socket.IO error callback
|
||||
error: function (msg) {
|
||||
window.SOCKET_ERROR_REASON = reason;
|
||||
window.SOCKET_ERROR_REASON = msg;
|
||||
$("<div/>")
|
||||
.addClass("server-msg-disconnect")
|
||||
.text("Unable to connect: " + msg)
|
||||
|
|
Loading…
Reference in a new issue