This commit is contained in:
2026-04-07 14:50:23 +09:00
commit b4e485502b
4778 changed files with 2017091 additions and 0 deletions

647
safekiso-server/index.js Normal file
View 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);
}