-
Notifications
You must be signed in to change notification settings - Fork 0
/
force_ssl_server.js
executable file
·74 lines (62 loc) · 2.7 KB
/
force_ssl_server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
var url = Npm.require("url");
// Unfortunately we can't use a connect middleware here since
// sockjs installs itself prior to all existing listeners
// (meaning prior to any connect middlewares) so we need to take
// an approach similar to overshadowListeners in
// https://github.com/sockjs/sockjs-node/blob/cf820c55af6a9953e16558555a31decea554f70e/src/utils.coffee
var httpServer = WebApp.httpServer;
var oldHttpServerListeners = httpServer.listeners('request').slice(0);
httpServer.removeAllListeners('request');
httpServer.addListener('request', function (req, res) {
// allow connections if they have been handled w/ ssl already
// (either by us or by a proxy) OR the connection is entirely over
// localhost (development mode).
//
// Note: someone could trick us into serving over non-ssl by setting
// x-forwarded-for or x-forwarded-proto. Not much we can do there if
// we still want to operate behind proxies.
var remoteAddress =
req.connection.remoteAddress || req.socket.remoteAddress;
// Determine if the connection is only over localhost. Both we
// received it on localhost, and all proxies involved received on
// localhost.
var localhostRegexp = /^\s*(127\.0\.0\.1|::1)\s*$/;
var isLocal = (
localhostRegexp.test(remoteAddress) &&
(!req.headers['x-forwarded-for'] ||
_.all(req.headers['x-forwarded-for'].split(','), function (x) {
return localhostRegexp.test(x);
})));
// Determine if the connection was over SSL at any point. Either we
// received it as SSL, or a proxy did and translated it for us.
var isSsl = req.connection.pair ||
(req.headers['x-forwarded-proto'] &&
req.headers['x-forwarded-proto'].indexOf('https') !== -1);
if (!isLocal && !isSsl) {
// connection is not cool. send a 302 redirect!
var host = req.headers['host'];
// strip off the port number. If we went to a URL with a custom
// port, we don't know what the custom SSL port is anyway.
host = host.replace(/:\d+$/, '');
res.writeHead(302, {
'Location': 'https://' + host + req.url
});
res.end();
return;
}
// connection is OK. Proceed normally.
var args = arguments;
_.each(oldHttpServerListeners, function(oldListener) {
oldListener.apply(httpServer, args);
});
});
// NOTE: this doesn't handle websockets!
//
// Websockets come in via the 'upgrade' request. We can override this,
// however the problem is we're not sure if the websocket is actually
// encrypted. We don't get x-forwarded-for or x-forwarded-proto on
// websockets. It's possible the 'sec-websocket-origin' header does
// what we want, but that's not clear.
//
// For now, this package allows raw unencrypted DDP connections over
// websockets.