Initial IP session cookie implementation

This commit is contained in:
calzoneman 2016-08-08 23:03:16 -07:00
parent 96a5d657a5
commit 016b125f49
4 changed files with 127 additions and 22 deletions

View file

@ -15,6 +15,7 @@ var crypto = require("crypto");
var isTorExit = require("../tor").isTorExit;
var session = require("../session");
import counters from '../counters';
import { verifyIPSessionCookie } from '../web/middleware/ipsessioncookie';
var CONNECT_RATE = {
burst: 5,
@ -25,33 +26,53 @@ var ipThrottle = {};
// Keep track of number of connections per IP
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.
*/
function handleAuth(socket, accept) {
var data = socket.request;
socket.user = false;
if (data.headers.cookie) {
cookieParser(data, null, function () {
var auth = data.signedCookies.auth;
if (!auth) {
return accept(null, true);
}
session.verifySession(auth, function (err, user) {
if (!err) {
socket.user = {
name: user.name,
global_rank: user.global_rank
};
}
accept(null, true);
});
});
} else {
accept(null, true);
var auth = socket.request.signedCookies.auth;
if (!auth) {
return accept(null, true);
}
session.verifySession(auth, function (err, user) {
if (!err) {
socket.user = {
name: user.name,
global_rank: user.global_rank
};
}
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) {
@ -247,8 +268,10 @@ module.exports = {
};
var io = sio.instance = sio();
io.use(handleAuth);
io.use(ipForwardingMiddleware(webConfig));
io.use(parseCookies);
io.use(handleIPSessionCookie);
io.use(handleAuth);
io.on("connection", handleConnection);
Config.get("listen").forEach(function (bind) {

View file

@ -18,6 +18,11 @@ module.exports = {
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");
fs.exists(gdvttpath, function (exists) {
exists || fs.mkdir(gdvttpath);

View file

@ -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();
}

View file

@ -146,6 +146,7 @@ module.exports = {
}
app.use(cookieParser(webConfig.getCookieSecret()));
app.use(csrf.init(webConfig.getCookieDomain()));
app.use('/r/:channel', require('./middleware/ipsessioncookie').ipSessionCookieMiddleware);
initializeLog(app);
require('./middleware/authorize')(app, session);