first
This commit is contained in:
647
safekiso-server/index.js
Normal file
647
safekiso-server/index.js
Normal file
@@ -0,0 +1,647 @@
|
||||
var utils = require('./src/utils');
|
||||
var crossCtl = require('./src/crossCtl');
|
||||
|
||||
var app = null;
|
||||
var http = null;
|
||||
var https = null;
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
var bouncy = require('bouncy');
|
||||
var crypto = require('crypto');
|
||||
var tls = require('tls');
|
||||
|
||||
const WebSocket = require('ws');
|
||||
var wss = new WebSocket.Server({ noServer: true });
|
||||
|
||||
wss.on('connection', function connection(ws, req) {
|
||||
crossCtl.addWebsockHandle(ws, req);
|
||||
});
|
||||
|
||||
var httpProxy = require('http-proxy');
|
||||
var proxy = httpProxy.createProxyServer({ ws: true });
|
||||
|
||||
proxy.on('error', function (err, req, res) {
|
||||
console.log('err=', err);
|
||||
if (typeof res.writeHead == 'function') {
|
||||
res.writeHead(500, {
|
||||
'Content-Type': 'text/plain',
|
||||
});
|
||||
}
|
||||
res.end(
|
||||
'Something went wrong. And we are reporting a custom error message.'
|
||||
);
|
||||
});
|
||||
|
||||
proxy.on('upgrade', function (req, socket, head) {
|
||||
proxy.ws(req, socket, head);
|
||||
});
|
||||
|
||||
/*
|
||||
var httpsOptions = {
|
||||
key: fs.readFileSync('./cert/dev2/privkey1.pem'),
|
||||
cert: fs.readFileSync('./cert/dev2/cert1.pem')
|
||||
}
|
||||
*/
|
||||
|
||||
var express = require('express');
|
||||
|
||||
proxy.on('proxyReq', function (proxyReq, req, res, options) {
|
||||
proxyReq.setHeader('x-forwarded-for', utils.getIPFromReq(req));
|
||||
proxyReq.setHeader('x-forwarded-by', 'bouncy');
|
||||
});
|
||||
|
||||
var ipHashPool = {};
|
||||
|
||||
function doProxyWorkWS(req, socket, head) {
|
||||
var targetHost = req.headers.host ? req.headers.host.toLowerCase() : '';
|
||||
// console.log('targetHost=', targetHost)
|
||||
|
||||
if (config.bouncy.names.includes(targetHost)) {
|
||||
var ip = utils.getIPFromReq(req);
|
||||
// console.log('fromIP=', ip)
|
||||
|
||||
var hashedIdx = ipHashPool[ip];
|
||||
if (hashedIdx === undefined) {
|
||||
hashedIdx = utils.getRandomInt(
|
||||
0,
|
||||
config.bouncy.destinations[targetHost].hosts
|
||||
? config.bouncy.destinations[targetHost].hosts.length - 1
|
||||
: 0
|
||||
);
|
||||
console.log('hashedIdx for ', ip, ' is ', hashedIdx);
|
||||
ipHashPool[ip] = hashedIdx;
|
||||
}
|
||||
|
||||
// var toHost = (config.bouncy.destinations[targetHost].hosts ? utils.pickCandy (config.bouncy.destinations[targetHost].hosts, targetHost) : undefined)
|
||||
var toHost = config.bouncy.destinations[targetHost].hosts
|
||||
? config.bouncy.destinations[targetHost].hosts[hashedIdx]
|
||||
: undefined;
|
||||
var toPort = config.bouncy.destinations[targetHost].port;
|
||||
var toUrl = config.bouncy.destinations[targetHost].url;
|
||||
|
||||
var toTarget = toUrl
|
||||
? toUrl
|
||||
: 'http://' +
|
||||
(toHost ? toHost : utils.getMyPrivateIp()) +
|
||||
':' +
|
||||
toPort;
|
||||
|
||||
// console.log('toTarget=', toTarget)
|
||||
|
||||
proxy.ws(req, socket, head, { target: toTarget });
|
||||
// res.statusCode = 200;
|
||||
// res.end('ok for now');
|
||||
}
|
||||
}
|
||||
|
||||
function doProxyWork(req, res, next) {
|
||||
var targetHost = req.headers.host ? req.headers.host.toLowerCase() : '';
|
||||
// console.log('targetHost=', targetHost)
|
||||
|
||||
var fullUrl =
|
||||
req.protocol + '://' + targetHost + req.originalUrl.toLowerCase();
|
||||
// console.log('fullUrl=', fullUrl)
|
||||
|
||||
if (config.bouncy.names.includes(targetHost)) {
|
||||
var ip = utils.getIPFromReq(req);
|
||||
// console.log('fromIP=', ip)
|
||||
|
||||
let protocol = req.headers['x-forwarded-proto'] || req.protocol;
|
||||
let sshDiff = 0;
|
||||
if (protocol == 'https') {
|
||||
sshDiff += config.bouncy.sshDiff;
|
||||
}
|
||||
|
||||
var hashedIdx = ipHashPool[ip];
|
||||
if (hashedIdx === undefined) {
|
||||
hashedIdx = utils.getRandomInt(
|
||||
0,
|
||||
config.bouncy.destinations[targetHost].hosts
|
||||
? config.bouncy.destinations[targetHost].hosts.length - 1
|
||||
: 0
|
||||
);
|
||||
// console.log("hashedIdx for ", ip, " is ", hashedIdx);
|
||||
ipHashPool[ip] = hashedIdx;
|
||||
}
|
||||
|
||||
// var toHost = (config.bouncy.destinations[targetHost].hosts ? utils.pickCandy (config.bouncy.destinations[targetHost].hosts, targetHost) : undefined)
|
||||
var toHost = config.bouncy.destinations[targetHost].hosts
|
||||
? config.bouncy.destinations[targetHost].hosts[hashedIdx]
|
||||
: undefined;
|
||||
var toPort = config.bouncy.destinations[targetHost].port;
|
||||
var toUrl = config.bouncy.destinations[targetHost].url;
|
||||
|
||||
if (config.bouncy.destinations[targetHost].shareSSL === true) {
|
||||
sshDiff = 0;
|
||||
protocol = 'http';
|
||||
}
|
||||
|
||||
var toTarget = toUrl
|
||||
? toUrl
|
||||
: protocol +
|
||||
'://' +
|
||||
(toHost ? toHost : utils.getMyPrivateIp()) +
|
||||
':' +
|
||||
(toPort + sshDiff);
|
||||
|
||||
// console.log("toTarget=", toTarget);
|
||||
|
||||
proxy.web(req, res, { target: toTarget });
|
||||
// res.statusCode = 200;
|
||||
// res.end('ok for now');
|
||||
} else {
|
||||
if (
|
||||
targetHost === utils.getMyPublicIP() ||
|
||||
targetHost === utils.getMyPrivateIp()
|
||||
) {
|
||||
if (req.url.toLowerCase() === '/ping') {
|
||||
// console.log('pong!')
|
||||
res.statusCode = 200;
|
||||
res.end('pong');
|
||||
} else if (req.url.toLowerCase() === '/admin/heapdump') {
|
||||
utils.doHeapdump(
|
||||
crossCtl.sConfig.debug,
|
||||
'heapsnapshot_of_' +
|
||||
crossCtl.sConfig.sid +
|
||||
'_' +
|
||||
utils.getNow().replace(' ', '_') +
|
||||
'.heapsnapshot',
|
||||
function (error, resultPath) {
|
||||
// console.log('heapsnapshot saved...')
|
||||
res.statusCode = 200;
|
||||
res.end('heapsnapshot saved...');
|
||||
}
|
||||
);
|
||||
} else {
|
||||
res.statusCode = 404;
|
||||
res.end('Failed host lookup: ' + targetHost);
|
||||
}
|
||||
} else {
|
||||
res.statusCode = 404;
|
||||
res.end('Failed host lookup: ' + targetHost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var server = null;
|
||||
|
||||
var minimist = require('minimist');
|
||||
var argv = minimist(process.argv.slice(2));
|
||||
|
||||
var configName = argv.config ? argv.config : argv.c;
|
||||
var serviceName = argv.service ? argv.service : argv.s;
|
||||
utils.setServiceName(serviceName);
|
||||
|
||||
if (configName === undefined) {
|
||||
utils.log('error', 'need configName. use -c or -config flag');
|
||||
process.exit(1);
|
||||
} else if (serviceName === undefined) {
|
||||
utils.log('error', 'need serviceName. use -s or -service flag');
|
||||
process.exit(1);
|
||||
} else {
|
||||
var config = require(configName);
|
||||
utils.getLogger(serviceName, config.configPool[serviceName].log);
|
||||
|
||||
crossCtl.s3.init(
|
||||
{
|
||||
...config.options.aws,
|
||||
type: config.configPool[serviceName].type,
|
||||
},
|
||||
function (err) {
|
||||
if (err) {
|
||||
utils.log('error', 's3 init error : ' + err);
|
||||
process.exit(1);
|
||||
} else {
|
||||
crossCtl.boom.init(
|
||||
{ ...config.configPool[serviceName], sid: serviceName },
|
||||
function (err) {
|
||||
if (err) {
|
||||
utils.log('error', 'boom init error : ' + err);
|
||||
process.exit(1);
|
||||
} else {
|
||||
crossCtl.init(config, serviceName, function (err) {
|
||||
if (err) {
|
||||
utils.log(
|
||||
'error',
|
||||
'crossCtl init error : ' + err
|
||||
);
|
||||
process.exit(1);
|
||||
} else {
|
||||
utils.log('info', 'crossCtl init ok');
|
||||
if (
|
||||
crossCtl.config.options
|
||||
.bootupReportFlag === true
|
||||
) {
|
||||
utils.mail.sendMonitorMail(
|
||||
'bootup report',
|
||||
'server boot up'
|
||||
);
|
||||
}
|
||||
var httpPort = normalizePort(
|
||||
crossCtl.config.configPool[serviceName]
|
||||
.port
|
||||
);
|
||||
var httpsPort =
|
||||
httpPort + config.bouncy.sshDiff;
|
||||
|
||||
if (
|
||||
crossCtl.config.configPool[serviceName]
|
||||
.type === 'bouncy'
|
||||
) {
|
||||
var names = [];
|
||||
Object.keys(
|
||||
config.bouncy.destinations
|
||||
).forEach(function (name) {
|
||||
names[names.length] = name;
|
||||
var tmpBouncyItem =
|
||||
config.bouncy.destinations[
|
||||
name
|
||||
];
|
||||
|
||||
if (
|
||||
config.configPool[
|
||||
tmpBouncyItem.type + '1'
|
||||
] !== undefined
|
||||
) {
|
||||
var creds = {
|
||||
key: fs.readFileSync(
|
||||
config.configPool[
|
||||
tmpBouncyItem.type +
|
||||
'1'
|
||||
].certPaths.privateKey,
|
||||
'utf8'
|
||||
),
|
||||
cert: fs.readFileSync(
|
||||
config.configPool[
|
||||
tmpBouncyItem.type +
|
||||
'1'
|
||||
].certPaths.certificate,
|
||||
'utf8'
|
||||
),
|
||||
ca: fs.readFileSync(
|
||||
config.configPool[
|
||||
tmpBouncyItem.type +
|
||||
'1'
|
||||
].certPaths.ca,
|
||||
'utf8'
|
||||
),
|
||||
};
|
||||
var ctx = tls.createSecureContext(
|
||||
creds
|
||||
);
|
||||
tmpBouncyItem.ctx = ctx;
|
||||
} else {
|
||||
var creds = {
|
||||
key: fs.readFileSync(
|
||||
config.configPool[
|
||||
'bouncy'
|
||||
].certPaths.privateKey,
|
||||
'utf8'
|
||||
),
|
||||
cert: fs.readFileSync(
|
||||
config.configPool[
|
||||
'bouncy'
|
||||
].certPaths.certificate,
|
||||
'utf8'
|
||||
),
|
||||
ca: fs.readFileSync(
|
||||
config.configPool[
|
||||
'bouncy'
|
||||
].certPaths.ca,
|
||||
'utf8'
|
||||
),
|
||||
};
|
||||
var ctx = tls.createSecureContext(
|
||||
creds
|
||||
);
|
||||
|
||||
tmpBouncyItem.ctx = ctx;
|
||||
}
|
||||
});
|
||||
config.bouncy.names = names;
|
||||
|
||||
http = require('http');
|
||||
https = require('https');
|
||||
app = express();
|
||||
app.use(function (req, res, next) {
|
||||
doProxyWork(req, res, next);
|
||||
});
|
||||
|
||||
var serverHttp = http.createServer(app);
|
||||
|
||||
serverHttp.on(
|
||||
'upgrade',
|
||||
function upgrade(
|
||||
req,
|
||||
socket,
|
||||
head
|
||||
) {
|
||||
doProxyWorkWS(
|
||||
req,
|
||||
socket,
|
||||
head
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
// doProxyWork(req, res)
|
||||
serverHttp.on('error', onError);
|
||||
|
||||
serverHttp.listen(
|
||||
httpPort,
|
||||
'localhost',
|
||||
onListening
|
||||
); // , '172.26.6.46'
|
||||
|
||||
serverHttp.listen(
|
||||
7890,
|
||||
'localhost',
|
||||
onListening
|
||||
);
|
||||
serverHttp.listen(
|
||||
httpPort,
|
||||
utils.getMyPrivateIp(),
|
||||
onListening
|
||||
);
|
||||
|
||||
var httpsOptions = {
|
||||
SNICallback: function (
|
||||
servername,
|
||||
cb
|
||||
) {
|
||||
// console.log("serverHttps(), SNICallback(), servername=",servername);
|
||||
var info =
|
||||
config.bouncy.destinations[
|
||||
servername
|
||||
];
|
||||
// console.log("info =", info);
|
||||
if (info !== undefined) {
|
||||
cb(null, info.ctx.context);
|
||||
} else {
|
||||
cb(new Error('miss'), null);
|
||||
}
|
||||
},
|
||||
key: fs.readFileSync(
|
||||
config.configPool['bouncy']
|
||||
.certPaths.privateKey,
|
||||
'utf8'
|
||||
),
|
||||
cert: fs.readFileSync(
|
||||
config.configPool['bouncy']
|
||||
.certPaths.certificate,
|
||||
'utf8'
|
||||
),
|
||||
ca: fs.readFileSync(
|
||||
config.configPool['bouncy']
|
||||
.certPaths.ca,
|
||||
'utf8'
|
||||
),
|
||||
};
|
||||
|
||||
var serverHttps = https.createServer(
|
||||
httpsOptions,
|
||||
app
|
||||
);
|
||||
|
||||
serverHttps.on(
|
||||
'upgrade',
|
||||
function upgrade(
|
||||
req,
|
||||
socket,
|
||||
head
|
||||
) {
|
||||
doProxyWorkWS(
|
||||
req,
|
||||
socket,
|
||||
head
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
serverHttps.on('error', onError);
|
||||
|
||||
serverHttps.listen(
|
||||
httpsPort,
|
||||
'localhost',
|
||||
onListening
|
||||
);
|
||||
serverHttps.listen(
|
||||
httpsPort,
|
||||
utils.getMyPrivateIp(),
|
||||
onListening
|
||||
);
|
||||
} else {
|
||||
app = require('./app');
|
||||
app.set('trust proxy', true);
|
||||
|
||||
http = require('http');
|
||||
https = require('https');
|
||||
|
||||
app.set('port', httpPort);
|
||||
|
||||
server = http.createServer(app);
|
||||
server.on('error', onError);
|
||||
server.on('listening', onListening);
|
||||
server.listen(
|
||||
normalizePort(
|
||||
crossCtl.config.configPool[
|
||||
serviceName
|
||||
].port
|
||||
),
|
||||
'localhost'
|
||||
);
|
||||
|
||||
server.listen(
|
||||
normalizePort(
|
||||
crossCtl.config.configPool[
|
||||
serviceName
|
||||
].port
|
||||
),
|
||||
utils.getMyPrivateIp(),
|
||||
onListening
|
||||
);
|
||||
|
||||
server.on('upgrade', function upgrade(
|
||||
request,
|
||||
socket,
|
||||
head
|
||||
) {
|
||||
wss.handleUpgrade(
|
||||
request,
|
||||
socket,
|
||||
head,
|
||||
function done(ws) {
|
||||
wss.emit(
|
||||
'connection',
|
||||
ws,
|
||||
request
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
var httpsOptions = {
|
||||
key: fs.readFileSync(
|
||||
config.configPool[serviceName]
|
||||
.certPaths.privateKey,
|
||||
'utf8'
|
||||
),
|
||||
cert: fs.readFileSync(
|
||||
config.configPool[serviceName]
|
||||
.certPaths.certificate,
|
||||
'utf8'
|
||||
),
|
||||
ca: fs.readFileSync(
|
||||
config.configPool[serviceName]
|
||||
.certPaths.ca,
|
||||
'utf8'
|
||||
),
|
||||
};
|
||||
|
||||
var httpsServer1 = https
|
||||
.createServer(httpsOptions, app)
|
||||
.listen(
|
||||
httpsPort,
|
||||
'localhost',
|
||||
function () {
|
||||
console.log(
|
||||
'Https server listening on port ' +
|
||||
httpsPort
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
/*
|
||||
https.createServer(httpsOptions, app).listen(httpsPort, 'localhost', function () {
|
||||
console.log('Https server listening on port ' + httpsPort)
|
||||
})
|
||||
*/
|
||||
var httpsServer2 = https
|
||||
.createServer(httpsOptions, app)
|
||||
.listen(
|
||||
httpsPort,
|
||||
utils.getMyPrivateIp(),
|
||||
function () {
|
||||
console.log(
|
||||
'Https server listening on port ' +
|
||||
httpsPort
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
httpsServer1.on(
|
||||
'upgrade',
|
||||
function upgrade(
|
||||
request,
|
||||
socket,
|
||||
head
|
||||
) {
|
||||
wss.handleUpgrade(
|
||||
request,
|
||||
socket,
|
||||
head,
|
||||
function done(ws) {
|
||||
wss.emit(
|
||||
'connection',
|
||||
ws,
|
||||
request
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
httpsServer2.on(
|
||||
'upgrade',
|
||||
function upgrade(
|
||||
request,
|
||||
socket,
|
||||
head
|
||||
) {
|
||||
wss.handleUpgrade(
|
||||
request,
|
||||
socket,
|
||||
head,
|
||||
function done(ws) {
|
||||
wss.emit(
|
||||
'connection',
|
||||
ws,
|
||||
request
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function normalizePort(val) {
|
||||
var port = parseInt(val, 10);
|
||||
|
||||
if (isNaN(port)) {
|
||||
// named pipe
|
||||
return val;
|
||||
}
|
||||
|
||||
if (port >= 0) {
|
||||
// port number
|
||||
return port;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "error" event.
|
||||
*/
|
||||
|
||||
function onClose() {
|
||||
crossCtl.killGoAccess();
|
||||
}
|
||||
|
||||
function onError(error) {
|
||||
if (error.syscall !== 'listen') {
|
||||
throw error;
|
||||
}
|
||||
|
||||
var bind =
|
||||
typeof crossCtl.config.configPool[serviceName].port === 'string'
|
||||
? 'Pipe ' + crossCtl.config.configPool[serviceName].port
|
||||
: 'Port ' + crossCtl.config.configPool[serviceName].port;
|
||||
|
||||
// handle specific listen errors with friendly messages
|
||||
var exitFlag = false;
|
||||
switch (error.code) {
|
||||
case 'EACCES':
|
||||
console.error(bind + ' requires elevated privileges');
|
||||
exitFlag = true;
|
||||
break;
|
||||
|
||||
case 'EADDRINUSE':
|
||||
console.error(bind + ' is already in use');
|
||||
exitFlag = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (exitFlag === true) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
function onListening() {
|
||||
var addr = this.address();
|
||||
var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port;
|
||||
utils.log('info', 'Listening on ' + bind);
|
||||
}
|
||||
Reference in New Issue
Block a user