mirror of https://github.com/calzoneman/sync.git
Initial IP session cookie implementation
This commit is contained in:
parent
96a5d657a5
commit
016b125f49
|
@ -15,6 +15,7 @@ var crypto = require("crypto");
|
||||||
var isTorExit = require("../tor").isTorExit;
|
var isTorExit = require("../tor").isTorExit;
|
||||||
var session = require("../session");
|
var session = require("../session");
|
||||||
import counters from '../counters';
|
import counters from '../counters';
|
||||||
|
import { verifyIPSessionCookie } from '../web/middleware/ipsessioncookie';
|
||||||
|
|
||||||
var CONNECT_RATE = {
|
var CONNECT_RATE = {
|
||||||
burst: 5,
|
burst: 5,
|
||||||
|
@ -25,16 +26,24 @@ var ipThrottle = {};
|
||||||
// Keep track of number of connections per IP
|
// Keep track of number of connections per IP
|
||||||
var ipCount = {};
|
var ipCount = {};
|
||||||
|
|
||||||
|
function parseCookies(socket, accept) {
|
||||||
|
var req = socket.request;
|
||||||
|
if (req.headers.cookie) {
|
||||||
|
cookieParser(req, null, () => {
|
||||||
|
accept(null, true);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
req.cookies = {};
|
||||||
|
req.signedCookies = {};
|
||||||
|
accept(null, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Called before an incoming socket.io connection is accepted.
|
* Called before an incoming socket.io connection is accepted.
|
||||||
*/
|
*/
|
||||||
function handleAuth(socket, accept) {
|
function handleAuth(socket, accept) {
|
||||||
var data = socket.request;
|
|
||||||
|
|
||||||
socket.user = false;
|
socket.user = false;
|
||||||
if (data.headers.cookie) {
|
var auth = socket.request.signedCookies.auth;
|
||||||
cookieParser(data, null, function () {
|
|
||||||
var auth = data.signedCookies.auth;
|
|
||||||
if (!auth) {
|
if (!auth) {
|
||||||
return accept(null, true);
|
return accept(null, true);
|
||||||
}
|
}
|
||||||
|
@ -48,10 +57,22 @@ function handleAuth(socket, accept) {
|
||||||
}
|
}
|
||||||
accept(null, true);
|
accept(null, true);
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
} else {
|
|
||||||
accept(null, true);
|
function handleIPSessionCookie(socket, accept) {
|
||||||
|
var cookie = socket.request.signedCookies['ip-session'];
|
||||||
|
if (!cookie) {
|
||||||
|
socket.ipSessionFirstSeen = new Date();
|
||||||
|
return accept(null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sessionMatch = verifyIPSessionCookie(socket._realip, cookie);
|
||||||
|
if (sessionMatch) {
|
||||||
|
socket.ipSessionFirstSeen = sessionMatch.date;
|
||||||
|
} else {
|
||||||
|
socket.ipSessionFirstSeen = new Date();
|
||||||
|
}
|
||||||
|
accept(null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function throttleIP(sock) {
|
function throttleIP(sock) {
|
||||||
|
@ -247,8 +268,10 @@ module.exports = {
|
||||||
};
|
};
|
||||||
var io = sio.instance = sio();
|
var io = sio.instance = sio();
|
||||||
|
|
||||||
io.use(handleAuth);
|
|
||||||
io.use(ipForwardingMiddleware(webConfig));
|
io.use(ipForwardingMiddleware(webConfig));
|
||||||
|
io.use(parseCookies);
|
||||||
|
io.use(handleIPSessionCookie);
|
||||||
|
io.use(handleAuth);
|
||||||
io.on("connection", handleConnection);
|
io.on("connection", handleConnection);
|
||||||
|
|
||||||
Config.get("listen").forEach(function (bind) {
|
Config.get("listen").forEach(function (bind) {
|
||||||
|
|
|
@ -18,6 +18,11 @@ module.exports = {
|
||||||
exists || fs.mkdir(chandumppath);
|
exists || fs.mkdir(chandumppath);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var statepath = path.join(__dirname, "../state");
|
||||||
|
fs.exists(statepath, function (exists) {
|
||||||
|
exists || fs.mkdir(statepath);
|
||||||
|
});
|
||||||
|
|
||||||
var gdvttpath = path.join(__dirname, "../google-drive-subtitles");
|
var gdvttpath = path.join(__dirname, "../google-drive-subtitles");
|
||||||
fs.exists(gdvttpath, function (exists) {
|
fs.exists(gdvttpath, function (exists) {
|
||||||
exists || fs.mkdir(gdvttpath);
|
exists || fs.mkdir(gdvttpath);
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
import path from 'path';
|
||||||
|
import fs from 'fs';
|
||||||
|
import crypto from 'crypto';
|
||||||
|
|
||||||
|
const SALT_PATH = path.resolve(__dirname, '..', '..', '..', 'state', 'ipsessionsalt.json');
|
||||||
|
|
||||||
|
var SALT;
|
||||||
|
try {
|
||||||
|
SALT = require(SALT_PATH);
|
||||||
|
} catch (error) {
|
||||||
|
SALT = crypto.randomBytes(32).toString('base64');
|
||||||
|
fs.writeFileSync(SALT_PATH, SALT);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sha256(input) {
|
||||||
|
var hash = crypto.createHash("sha256");
|
||||||
|
hash.update(input);
|
||||||
|
return hash.digest("base64");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createIPSessionCookie(ip, date) {
|
||||||
|
const hashInput = [
|
||||||
|
ip,
|
||||||
|
date.getTime(),
|
||||||
|
SALT
|
||||||
|
].join(':');
|
||||||
|
|
||||||
|
return [
|
||||||
|
date.getTime(),
|
||||||
|
sha256(hashInput)
|
||||||
|
].join(':');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function verifyIPSessionCookie(ip, cookie) {
|
||||||
|
const parts = cookie.split(':');
|
||||||
|
if (parts.length !== 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const timestamp = parseInt(parts[0], 10);
|
||||||
|
if (isNaN(timestamp)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const date = new Date(timestamp);
|
||||||
|
const expected = createIPSessionCookie(ip, date);
|
||||||
|
if (expected !== cookie) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
date: date,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ipSessionCookieMiddleware(req, res, next) {
|
||||||
|
var firstSeen = new Date();
|
||||||
|
var hasSession = false;
|
||||||
|
if (req.signedCookies && req.signedCookies['ip-session']) {
|
||||||
|
var sessionMatch = verifyIPSessionCookie(req.realIP, req.signedCookies['ip-session']);
|
||||||
|
if (sessionMatch) {
|
||||||
|
hasSession = true;
|
||||||
|
firstSeen = sessionMatch.date;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasSession) {
|
||||||
|
res.cookie('ip-session', createIPSessionCookie(req.realIP, firstSeen), {
|
||||||
|
signed: true,
|
||||||
|
httpOnly: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
req.ipSessionFirstSeen = firstSeen;
|
||||||
|
next();
|
||||||
|
}
|
|
@ -146,6 +146,7 @@ module.exports = {
|
||||||
}
|
}
|
||||||
app.use(cookieParser(webConfig.getCookieSecret()));
|
app.use(cookieParser(webConfig.getCookieSecret()));
|
||||||
app.use(csrf.init(webConfig.getCookieDomain()));
|
app.use(csrf.init(webConfig.getCookieDomain()));
|
||||||
|
app.use('/r/:channel', require('./middleware/ipsessioncookie').ipSessionCookieMiddleware);
|
||||||
initializeLog(app);
|
initializeLog(app);
|
||||||
require('./middleware/authorize')(app, session);
|
require('./middleware/authorize')(app, session);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue