diff --git a/newServer.ts b/newServer.ts deleted file mode 100644 index b70d7ba..0000000 --- a/newServer.ts +++ /dev/null @@ -1,160 +0,0 @@ -import fastify from "fastify"; -import fastifyStatic from "@fastify/static"; -import { fileURLToPath } from "url"; -import path from "path"; -import fs from "fs"; -import cookieParser from "@fastify/cookie"; -import { createServer } from "http"; - -import { createBareServer } from "@tomphttp/bare-server-node"; -import createRammerhead from "rammerhead/src/server/index.js"; -import wisp from "wisp-server-node"; -import { Socket } from "net"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -const bare = createBareServer("/bare/"); -const rh = createRammerhead(); - -const failureFile = fs.readFileSync("Checkfailed.html", "utf8"); - -const LICENSE_SERVER_URL = "https://license.mercurywork.shop/validate?license="; - -const rammerheadScopes = [ - "/rammerhead.js", - "/hammerhead.js", - "/transport-worker.js", - "/task.js", - "/iframe-task.js", - "/worker-hammerhead.js", - "/messaging", - "/sessionexists", - "/deletesession", - "/newsession", - "/editsession", - "/needpassword", - "/syncLocalStorage", - "/api/shuffleDict", - "/mainport" -]; - -const rammerheadSession = /^\/[a-z0-9]{32}/; - -function shouldRouteRh(req) { - const url = new URL(req.url, "http://0.0.0.0"); - return ( - rammerheadScopes.includes(url.pathname) || - rammerheadSession.test(url.pathname) - ); -} - -function routeRhRequest(req, res) { - rh.emit("request", req, res); -} - -function routeRhUpgrade(req, socket, head) { - rh.emit("upgrade", req, socket, head); -} - -const serverFactory = (handler, opts) => { - return createServer() - .on("request", (req, res) => { - if (bare.shouldRoute(req)) { - bare.routeRequest(req, res); - } else if (shouldRouteRh(req)) { - routeRhRequest(req, res); - } else { - handler(req, res); - } - }) - .on("upgrade", (req, socket, head) => { - if (bare.shouldRoute(req)) { - bare.routeUpgrade(req, socket, head); - } else if (shouldRouteRh(req)) { - routeRhUpgrade(req, socket, head); - } else { - wisp.routeRequest(req, socket as Socket, head); - } - }); -}; - -const app = fastify({ logger: false, serverFactory }); - -app.register(cookieParser); -await app.register(import("@fastify/compress")); - -// Uncomment if you wish to add masqr. -/* -app.addHook("preHandler", async (req, reply) => { - if (req.cookies["authcheck"]) { - return reply; - } - - const authheader = req.headers.authorization; - - if (req.cookies["refreshcheck"] != "true") { - reply - .setCookie("refreshcheck", "true", { maxAge: 10000 }) - .type("text/html") - .send(failureFile); - return reply; - } - - if (!authheader) { - reply - .code(401) - .header("WWW-Authenticate", "Basic") - .type("text/html") - .send(failureFile); - return reply; - } - - const auth = Buffer.from(authheader.split(" ")[1], "base64") - .toString() - .split(":"); - const user = auth[0]; - const pass = auth[1]; - - const licenseCheck = ( - await ( - await fetch(`${LICENSE_SERVER_URL}${pass}&host=${req.headers.host}`) - ).json() - )["status"]; - console.log( - `${LICENSE_SERVER_URL}${pass}&host=${req.headers.host} returned ${licenseCheck}` - ); - - if (licenseCheck === "License valid") { - reply.setCookie("authcheck", "true"); - return reply; - } - - reply.type("text/html").send(failureFile); - return reply; -}); */ - -app.register(fastifyStatic, { - root: path.join(__dirname, "dist"), - prefix: "/", - serve: true, - wildcard: false -}); - -app.get("/search=:query", async (req, res) => { - const { query } = req.params as { query: string }; // Define the type for req.params - - const response = await fetch( - `http://api.duckduckgo.com/ac?q=${query}&format=json` - ).then((apiRes) => apiRes.json()); - - res.send(response); -}); - -app.setNotFoundHandler((req, res) => { - res.sendFile("index.html"); // SPA catch-all -}); - -app.listen({ - port: 8080 -}); diff --git a/server.ts b/server.ts index 6eaee2e..6180e66 100644 --- a/server.ts +++ b/server.ts @@ -1,200 +1,160 @@ -import { createBareServer } from "@tomphttp/bare-server-node"; -import chalk from "chalk"; -import express from "express"; -import { createServer } from "node:http"; -import { fileURLToPath } from "url"; -import compression from "compression"; -import createRammerhead from "rammerhead/src/server/index.js"; -import path from "path"; -import fs from "fs"; -import cookieParser from "cookie-parser"; -import wisp from "wisp-server-node"; -import { Request, Response } from "express"; -//@ts-ignore -import { Socket, Head } from "ws"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -const LICENSE_SERVER_URL = "https://license.mercurywork.shop/validate?license="; -const whiteListedDomains = ["nebulaproxy.io"]; // Add any public domains you have here -const failureFile = fs.readFileSync("Checkfailed.html", "utf8"); -const rh = createRammerhead(); -const rammerheadScopes = [ - "/rammerhead.js", - "/hammerhead.js", - "/transport-worker.js", - "/task.js", - "/iframe-task.js", - "/worker-hammerhead.js", - "/messaging", - "/sessionexists", - "/deletesession", - "/newsession", - "/editsession", - "/needpassword", - "/syncLocalStorage", - "/api/shuffleDict" -]; -const rammerheadSession = /^\/[a-z0-9]{32}/; - -console.log(`${chalk.magentaBright("Starting Nebula...")}\n`); - -const app = express(); -app.use( - compression({ - threshold: 0, - filter: () => true - }) -); -app.use(cookieParser()); - -// Congratulations! Masqr failed to validate, this is either your first visit or you're a FRAUD -async function MasqFail(req: Request, res: Response) { - if (!req.headers.host) { - // no bitch still using HTTP/1.0 go away - return; - } - const unsafeSuffix = req.headers.host + ".html"; - let safeSuffix = path - .normalize(unsafeSuffix) - .replace(/^(\.\.(\/|\\|$))+/, ""); - let safeJoin = path.join(process.cwd() + "/Masqrd", safeSuffix); - try { - await fs.promises.access(safeJoin); // man do I wish this was an if-then instead of a "exception on fail" - const failureFileLocal = await fs.promises.readFile(safeJoin, "utf8"); - res.setHeader("Content-Type", "text/html"); - res.send(failureFileLocal); - return; - } catch (e) { - res.setHeader("Content-Type", "text/html"); - res.send(failureFile); - return; - } -} - -// Woooooo masqr yayyyy (said no one) -// uncomment for masqr -/* app.use(async (req, res, next) => { - if (req.headers.host && whiteListedDomains.includes(req.headers.host)) { - next(); - return; - } - if (req.url.includes("/bare/")) { // replace this with your bare endpoint - next(); - return; - // Bypass for UV and other bares - } - - const authheader = req.headers.authorization; - - if (req.cookies["authcheck"]) { - next(); - return; - } - - - if (req.cookies['refreshcheck'] != "true") { - res.cookie("refreshcheck", "true", {maxAge: 10000}) // 10s refresh check - MasqFail(req, res) - return; - } - - if (!authheader) { - - res.setHeader('WWW-Authenticate', 'Basic'); // Yeah so we need to do this to get the auth params, kinda annoying and just showing a login prompt gives it away so its behind a 10s refresh check - res.status(401); - MasqFail(req, res) - return; - } - - const auth = Buffer.from(authheader.split(' ')[1], - 'base64').toString().split(':'); - const user = auth[0]; - const pass = auth[1]; - - const licenseCheck = ((await (await fetch(LICENSE_SERVER_URL + pass + "&host=" + req.headers.host)).json()))["status"] - console.log(LICENSE_SERVER_URL + pass + "&host=" + req.headers.host +" returned " +licenseCheck) - if (licenseCheck == "License valid") { - res.cookie("authcheck", "true", {expires: new Date((Date.now()) + (365*24*60*60 * 1000))}) // authorize session, for like a year, by then the link will be expired lol - res.send(``) // fun hack to make the browser refresh and remove the auth params from the URL - return; - } - - MasqFail(req, res) - return; -}) */ - -app.use( - express.static("dist", { - //force .cjs files to be served as text/javascript (libcurl) - setHeaders: (res, path) => { - if (path.endsWith(".cjs")) { - res.setHeader("Content-Type", "text/javascript"); - } - } - }) -); - -app.get("/search=:query", async (req: Request, res: Response) => { - const { query } = req.params; - - const response = await fetch( - `http://api.duckduckgo.com/ac?q=${query}&format=json` - ).then((apiRes) => apiRes.json()); - - res.send(response); -}); - -app.get("*", (req, res) => { - res.sendFile(path.join(__dirname, "dist", "index.html")); -}); - -const server = createServer(); - -const bare = createBareServer("/bare/"); - -server.on("request", (req: Request, res: Response) => { - if (bare.shouldRoute(req)) { - bare.routeRequest(req, res); - } else if (shouldRouteRh(req)) { - routeRhRequest(req, res); - } else { - app(req, res); - } -}); - -server.on("upgrade", (req: Request, socket: Socket, head: Head) => { - if (bare.shouldRoute(req)) { - bare.routeUpgrade(req, socket, head); - } else if (shouldRouteRh(req)) { - routeRhUpgrade(req, socket, head); - } else if (req.url.endsWith("/wisp/")) { - wisp.routeRequest(req, socket, head); - } -}); - -function shouldRouteRh(req) { - const url = new URL(req.url, "http://0.0.0.0"); - return ( - rammerheadScopes.includes(url.pathname) || - rammerheadSession.test(url.pathname) - ); -} - -function routeRhRequest(req: Request, res: Response) { - rh.emit("request", req, res); -} - -function routeRhUpgrade(req: Request, socket: Socket, head: Head) { - rh.emit("upgrade", req, socket, head); -} - -const port = parseInt(process.env.PORT || "8080"); - -server.listen(port, () => { - console.log( - `${ - chalk.magentaBright("You can now use Nebula on port ") + chalk.bold(port) - }\n` - ); -}); +import fastify from "fastify"; +import fastifyStatic from "@fastify/static"; +import { fileURLToPath } from "url"; +import path from "path"; +import fs from "fs"; +import cookieParser from "@fastify/cookie"; +import { createServer } from "http"; + +import { createBareServer } from "@tomphttp/bare-server-node"; +import createRammerhead from "rammerhead/src/server/index.js"; +import wisp from "wisp-server-node"; +import { Socket } from "net"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const bare = createBareServer("/bare/"); +const rh = createRammerhead(); + +const failureFile = fs.readFileSync("Checkfailed.html", "utf8"); + +const LICENSE_SERVER_URL = "https://license.mercurywork.shop/validate?license="; + +const rammerheadScopes = [ + "/rammerhead.js", + "/hammerhead.js", + "/transport-worker.js", + "/task.js", + "/iframe-task.js", + "/worker-hammerhead.js", + "/messaging", + "/sessionexists", + "/deletesession", + "/newsession", + "/editsession", + "/needpassword", + "/syncLocalStorage", + "/api/shuffleDict", + "/mainport" +]; + +const rammerheadSession = /^\/[a-z0-9]{32}/; + +function shouldRouteRh(req) { + const url = new URL(req.url, "http://0.0.0.0"); + return ( + rammerheadScopes.includes(url.pathname) || + rammerheadSession.test(url.pathname) + ); +} + +function routeRhRequest(req, res) { + rh.emit("request", req, res); +} + +function routeRhUpgrade(req, socket, head) { + rh.emit("upgrade", req, socket, head); +} + +const serverFactory = (handler, opts) => { + return createServer() + .on("request", (req, res) => { + if (bare.shouldRoute(req)) { + bare.routeRequest(req, res); + } else if (shouldRouteRh(req)) { + routeRhRequest(req, res); + } else { + handler(req, res); + } + }) + .on("upgrade", (req, socket, head) => { + if (bare.shouldRoute(req)) { + bare.routeUpgrade(req, socket, head); + } else if (shouldRouteRh(req)) { + routeRhUpgrade(req, socket, head); + } else if (req.url.endsWith("/wisp/")) { + wisp.routeRequest(req, socket as Socket, head); + } + }); +}; + +const app = fastify({ logger: false, serverFactory }); + +app.register(cookieParser); +await app.register(import("@fastify/compress")); + +// Uncomment if you wish to add masqr. +/* +app.addHook("preHandler", async (req, reply) => { + if (req.cookies["authcheck"]) { + return reply; + } + + const authheader = req.headers.authorization; + + if (req.cookies["refreshcheck"] != "true") { + reply + .setCookie("refreshcheck", "true", { maxAge: 10000 }) + .type("text/html") + .send(failureFile); + return reply; + } + + if (!authheader) { + reply + .code(401) + .header("WWW-Authenticate", "Basic") + .type("text/html") + .send(failureFile); + return reply; + } + + const auth = Buffer.from(authheader.split(" ")[1], "base64") + .toString() + .split(":"); + const user = auth[0]; + const pass = auth[1]; + + const licenseCheck = ( + await ( + await fetch(`${LICENSE_SERVER_URL}${pass}&host=${req.headers.host}`) + ).json() + )["status"]; + console.log( + `${LICENSE_SERVER_URL}${pass}&host=${req.headers.host} returned ${licenseCheck}` + ); + + if (licenseCheck === "License valid") { + reply.setCookie("authcheck", "true"); + return reply; + } + + reply.type("text/html").send(failureFile); + return reply; +}); */ + +app.register(fastifyStatic, { + root: path.join(__dirname, "dist"), + prefix: "/", + serve: true, + wildcard: false +}); + +app.get("/search=:query", async (req, res) => { + const { query } = req.params as { query: string }; // Define the type for req.params + + const response = await fetch( + `http://api.duckduckgo.com/ac?q=${query}&format=json` + ).then((apiRes) => apiRes.json()); + + res.send(response); +}); + +app.setNotFoundHandler((req, res) => { + res.sendFile("index.html"); // SPA catch-all +}); + +app.listen({ + port: 8080 +});