mirror of https://github.com/calzoneman/sync.git
Use `proxy-addr` for parsing x-forwarded-for
Closes #683 by providing functionality to trust proxies other than localhost.
This commit is contained in:
parent
9cffd7dde8
commit
76e0d1b7ec
|
@ -70,6 +70,9 @@ http:
|
||||||
index:
|
index:
|
||||||
# Maximum number of channels to display on the index page public channel list
|
# Maximum number of channels to display on the index page public channel list
|
||||||
max-entries: 50
|
max-entries: 50
|
||||||
|
# Configure trusted proxy addresses to map X-Forwarded-For to the client IP.
|
||||||
|
# See also: https://github.com/jshttp/proxy-addr
|
||||||
|
trust-proxies: ['loopback']
|
||||||
|
|
||||||
# HTTPS server details
|
# HTTPS server details
|
||||||
https:
|
https:
|
||||||
|
|
|
@ -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.39.0",
|
"version": "3.39.1",
|
||||||
"repository": {
|
"repository": {
|
||||||
"url": "http://github.com/calzoneman/sync"
|
"url": "http://github.com/calzoneman/sync"
|
||||||
},
|
},
|
||||||
|
@ -32,6 +32,7 @@
|
||||||
"mysql": "^2.9.0",
|
"mysql": "^2.9.0",
|
||||||
"nodemailer": "^1.4.0",
|
"nodemailer": "^1.4.0",
|
||||||
"oauth": "^0.9.12",
|
"oauth": "^0.9.12",
|
||||||
|
"proxy-addr": "^1.1.4",
|
||||||
"pug": "^2.0.0-beta3",
|
"pug": "^2.0.0-beta3",
|
||||||
"q": "^1.4.1",
|
"q": "^1.4.1",
|
||||||
"redis": "^2.4.2",
|
"redis": "^2.4.2",
|
||||||
|
|
|
@ -43,7 +43,10 @@ var defaults = {
|
||||||
"cookie-secret": "change-me",
|
"cookie-secret": "change-me",
|
||||||
index: {
|
index: {
|
||||||
"max-entries": 50
|
"max-entries": 50
|
||||||
}
|
},
|
||||||
|
"trust-proxies": [
|
||||||
|
"loopback"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
https: {
|
https: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
import clone from 'clone';
|
import clone from 'clone';
|
||||||
|
|
||||||
const DEFAULT_TRUSTED_PROXIES = Object.freeze([
|
|
||||||
'127.0.0.1',
|
|
||||||
'::1'
|
|
||||||
]);
|
|
||||||
|
|
||||||
export default class WebConfiguration {
|
export default class WebConfiguration {
|
||||||
constructor(config) {
|
constructor(config) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
@ -15,7 +10,7 @@ export default class WebConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
getTrustedProxies() {
|
getTrustedProxies() {
|
||||||
return DEFAULT_TRUSTED_PROXIES;
|
return this.config.trustProxies;
|
||||||
}
|
}
|
||||||
|
|
||||||
getCookieSecret() {
|
getCookieSecret() {
|
||||||
|
@ -76,5 +71,7 @@ WebConfiguration.fromOldConfig = function (oldConfig) {
|
||||||
|
|
||||||
config.maxIndexEntries = oldConfig.get('http.index.max-entries');
|
config.maxIndexEntries = oldConfig.get('http.index.max-entries');
|
||||||
|
|
||||||
|
config.trustProxies = oldConfig.get('http.trust-proxies');
|
||||||
|
|
||||||
return new WebConfiguration(config);
|
return new WebConfiguration(config);
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { LoggerFactory } from '@calzoneman/jsli';
|
||||||
const verifySession = Promise.promisify(session.verifySession);
|
const verifySession = Promise.promisify(session.verifySession);
|
||||||
const getAliases = Promise.promisify(db.getAliases);
|
const getAliases = Promise.promisify(db.getAliases);
|
||||||
import { CachingGlobalBanlist } from './globalban';
|
import { CachingGlobalBanlist } from './globalban';
|
||||||
|
import proxyaddr from 'proxy-addr';
|
||||||
|
|
||||||
const LOGGER = LoggerFactory.getLogger('ioserver');
|
const LOGGER = LoggerFactory.getLogger('ioserver');
|
||||||
|
|
||||||
|
@ -165,35 +166,13 @@ function addTypecheckedFunctions(sock) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ipForwardingMiddleware(webConfig) {
|
function ipForwardingMiddleware(webConfig) {
|
||||||
function getForwardedIP(socket) {
|
const trustFn = proxyaddr.compile(webConfig.getTrustedProxies());
|
||||||
var req = socket.client.request;
|
|
||||||
const xForwardedFor = req.headers['x-forwarded-for'];
|
|
||||||
if (!xForwardedFor) {
|
|
||||||
return socket.client.conn.remoteAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ipList = xForwardedFor.split(',');
|
|
||||||
for (let i = 0; i < ipList.length; i++) {
|
|
||||||
const ip = ipList[i].trim();
|
|
||||||
if (net.isIP(ip)) {
|
|
||||||
return ip;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return socket.client.conn.remoteAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isTrustedProxy(ip) {
|
|
||||||
return webConfig.getTrustedProxies().indexOf(ip) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return function (socket, accept) {
|
return function (socket, accept) {
|
||||||
if (isTrustedProxy(socket.client.conn.remoteAddress)) {
|
LOGGER.debug('ip = %s', socket.client.request.connection.remoteAddress);
|
||||||
socket._realip = getForwardedIP(socket);
|
//socket.client.request.ip = socket.client.conn.remoteAddress;
|
||||||
} else {
|
socket._realip = proxyaddr(socket.client.request, trustFn);
|
||||||
socket._realip = socket.client.conn.remoteAddress;
|
LOGGER.debug('socket._realip: %s', socket._realip);
|
||||||
}
|
|
||||||
|
|
||||||
accept(null, true);
|
accept(null, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,39 +1,24 @@
|
||||||
import net from 'net';
|
import proxyaddr from 'proxy-addr';
|
||||||
|
|
||||||
export default function initialize(app, webConfig) {
|
export function initialize(app, webConfig) {
|
||||||
function isTrustedProxy(ip) {
|
const trustFn = proxyaddr.compile(webConfig.getTrustedProxies());
|
||||||
return webConfig.getTrustedProxies().indexOf(ip) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getForwardedIP(req) {
|
app.use(readProxyHeaders.bind(null, trustFn));
|
||||||
const xForwardedFor = req.header('x-forwarded-for');
|
}
|
||||||
if (!xForwardedFor) {
|
|
||||||
return req.ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ipList = xForwardedFor.split(',');
|
function getForwardedProto(req) {
|
||||||
for (let i = 0; i < ipList.length; i++) {
|
|
||||||
const ip = ipList[i].trim();
|
|
||||||
if (net.isIP(ip)) {
|
|
||||||
return ip;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return req.ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getForwardedProto(req) {
|
|
||||||
const xForwardedProto = req.header('x-forwarded-proto');
|
const xForwardedProto = req.header('x-forwarded-proto');
|
||||||
if (xForwardedProto && xForwardedProto.match(/^https?$/)) {
|
if (xForwardedProto && xForwardedProto.match(/^https?$/)) {
|
||||||
return xForwardedProto;
|
return xForwardedProto;
|
||||||
} else {
|
} else {
|
||||||
return req.protocol;
|
return req.protocol;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
app.use((req, res, next) => {
|
function readProxyHeaders(trustFn, req, res, next) {
|
||||||
if (isTrustedProxy(req.ip)) {
|
const forwardedIP = proxyaddr(req, trustFn);
|
||||||
req.realIP = getForwardedIP(req);
|
if (forwardedIP !== req.ip) {
|
||||||
|
req.realIP = forwardedIP;
|
||||||
req.realProtocol = getForwardedProto(req);
|
req.realProtocol = getForwardedProto(req);
|
||||||
} else {
|
} else {
|
||||||
req.realIP = req.ip;
|
req.realIP = req.ip;
|
||||||
|
@ -41,5 +26,4 @@ export default function initialize(app, webConfig) {
|
||||||
}
|
}
|
||||||
|
|
||||||
next();
|
next();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,7 +138,7 @@ module.exports = {
|
||||||
counters.add("http:request", 1);
|
counters.add("http:request", 1);
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
require('./middleware/x-forwarded-for')(app, webConfig);
|
require('./middleware/x-forwarded-for').initialize(app, webConfig);
|
||||||
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
|
||||||
|
|
Loading…
Reference in New Issue