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