const cluster = require('cluster'); const numCPUs = require('os').cpus().length; if (cluster.isMaster) { console.log(`Master ${process.pid} is running`); console.log(`Total Workers ${numCPUs*8}`) // Fork workers for (let i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('exit', (worker, code, signal) => { console.log(`Worker ${worker.process.pid} died`); }); } else { const fs = require('fs'); const http = require('http'); const httpProxy = require('http-proxy'); const HyperDHTServer = require('hyperdht'); const b32 = require("hi-base32"); const net = require("net"); let invalid = false; const tunnels = {}; const agent = new http.Agent({ maxSockets: Number.MAX_VALUE }); const content = fs.readFileSync('404.txt.new', 'utf8'); const DEBUG = 0; // Set DEBUG to 1 to enable debug mode const CONINFO = 0; // Set CONINFO to 1 for a smaller breakdown of connections. const dhtServer = new HyperDHTServer(); const startServer = async () => { console.log(`Worker ${process.pid} started`); await dhtServer.ready(); const proxy = httpProxy.createProxyServer({ ws: true, agent: agent, timeout: 360000 }); const server = http.createServer(async function (req, res) { try { if (DEBUG === 1 || CONINFO === 1) console.log("Incoming HTTP request..."); const split = req.headers.host.split('.'); if (DEBUG === 1) console.log("Request Headers Host Split: ", split); const publicKey = Buffer.from(b32.decode.asBytes(split[0].toUpperCase())); if (DEBUG === 1) { console.log("Public Key Buffer: ", publicKey); console.log("Length: " + publicKey.length); } if (!(publicKey.length >= 32)) { console.log("Invalid Connection!") res.writeHead(418, { 'Content-Type': 'text/html' }); res.end(content); invalid = true } else { invalid = false } if (invalid == true) return if (!tunnels[publicKey]) { if (DEBUG === 1 || CONINFO === 1) console.log("No tunnel found for public key, creating new tunnel..."); const port = await getAvailablePort(); // Get an available port const server = net.createServer(function (servsock) { if (DEBUG === 1 || CONINFO === 1) console.log('Incoming Connection, Connecting to:', publicKey.toString('hex')); if (DEBUG === 1) console.log("Public Key Length: ", publicKey.toString('hex').length); const socket = dhtServer.connect(publicKey); const local = servsock; let open = { local: true, remote: true }; local.on('data', (d) => { if (DEBUG === 1) console.log("Local Data: ", d); socket.write(d); }); socket.on('data', (d) => { if (DEBUG === 1) console.log("Socket Data: ", d); local.write(d); }); const remoteend = (type) => { if (DEBUG === 1) console.log('Local Connection Ended, Ending Remote Connection'); if (open.remote) socket.end(); open.remote = false; }; const localend = (type) => { if (DEBUG === 1) console.log('Remote Connection Ended, Ending Local Connection'); if (open.local) local.end(); open.local = false; }; local.on('error', remoteend); local.on('finish', remoteend); local.on('end', remoteend); socket.on('finish', localend); socket.on('error', localend); socket.on('end', localend); }); // Check if the port is available server.listen(port, "127.0.0.1", () => { if (DEBUG === 1 | CONINFO === 1) console.log(`Tunnel server listening on port ${port}`); tunnels[publicKey] = port; if (DEBUG === 1 || CONINFO === 1) console.log("New tunnel created. Public Key:", publicKey, "Port:", port); proxy.web(req, res, { target: 'http://127.0.0.1:' + port }, function (e) { console.log("Proxy Web Error: ", e); res.writeHead(404, { 'Content-Type': 'text/html' }); res.end(content); }); }); return; } else { if (DEBUG === 1) console.log('Tunnel exists for public key:', publicKey); proxy.web(req, res, { target: 'http://127.0.0.1:' + tunnels[publicKey] }, function (e) { console.log("Proxy Web Error: ", e); res.writeHead(418, { 'Content-Type': 'text/html' }); res.end(content); }); } } catch (e) { console.error("Error Occurred: ", e); } }); server.on('upgrade', function (req, socket, head) { if (DEBUG === 1) console.log('Upgrade Request'); const split = req.headers.host.split('.'); const publicKey = Buffer.from(b32.decode.asBytes(split[0].toUpperCase())); proxy.ws(req, socket, { target: 'http://127.0.0.1:' + tunnels[publicKey] }, function (e) { console.error("Proxy WS Error: ", e); socket.end(); }); }); server.listen(8081, () => { console.log(`Worker ${process.pid} listening on port 8081`); }); }; startServer().catch(console.error); async function getAvailablePort() { let port; do { port = 1337 + Math.floor(Math.random() * 1000); // Generate a random port between 1337 and 2336 } while (Object.values(tunnels).includes(port)); // Check if the port is already used return port; } }