add port isolation (services only respond to their own ports), also rewrite pc services a bit. initial (very pre-alpha and not functional) https code added too
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
const tls = require('tls');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const zlib = require('zlib');
|
const zlib = require('zlib');
|
||||||
const http = require('http');
|
const http = require('http');
|
||||||
@@ -25,7 +26,7 @@ process
|
|||||||
.on('uncaughtException', (e => { console.log(e); }));
|
.on('uncaughtException', (e => { console.log(e); }));
|
||||||
|
|
||||||
|
|
||||||
function shutdown(signal) {
|
function shutdown(signal = 'SIGTERM') {
|
||||||
return (err) => {
|
return (err) => {
|
||||||
console.log("Received signal", signal);
|
console.log("Received signal", signal);
|
||||||
if (err) console.error(err.stack || err);
|
if (err) console.error(err.stack || err);
|
||||||
@@ -431,16 +432,35 @@ async function processPath(socket, service_vault_file_path, request_headers = ne
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function verifyServicePort(service_name, socket) {
|
||||||
|
if (socket._server._connectionKey) {
|
||||||
|
var socketPort = parseInt(socket._server._connectionKey.split(':')[2])
|
||||||
|
if (minisrv_config.services[service_name]) {
|
||||||
|
if (minisrv_config.services[service_name].port == socketPort) {
|
||||||
|
if (minisrv_config.services[service_name].servicevault_dir)
|
||||||
|
return minisrv_config.services[service_name].servicevault_dir;
|
||||||
|
else
|
||||||
|
return service_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
async function processURL(socket, request_headers) {
|
async function processURL(socket, request_headers) {
|
||||||
console.log(request_headers)
|
|
||||||
var shortURL, headers, data = "";
|
var shortURL, headers, data = "";
|
||||||
var enable_multi_query = false;
|
var enable_multi_query = false;
|
||||||
socket.minisrv_pc_mode = false;
|
|
||||||
request_headers.query = new Array();
|
request_headers.query = new Array();
|
||||||
if (request_headers.request_url) {
|
if (request_headers.request_url) {
|
||||||
if (request_headers.request_url.indexOf('?') >= 0) {
|
if (request_headers.request_url.indexOf('?') >= 0) {
|
||||||
shortURL = request_headers.request_url.split('?')[0];
|
shortURL = request_headers.request_url.split('?')[0];
|
||||||
service_name = shortURL.split(':')[0];
|
service_name = verifyServicePort(shortURL.split(':')[0], socket);
|
||||||
|
if (!service_name) {
|
||||||
|
var errpage = wtvshared.doErrorPage(500, null, socket.minisrv_pc_mode);
|
||||||
|
socket_sessions[socket.id].close_me = true;
|
||||||
|
sendToClient(socket, errpage[0], errpage[1]);
|
||||||
|
return
|
||||||
|
}
|
||||||
if (minisrv_config.services[service_name]) enable_multi_query = minisrv_config.services[service_name].enable_multi_query || false;
|
if (minisrv_config.services[service_name]) enable_multi_query = minisrv_config.services[service_name].enable_multi_query || false;
|
||||||
var qraw = request_headers.request_url.split('?')[1];
|
var qraw = request_headers.request_url.split('?')[1];
|
||||||
if (qraw.length > 0) {
|
if (qraw.length > 0) {
|
||||||
@@ -530,14 +550,30 @@ async function processURL(socket, request_headers) {
|
|||||||
shortURL = shortURL_service_name + ":/" + shortURL_service_path;
|
shortURL = shortURL_service_name + ":/" + shortURL_service_path;
|
||||||
} else if (shortURL.indexOf(":") == -1 && request_headers.request.indexOf("HTTP/1") > 0 && socket.ssid == null) {
|
} else if (shortURL.indexOf(":") == -1 && request_headers.request.indexOf("HTTP/1") > 0 && socket.ssid == null) {
|
||||||
if (request_headers.Host) {
|
if (request_headers.Host) {
|
||||||
if (minisrv_config.config.pc_server_hidden_service_enabled) {
|
if (minisrv_config.services.pc_services) {
|
||||||
|
if (!minisrv_config.services.pc_services.disabled) {
|
||||||
// browsers typically send a Host header
|
// browsers typically send a Host header
|
||||||
service_name = minisrv_config.config.pc_server_hidden_service;
|
|
||||||
socket.minisrv_pc_mode = true;
|
socket.minisrv_pc_mode = true;
|
||||||
shortURL = service_name + ":" + shortURL;
|
service_name = verifyServicePort("pc_services", socket);
|
||||||
|
if (!service_name) {
|
||||||
|
var errpage = wtvshared.doErrorPage(500, null, socket.minisrv_pc_mode);
|
||||||
|
socket_sessions[socket.id].close_me = true;
|
||||||
|
sendToClient(socket, errpage[0], errpage[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// if a directory, request index
|
// if a directory, request index
|
||||||
if (shortURL.substring(shortURL.length - 1) == "/") shortURL += "index";
|
if (shortURL.substring(shortURL.length - 1) == "/") shortURL += "index";
|
||||||
|
shortURL = service_name + ":" + shortURL;
|
||||||
|
} else {
|
||||||
|
// minimal pc mode to send error
|
||||||
|
socket.minisrv_pc_mode = true;
|
||||||
|
var errpage = wtvshared.doErrorPage(401, "PC services are disabled on this server", socket.minisrv_pc_mode);
|
||||||
|
headers = errpage[0];
|
||||||
|
data = errpage[1]
|
||||||
|
socket_sessions[socket.id].close_me = true;
|
||||||
|
sendToClient(socket, headers, data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// minimal pc mode to send error
|
// minimal pc mode to send error
|
||||||
socket.minisrv_pc_mode = true;
|
socket.minisrv_pc_mode = true;
|
||||||
@@ -550,7 +586,8 @@ async function processURL(socket, request_headers) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!socket.minisrv_pc_mode) {
|
|
||||||
|
if (!socket.minisrv_pc_mode && !socket.ssid) {
|
||||||
// skip box auth tests for pc mode
|
// skip box auth tests for pc mode
|
||||||
|
|
||||||
// check security
|
// check security
|
||||||
@@ -614,8 +651,15 @@ minisrv-no-mail-count: true`;
|
|||||||
} else {
|
} else {
|
||||||
console.log(" * " + reqverb + " for " + request_headers.request_url, 'on', socket.id);
|
console.log(" * " + reqverb + " for " + request_headers.request_url, 'on', socket.id);
|
||||||
}
|
}
|
||||||
// assume webtv since there is a :/ in the GET
|
if (!socket.minisrv_pc_mode) {
|
||||||
var service_name = shortURL.split(':/')[0];
|
var service_name = verifyServicePort(shortURL.split(':/')[0], socket);
|
||||||
|
if (!service_name) {
|
||||||
|
var errpage = wtvshared.doErrorPage(500, null, socket.minisrv_pc_mode);
|
||||||
|
socket_sessions[socket.id].close_me = true;
|
||||||
|
sendToClient(socket, errpage[0], errpage[1]);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
var urlToPath = wtvshared.fixPathSlashes(service_name + path.sep + shortURL.split(':/')[1]);
|
var urlToPath = wtvshared.fixPathSlashes(service_name + path.sep + shortURL.split(':/')[1]);
|
||||||
var shared_romcache = null;
|
var shared_romcache = null;
|
||||||
if (shortURL.indexOf(":/ROMCache/") != -1 && minisrv_config.config.enable_shared_romcache) {
|
if (shortURL.indexOf(":/ROMCache/") != -1 && minisrv_config.config.enable_shared_romcache) {
|
||||||
@@ -1429,6 +1473,13 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq
|
|||||||
} else {
|
} else {
|
||||||
socket_sessions[socket.id].headers = headers;
|
socket_sessions[socket.id].headers = headers;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (!socket.ssid) {
|
||||||
|
// incomplete, dont use https on pc services yet
|
||||||
|
socket = new tls.TLSSocket(socket);
|
||||||
|
socket.minisrv_pc_mode = true;
|
||||||
|
console.log(socket)
|
||||||
|
console.log("pc https?");
|
||||||
} else {
|
} else {
|
||||||
// handle streaming POST
|
// handle streaming POST
|
||||||
if (socket_sessions[socket.id].expecting_post_data && headers) {
|
if (socket_sessions[socket.id].expecting_post_data && headers) {
|
||||||
@@ -1494,7 +1545,6 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq
|
|||||||
sendToClient(socket, headers, data);
|
sendToClient(socket, headers, data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (!skipSecure) {
|
} else if (!skipSecure) {
|
||||||
if (!encryptedRequest) {
|
if (!encryptedRequest) {
|
||||||
if (socket_sessions[socket.id].secure != true) {
|
if (socket_sessions[socket.id].secure != true) {
|
||||||
@@ -1558,6 +1608,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function cleanupSocket(socket) {
|
async function cleanupSocket(socket) {
|
||||||
try {
|
try {
|
||||||
@@ -1806,14 +1857,16 @@ ports.sort();
|
|||||||
// de-duplicate ports in case user configured multiple services on same port
|
// de-duplicate ports in case user configured multiple services on same port
|
||||||
const bind_ports = [...new Set(ports)]
|
const bind_ports = [...new Set(ports)]
|
||||||
if (!minisrv_config.config.bind_ip) minisrv_config.config.bind_ip = "0.0.0.0";
|
if (!minisrv_config.config.bind_ip) minisrv_config.config.bind_ip = "0.0.0.0";
|
||||||
bind_ports.forEach(function (v) {
|
bind_ports.every(function (v) {
|
||||||
try {
|
try {
|
||||||
var server = net.createServer(handleSocket);
|
var server = net.createServer(handleSocket);
|
||||||
server.listen(v, minisrv_config.config.bind_ip);
|
server.listen(v, minisrv_config.config.bind_ip);
|
||||||
initstring += v + ", ";
|
initstring += v + ", ";
|
||||||
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw ("Could not bind to port", v, "on", minisrv_config.config.bind_ip, e.toString());
|
throw ("Could not bind to port", v, "on", minisrv_config.config.bind_ip, e.toString());
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
initstring = initstring.substring(0, initstring.length - 2);
|
initstring = initstring.substring(0, initstring.length - 2);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"config": {
|
"config": {
|
||||||
"service_ip": "127.0.0.1",
|
"service_ip": "127.0.0.1",
|
||||||
|
"bind_ip": "0.0.0.0",
|
||||||
"ServiceVaults": [
|
"ServiceVaults": [
|
||||||
"UserServiceVault",
|
"UserServiceVault",
|
||||||
"ServiceVault"
|
"ServiceVault"
|
||||||
@@ -26,8 +27,6 @@
|
|||||||
"hide_incomplete_features": true,
|
"hide_incomplete_features": true,
|
||||||
"enable_lzpf_compression": true,
|
"enable_lzpf_compression": true,
|
||||||
"enable_gzip_compression": true,
|
"enable_gzip_compression": true,
|
||||||
"pc_server_hidden_service": "http_pc",
|
|
||||||
"pc_server_hidden_service_enabled": false,
|
|
||||||
"show_detailed_splash": true,
|
"show_detailed_splash": true,
|
||||||
"show_diskmap": false,
|
"show_diskmap": false,
|
||||||
"unauthorized_url": "wtv-1800:/unauthorized?",
|
"unauthorized_url": "wtv-1800:/unauthorized?",
|
||||||
@@ -129,6 +128,13 @@
|
|||||||
"external_proxy_host": "127.0.0.1",
|
"external_proxy_host": "127.0.0.1",
|
||||||
"external_proxy_port": 1080,
|
"external_proxy_port": 1080,
|
||||||
"flags": "0x00000001"
|
"flags": "0x00000001"
|
||||||
|
},
|
||||||
|
"pc_services": {
|
||||||
|
"port": 1699,
|
||||||
|
"servicevault_dir": "http_pc",
|
||||||
|
"disabled": true,
|
||||||
|
"allow_https": false,
|
||||||
|
"force_https": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user