Move x-forwarded-for middleware

This commit is contained in:
calzoneman 2015-10-27 23:54:32 -07:00
parent 13d4a49976
commit c2726898e5
6 changed files with 53 additions and 40 deletions

View file

@ -1,5 +1,10 @@
import clone from 'clone'; import clone from 'clone';
const DEFAULT_TRUSTED_PROXIES = [
'127.0.0.1',
'::1'
];
export default class WebConfiguration { export default class WebConfiguration {
constructor(config) { constructor(config) {
this.config = config; this.config = config;
@ -8,6 +13,10 @@ export default class WebConfiguration {
getEmailContacts() { getEmailContacts() {
return clone(this.config.contacts); return clone(this.config.contacts);
} }
getTrustedProxies() {
return DEFAULT_TRUSTED_PROXIES.slice();
}
} }
WebConfiguration.fromOldConfig = function (oldConfig) { WebConfiguration.fromOldConfig = function (oldConfig) {

View file

@ -92,7 +92,7 @@ function handleChangePassword(req, res) {
return; return;
} }
Logger.eventlog.log("[account] " + webserver.ipForRequest(req) + Logger.eventlog.log("[account] " + req.realIP +
" changed password for " + name); " changed password for " + name);
db.users.getUser(name, function (err, user) { db.users.getUser(name, function (err, user) {
@ -172,7 +172,7 @@ function handleChangeEmail(req, res) {
}); });
return; return;
} }
Logger.eventlog.log("[account] " + webserver.ipForRequest(req) + Logger.eventlog.log("[account] " + req.realIP +
" changed email for " + name + " changed email for " + name +
" to " + email); " to " + email);
sendJade(res, "account-edit", { sendJade(res, "account-edit", {
@ -269,7 +269,7 @@ function handleNewChannel(req, res) {
db.channels.register(name, req.user.name, function (err, channel) { db.channels.register(name, req.user.name, function (err, channel) {
if (!err) { if (!err) {
Logger.eventlog.log("[channel] " + req.user.name + "@" + Logger.eventlog.log("[channel] " + req.user.name + "@" +
webserver.ipForRequest(req) + req.realIP +
" registered channel " + name); " registered channel " + name);
var sv = Server.getServer(); var sv = Server.getServer();
if (sv.isChannelLoaded(name)) { if (sv.isChannelLoaded(name)) {
@ -336,7 +336,7 @@ function handleDeleteChannel(req, res) {
db.channels.drop(name, function (err) { db.channels.drop(name, function (err) {
if (!err) { if (!err) {
Logger.eventlog.log("[channel] " + req.user.name + "@" + Logger.eventlog.log("[channel] " + req.user.name + "@" +
webserver.ipForRequest(req) + " deleted channel " + req.realIP + " deleted channel " +
name); name);
} }
var sv = Server.getServer(); var sv = Server.getServer();
@ -498,7 +498,7 @@ function handlePasswordReset(req, res) {
var hash = $util.sha1($util.randomSalt(64)); var hash = $util.sha1($util.randomSalt(64));
// 24-hour expiration // 24-hour expiration
var expire = Date.now() + 86400000; var expire = Date.now() + 86400000;
var ip = webserver.ipForRequest(req); var ip = req.realIP;
db.addPasswordReset({ db.addPasswordReset({
ip: ip, ip: ip,
@ -575,7 +575,7 @@ function handlePasswordRecover(req, res) {
return; return;
} }
var ip = webserver.ipForRequest(req); var ip = req.realIP;
db.lookupPasswordReset(hash, function (err, row) { db.lookupPasswordReset(hash, function (err, row) {
if (err) { if (err) {

View file

@ -15,7 +15,7 @@ function checkAdmin(cb) {
if (req.user.global_rank < 255) { if (req.user.global_rank < 255) {
res.send(403); res.send(403);
Logger.eventlog.log("[acp] Attempted GET "+req.path+" from non-admin " + Logger.eventlog.log("[acp] Attempted GET "+req.path+" from non-admin " +
user.name + "@" + webserver.ipForRequest(req)); user.name + "@" + req.realIP);
return; return;
} }

View file

@ -54,7 +54,7 @@ function handleLogin(req, res) {
if (err) { if (err) {
if (err === "Invalid username/password combination") { if (err === "Invalid username/password combination") {
Logger.eventlog.log("[loginfail] Login failed (bad password): " + name Logger.eventlog.log("[loginfail] Login failed (bad password): " + name
+ "@" + webserver.ipForRequest(req)); + "@" + req.realIP);
} }
sendJade(res, "login", { sendJade(res, "login", {
loggedIn: false, loggedIn: false,
@ -173,7 +173,7 @@ function handleRegister(req, res) {
if (typeof email !== "string") { if (typeof email !== "string") {
email = ""; email = "";
} }
var ip = webserver.ipForRequest(req); var ip = req.realIP;
if (typeof name !== "string" || typeof password !== "string") { if (typeof name !== "string" || typeof password !== "string") {
res.sendStatus(400); res.sendStatus(400);

View file

@ -0,0 +1,32 @@
import net from 'net';
export default function initialize(app, webConfig) {
function isTrustedProxy(ip) {
return webConfig.getTrustedProxies().indexOf(ip) >= 0;
}
function getForwardedIP(req) {
const xForwardedFor = req.header('x-forwarded-for');
if (!xForwardedFor) {
return req.ip;
}
const ipList = xForwardedFor.split(',');
for (let i = 0; i < ipList.length; i++) {
const ip = ipList[i].trim();
if (net.isIP(ip)) {
return ip;
}
}
return req.ip;
}
app.use((req, res, next) => {
if (isTrustedProxy(req.ip)) {
req.realIP = getForwardedIP(req);
}
next();
});
}

View file

@ -20,30 +20,7 @@ import * as HTTPStatus from './httpstatus';
import { CSRFError, HTTPError } from '../errors'; import { CSRFError, HTTPError } from '../errors';
const LOG_FORMAT = ':real-address - :remote-user [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"'; const LOG_FORMAT = ':real-address - :remote-user [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"';
morgan.token('real-address', function (req) { return req._ip; }); morgan.token('real-address', function (req) { return req.realIP; });
/**
* Extracts an IP address from a request. Uses X-Forwarded-For if the IP is localhost
*/
function ipForRequest(req) {
var ip = req.ip;
if (ip === "127.0.0.1" || ip === "::1") {
var xforward = req.header("x-forwarded-for");
if (typeof xforward !== "string") {
xforward = [];
} else {
xforward = xforward.split(",");
}
for (var i = 0; i < xforward.length; i++) {
if (net.isIP(xforward[i])) {
return xforward[i];
}
}
return ip;
}
return ip;
}
/** /**
* Redirects a request to HTTPS if the server supports it * Redirects a request to HTTPS if the server supports it
@ -87,7 +64,7 @@ function handleSocketConfig(req, res) {
var sioconfig = Config.get("sioconfig"); var sioconfig = Config.get("sioconfig");
var iourl; var iourl;
var ip = ipForRequest(req); var ip = req.realIP;
var ipv6 = false; var ipv6 = false;
if (net.isIPv6(ip)) { if (net.isIPv6(ip)) {
@ -115,10 +92,7 @@ module.exports = {
* Initializes webserver callbacks * Initializes webserver callbacks
*/ */
init: function (app, webConfig, ioConfig, clusterClient, channelIndex) { init: function (app, webConfig, ioConfig, clusterClient, channelIndex) {
app.use(function (req, res, next) { require("./middleware/x-forwarded-for")(app, webConfig);
req._ip = ipForRequest(req);
next();
});
app.use(bodyParser.urlencoded({ app.use(bodyParser.urlencoded({
extended: false, extended: false,
limit: '1kb' // No POST data should ever exceed this size under normal usage limit: '1kb' // No POST data should ever exceed this size under normal usage
@ -226,8 +200,6 @@ module.exports = {
}); });
}, },
ipForRequest: ipForRequest,
redirectHttps: redirectHttps, redirectHttps: redirectHttps,
redirectHttp: redirectHttp redirectHttp: redirectHttp