From eaff850d27bf0842437cc2f2db7df3a0aa59f7e7 Mon Sep 17 00:00:00 2001 From: Felix Hammerl Date: Tue, 14 Oct 2014 11:02:04 +0200 Subject: [PATCH] [WO-628] Restrict connections for socket.io proxy --- README.md | 18 ++++++++++++++++++ config/default.js | 11 +++++++++-- server.js | 17 ++++++++++++----- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 23e6334..96e9638 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,24 @@ Then start the server and navigate to [http://localhost:8585](http://localhost:8 **A note on security:** The app should not be used without SSL so it's best to set up a reverse proxy or Loadbalancer with your SSL certificates. If you are not sure how to do this it might be easier to use our managed web hosting or packaged apps under [https://whiteout.io/#product](https://whiteout.io/#product). +You can limit incoming and outgoing connections to the socket.io proxy by setting the following environment variables: + + # the web socket proxy listens to this port + # if unset, defaults to 8889 + PORT=12345 + + # the socket.io proxy accepts connections from these origins to tunnel them to tcp, + # separate with commas + # if unset, defaults to 'localhost:' + port + INBOUND_ORIGINS='foo:1234,bar:569' + + # the socket.io proxy opens tcp connections with these ports to tunnel them to socket.io + # separate with commas + # if unset, defaults to '143,465,587,993' (25 is forbidden by default) + OUTBOUND_PORTS='123,456,789' + +To start the server in development mode (no forced HTTPS, iframe loads http content), run `node server.js --dev` + ## License Copyright © 2014, Whiteout Networks GmbH. All rights reserved. diff --git a/config/default.js b/config/default.js index 5a7447f..1dab158 100644 --- a/config/default.js +++ b/config/default.js @@ -1,9 +1,16 @@ 'use strict'; +var port = process.env.PORT || 8889; + module.exports = { server: { - port: process.env.PORT || 8889, - host: "0.0.0.0" + port: port, + inboundOrigins: (process.env.INBOUND_ORIGINS || ('localhost:' + port)).split(',').map(function(host) { + return host.trim(); + }), + outboundPorts: (process.env.OUTBOUND_PORTS || '143,465,587,993').split(',').map(function(i) { + return parseInt(i, 10); + }) }, log: { level: "silly", diff --git a/server.js b/server.js index e6b71f0..386e34b 100644 --- a/server.js +++ b/server.js @@ -71,15 +71,14 @@ app.disable('x-powered-by'); // web server config // -var port = config.server.port, - development = process.argv[2] === '--dev'; +var development = (process.argv[2] === '--dev'); // set HTTP headers app.use(function(req, res, next) { // HSTS res.set('Strict-Transport-Security', 'max-age=16070400; includeSubDomains'); // CSP - var iframe = development ? "http://" + req.hostname + ":" + port : "https://" + req.hostname; // allow iframe to load assets + var iframe = development ? "http://" + req.hostname + ":" + config.server.port : "https://" + req.hostname; // allow iframe to load assets res.set('Content-Security-Policy', "default-src 'self' " + iframe + "; object-src 'none'; connect-src *; style-src 'self' 'unsafe-inline' " + iframe + "; img-src *"); // set Cache-control Header (for AppCache) res.set('Cache-control', 'public, max-age=0'); @@ -110,6 +109,8 @@ app.use(express.static(__dirname + '/dist')); // Socket.io proxy // +io.origins(config.server.inboundOrigins.join(' ')); + io.on('connection', function(socket) { log.info('io', 'New connection [%s]', socket.conn.id); @@ -120,6 +121,12 @@ io.on('connection', function(socket) { var socketId = ++idCounter; var tcp; + if (config.server.outboundPorts.indexOf(data.port) < 0) { + log.warn('io', 'Open request to %s:%s was rejected, closing [%s:%s]', data.host, data.port, socket.conn.id, socketId); + socket.disconnect(); + return; + } + log.verbose('io', 'Open request to %s:%s [%s:%s]', data.host, data.port, socket.conn.id, socketId); tcp = net.connect(data.port, data.host, function() { @@ -187,8 +194,8 @@ io.on('connection', function(socket) { // start server // -server.listen(port); +server.listen(config.server.port); if (development) { console.log(' > starting in development mode'); } -console.log(' > listening on http://localhost:' + port + '\n'); \ No newline at end of file +console.log(' > listening on http://localhost:' + config.server.port + '\n');