diff --git a/app.js b/app.js index 2848481..d65d184 100644 --- a/app.js +++ b/app.js @@ -1,3 +1,4 @@ (async() => { - await import('./app.mjs'); + await + import ('./app.mjs'); })(); \ No newline at end of file diff --git a/app.mjs b/app.mjs index 8272279..ac77459 100644 --- a/app.mjs +++ b/app.mjs @@ -5,13 +5,20 @@ import nodeStatic from 'node-static'; import fs from 'fs'; import * as custombare from './static/customBare.mjs'; + +const httpPort = 80; +const httpsPort = 443; +const debug = true; + + + const bareServer = createBareServer('/bare/', { - logErrors: false, - localAddress: undefined, - maintainer: { - email: 'tomphttp@sys32.dev', - website: 'https://github.com/tomphttp/', - }, + logErrors: false, + localAddress: undefined, + maintainer: { + email: 'tomphttp@sys32.dev', + website: 'https://github.com/tomphttp/', + }, }); const serve = new nodeStatic.Server('static/'); @@ -39,25 +46,28 @@ httpsServer.on('request', request); httpServer.on('upgrade', upgrade); httpsServer.on('upgrade', upgrade); -function request (request, response) { +function request(request, response) { if (custombare.route(request, response)) return true; - + if (debug === true) { + console.log(`[${request.method}] - ${request.url} - LINK: ${request.headers['host']} - AGENT: ${request.headers['user-agent']}`); + } + if (bareServer.shouldRoute(request)) { - bareServer.routeRequest(request, response); - } else { - serve.serve(request, response); - } + bareServer.routeRequest(request, response); + } else { + serve.serve(request, response); + } } -function upgrade (req, socket, head) { +function upgrade(req, socket, head) { if (bareServer.shouldRoute(req)) { - bareServer.routeUpgrade(req, socket, head); - } else { - socket.end(); - } + bareServer.routeUpgrade(req, socket, head); + } else { + socket.end(); + } } -httpServer.listen(80); -httpsServer.listen(443); +httpServer.listen(httpPort); +httpsServer.listen(httpsPort); -console.log("Server running on port 80 and 443."); +console.log("Server running on http://localhost:" + httpPort + " and https://localhost:" + httpsPort); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 4533b3c..628919b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,22 +10,47 @@ "license": "Copyright Nebula Services. All Rights Reserved.", "dependencies": { "@tomphttp/bare-server-node": "^1.0.2-beta-readme5", + "bare-server-node": "github:tomphttp/bare-server-node", + "crypto-js": "4.1.1", + "css-tree": "^2.1.0", "node-fetch": "^3.2.6", - "node-static": "^0.7.11" + "node-static": "^0.7.11", + "ws": "^8.8.1" } }, "node_modules/@tomphttp/bare-server-node": { - "version": "1.0.2-beta-readme5", - "resolved": "https://registry.npmjs.org/@tomphttp/bare-server-node/-/bare-server-node-1.0.2-beta-readme5.tgz", - "integrity": "sha512-WOYNae3faSj9Yt4dKVqzjbh1ovpKRhsevnJaM2BgC6LkRULFN/GhtslXDXG6KLbqeokFFj0XqpZ8TTzdxKyhkw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tomphttp/bare-server-node/-/bare-server-node-1.0.3.tgz", + "integrity": "sha512-mKMipi9qntDy3wcalWGuK3iKzM0XQT4sW3E6yRXeIU4BxFZVSLzSDejPxL6wWwniKGm0faSwZ4Pk0dQ04JEFNA==", "dependencies": { "commander": "^9.0.0", "dotenv": "^16.0.1", - "fetch-headers": "^3.0.1", + "headers-polyfill": "^3.0.10", "http-errors": "^2.0.0" }, "bin": { - "bare-server-node": "scripts/start.js" + "bare-server-node": "scripts/cli.js" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/bare-server-node": { + "name": "@tomphttp/bare-server-node", + "version": "1.0.3-deps2", + "resolved": "git+ssh://git@github.com/tomphttp/bare-server-node.git#c5a87ef6c063c4728bb88a362db9581f26be2225", + "license": "GPL-3.0", + "dependencies": { + "commander": "^9.0.0", + "dotenv": "^16.0.1", + "headers-polyfill": "^3.0.10", + "http-errors": "^2.0.0" + }, + "bin": { + "bare-server-node": "scripts/cli.js" + }, + "engines": { + "node": ">=16.0.0" } }, "node_modules/colors": { @@ -44,6 +69,24 @@ "node": "^12.20.0 || >=14" } }, + "node_modules/crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" + }, + "node_modules/css-tree": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.1.0.tgz", + "integrity": "sha512-PcysZRzToBbrpoUrZ9qfblRIRf8zbEAkU0AIpQFtgkFK0vSbzOmBCvdSAx2Zg7Xx5wiYJKUKk0NMP7kxevie/A==", + "dependencies": { + "mdn-data": "2.0.27", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/data-uri-to-buffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", @@ -90,24 +133,6 @@ "node": "^12.20 || >= 14.13" } }, - "node_modules/fetch-headers": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fetch-headers/-/fetch-headers-3.0.1.tgz", - "integrity": "sha512-Kq+NyED/wLgT29St7aW47gAWg8EmmE5QmhwQ5RmPRULYLqpglA7Kc/ZnbqXu2vhH6mw1koikew2g94WiHLPmpA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "engines": { - "node": ">=12.20" - } - }, "node_modules/formdata-polyfill": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", @@ -119,6 +144,11 @@ "node": ">=12.20.0" } }, + "node_modules/headers-polyfill": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-3.0.10.tgz", + "integrity": "sha512-lOhQU7iG3AMcjmb8NIWCa+KwfJw5bY44BoWPtrj5A4iDbSD3ylGf5QcYr0ZyQnhkKQ2GgWNLdF2rfrXtXlF3nQ==" + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -139,6 +169,11 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/mdn-data": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.27.tgz", + "integrity": "sha512-kwqO0I0jtWr25KcfLm9pia8vLZ8qoAKhWZuZMbneJq3jjBD3gl5nZs8l8Tu3ZBlBAHVQtDur9rdDGyvtfVraHQ==" + }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -220,6 +255,14 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -251,17 +294,47 @@ "engines": { "node": ">=0.4.0" } + }, + "node_modules/ws": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", + "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } } }, "dependencies": { "@tomphttp/bare-server-node": { - "version": "1.0.2-beta-readme5", - "resolved": "https://registry.npmjs.org/@tomphttp/bare-server-node/-/bare-server-node-1.0.2-beta-readme5.tgz", - "integrity": "sha512-WOYNae3faSj9Yt4dKVqzjbh1ovpKRhsevnJaM2BgC6LkRULFN/GhtslXDXG6KLbqeokFFj0XqpZ8TTzdxKyhkw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tomphttp/bare-server-node/-/bare-server-node-1.0.3.tgz", + "integrity": "sha512-mKMipi9qntDy3wcalWGuK3iKzM0XQT4sW3E6yRXeIU4BxFZVSLzSDejPxL6wWwniKGm0faSwZ4Pk0dQ04JEFNA==", "requires": { "commander": "^9.0.0", "dotenv": "^16.0.1", - "fetch-headers": "^3.0.1", + "headers-polyfill": "^3.0.10", + "http-errors": "^2.0.0" + } + }, + "bare-server-node": { + "version": "git+ssh://git@github.com/tomphttp/bare-server-node.git#c5a87ef6c063c4728bb88a362db9581f26be2225", + "from": "bare-server-node@github:tomphttp/bare-server-node", + "requires": { + "commander": "^9.0.0", + "dotenv": "^16.0.1", + "headers-polyfill": "^3.0.10", "http-errors": "^2.0.0" } }, @@ -275,6 +348,20 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.0.tgz", "integrity": "sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==" }, + "crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" + }, + "css-tree": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.1.0.tgz", + "integrity": "sha512-PcysZRzToBbrpoUrZ9qfblRIRf8zbEAkU0AIpQFtgkFK0vSbzOmBCvdSAx2Zg7Xx5wiYJKUKk0NMP7kxevie/A==", + "requires": { + "mdn-data": "2.0.27", + "source-map-js": "^1.0.1" + } + }, "data-uri-to-buffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", @@ -299,11 +386,6 @@ "web-streams-polyfill": "^3.0.3" } }, - "fetch-headers": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fetch-headers/-/fetch-headers-3.0.1.tgz", - "integrity": "sha512-Kq+NyED/wLgT29St7aW47gAWg8EmmE5QmhwQ5RmPRULYLqpglA7Kc/ZnbqXu2vhH6mw1koikew2g94WiHLPmpA==" - }, "formdata-polyfill": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", @@ -312,6 +394,11 @@ "fetch-blob": "^3.1.2" } }, + "headers-polyfill": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-3.0.10.tgz", + "integrity": "sha512-lOhQU7iG3AMcjmb8NIWCa+KwfJw5bY44BoWPtrj5A4iDbSD3ylGf5QcYr0ZyQnhkKQ2GgWNLdF2rfrXtXlF3nQ==" + }, "http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -329,6 +416,11 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "mdn-data": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.27.tgz", + "integrity": "sha512-kwqO0I0jtWr25KcfLm9pia8vLZ8qoAKhWZuZMbneJq3jjBD3gl5nZs8l8Tu3ZBlBAHVQtDur9rdDGyvtfVraHQ==" + }, "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -378,6 +470,11 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" + }, "statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -397,6 +494,12 @@ "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==" + }, + "ws": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", + "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==", + "requires": {} } } } diff --git a/package.json b/package.json index fdebe08..7e96603 100644 --- a/package.json +++ b/package.json @@ -15,10 +15,12 @@ "author": "Nebula Services", "license": "Copyright Nebula Services. All Rights Reserved.", "dependencies": { + "@tomphttp/bare-server-node": "^1.0.2-beta-readme5", "bare-server-node": "github:tomphttp/bare-server-node", "css-tree": "^2.1.0", "node-fetch": "^3.2.6", "node-static": "^0.7.11", - "ws": "^8.8.1" + "ws": "^8.8.1", + "crypto-js": "4.1.1" } -} +} \ No newline at end of file diff --git a/static/customBare.mjs b/static/customBare.mjs index 2433aef..8694c45 100644 --- a/static/customBare.mjs +++ b/static/customBare.mjs @@ -3,17 +3,15 @@ import { URL } from 'url'; import fs from 'fs'; import * as csstree from 'css-tree'; import * as ws from 'ws'; +import filter from './cyclone/filter.cyclone.mjs'; +import * as security from './cyclone/security.cyclone.mjs'; const config = { - prefix: "/service", - requireSSL: true, // Requires SSL? - defaultHeaders: { - 'X-Content-Type-Options': 'no-sniff', - }, - //proxy: { - // host: "3.211.17.212", - // port: "80" - //} // HTTP Proxy + prefix: "/service", + requireSSL: true, // Requires SSL? + defaultHeaders: { + 'X-Content-Type-Options': 'no-sniff', + }, } if (config.requireSSL) { @@ -23,125 +21,126 @@ if (config.requireSSL) { } function rewriteJavascript(js) { - var javascript = js.replace('window.location', 'document._dlocation') - javascript = javascript.replace('document.location', 'document._dlocation') - javascript = javascript.replace('location.', 'document._location.') - return javascript + var javascript = js.replace(/window\.location/g, 'window._dlocation') + javascript = javascript.replace(/document\.location/g, 'document._dlocation') + javascript = javascript.replace(/location\./g, '_location.') + return javascript } function insertScript(html) { - var res = ` - - - - - -${html} - -` - return res -} // - -async function fetchBare(url, res, req) { - try { - var options = { - method: req.method, - headers: { - "Refer": url.href, - "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36", - "cookies": req.cookies, - }, - } - - try { - var request = await fetch(url.href, options); - } catch (e) { - var request = { - text() { - return 'Error: '+e; - }, - - } - } - - try { - var contentType = request.headers.get('content-type') || 'application/javascript' - } catch { - var contentType = 'application/javascript'; - } - - if (url.href.endsWith('.js')||url.href.endsWith(".js")) contentType = "application/javascript"; - if (url.href.endsWith('.css')||url.href.endsWith(".css")) contentType = "text/css"; - - var output = null; - - if (contentType.includes('html') || contentType.includes('javascript')) { - var doc = await request.text(); - } - - res.setHeader('content-type', contentType); - - if (contentType.includes('html')) { - output = insertScript(doc); - res.write(output); - res.end(); - } else if (contentType.includes('javascript')) { - output = rewriteJavascript(doc) - res.write(output); - res.end() - } else { - request.body.pipe(res) - } - - - } catch (e) { - console.log(e); - res.writeHead(500, 'Error', { - 'content-type': 'application/javascript' - }) - res.end(e) - } + var res = ` + + + + + + ${html} + + ` + return res } -function websocketIntercept(req,res) { - console.log(req); +async function fetchBare(url, res, req) { + try { + var options = { + method: req.method, + headers: { + "Refer": url.href, + "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36", + "cookies": req.cookies, + }, + } + + try { + var request = await fetch(url.href, options); + } catch (e) { + var request = { + text() { + return 'Error: ' + e; + }, + } + } + + try { + var contentType = request.headers.get('content-type') || 'application/javascript' + } catch { + var contentType = 'application/javascript'; + } + + if (url.href.endsWith('.js') || url.href.endsWith(".js")) contentType = "application/javascript"; + if (url.href.endsWith('.css') || url.href.endsWith(".css")) contentType = "text/css"; + + var output = null; + + if (contentType.includes('html') || contentType.includes('javascript')) { + var doc = await request.text(); + } + + res.setHeader('content-type', contentType); + + if (contentType.includes('html')) { + output = insertScript(doc); + res.write(output); + res.end(); + } else if (contentType.includes('javascript')) { + output = rewriteJavascript(doc) + res.write(output); + res.end() + } else { + request.body.pipe(res) + } + } catch (e) { + console.log(e); + res.writeHead(500, 'Error', { + 'content-type': 'application/javascript' + }) + res.end(e); + } +} + +function websocketIntercept(req, res) { + console.log(req); } function route(req, res) { - var path = req.url; + var path = req.url; - if (path.startsWith(config.prefix + "/")) { - try { - var url = new URL(path.split(config.prefix + "/")[1]) - } catch { - var url = new URL("https://" + path.split(config.prefix + "/")[1]) + if (path.startsWith(config.prefix + "/")) { + var decoded = path.split(config.prefix + "/")[1]; + + try { + var url = new URL(decoded); + } catch { + var url = new URL("https://" + decoded); + } + + if (filter(req, res)) return; + + return fetchBare(url, res, req); + + } else { + return false; } - - fetchBare(url, res,req); - - } else { - return false; - } } function isBare(req, res) { - return (req.url.startsWith(config.prefix)); + return (req.url.startsWith(config.prefix)); } function routeSocket(req, socket) { - var path = req.url; + var path = req.url; - try { - var url = new URL(path.split(config.prefix + "/")[1]) - } catch { - var url = new URL("wss://" + path.split(config.prefix + "/")[1]) - } + try { + var url = new URL(path(config.prefix + "/")[1]) + } catch { + var url = new URL("wss://" + path(config.prefix + "/")[1]) + } - console.log(url); + console.log(url); } export { - route, - routeSocket, - isBare, -} + route, + routeSocket, + isBare, +} \ No newline at end of file diff --git a/static/cySw.js b/static/cySw.js index 1f870b5..08ca925 100644 --- a/static/cySw.js +++ b/static/cySw.js @@ -1,109 +1,109 @@ class Cyclone { - constructor() { - tmp = location.pathname.split('/service')[1] + constructor() { + tmp = location.pathname.split('/service')[1] - tmp = tmp.substring(1, tmp.length); - let re = /(http(s|):)/g + tmp = tmp.substring(1, tmp.length); + let re = /(http(s|):)/g - //if (tmp.match(re)) { - tmp = tmp.replace("http://", '') - tmp = tmp.replace("https://", '') - tmp = tmp.replace("http:/", '') - tmp = tmp.replace("https:/", '') - tmp = location.protocol + "//" + tmp + //if (tmp.match(re)) { + tmp = tmp.replace("http://", '') + tmp = tmp.replace("https://", '') + tmp = tmp.replace("http:/", '') + tmp = tmp.replace("https:/", '') + tmp = location.protocol + "//" + tmp - document._location = new URL(tmp); + document._location = new URL(tmp); - this.url = new URL(document._location.href); + this.url = new URL(document._location.href); - this.bareEndpoint = location.host + "/service"; + this.bareEndpoint = location.host + "/service"; - if (this.url.pathname == "/") { - this.paths = ['/'] - } else { - this.paths = this.url.pathname.split('/') - } - this.host = 'https://' + this.url.host - - this.targetAttrs = ['href', 'src', 'action', 'srcdoc', 'srcset']; - - console.log("Cyclone Injected with paths of:", this.paths, this.url.pathname) - - /*const LocationHandler = { - get(target, prop, reciver) { - return loc[prop] - }, - set(target, prop, val) { - return 'hi' - } - } - - document._location = new Proxy(LocationHandler, loc)*/ - } - - rewriteUrl(link) { - var rewritten; - - if (link.startsWith('https://') || link.startsWith('http://') || link.startsWith('//')) { - if (link.startsWith('//')) { - rewritten = 'https:' + link; - } else { - rewritten = link; - }; - } else { - if (link.startsWith('.')) { - let offset = 1; - if (link.startsWith('..')) { - offset = 2; - } - let file = link.substr(link.indexOf('.') + 1 + offset, link.length) - - rewritten = this.url.hostname + file - } else { - if (link.startsWith('/')) { - rewritten = this.host + link + if (this.url.pathname == "/") { + this.paths = ['/'] } else { - rewritten = this.host + '/' + link; + this.paths = this.url.pathname.split('/') + } + this.host = 'https://' + this.url.host + + this.targetAttrs = ['href', 'src', 'action', 'srcdoc', 'srcset']; + + console.log("Cyclone Injected with paths of:", this.paths, this.url.pathname) + + /*const LocationHandler = { + get(target, prop, reciver) { + return loc[prop] + }, + set(target, prop, val) { + return 'hi' } } + + document._location = new Proxy(LocationHandler, loc)*/ } - var exceptions = ['about:', 'mailto:', 'javascript:', 'data:'] - let needstowrite = true; - for (let i = 0; i < exceptions.length; i++) { - if (link.startsWith(exceptions[i])) { - needstowrite = false - } - } + rewriteUrl(link) { + var rewritten; - if (needstowrite) { - rewritten = location.protocol + '//' + this.bareEndpoint + '/' + rewritten - return rewritten; - } else { - return link; - } - } + if (link.startsWith('https://') || link.startsWith('http://') || link.startsWith('//')) { + if (link.startsWith('//')) { + rewritten = 'https:' + link; + } else { + rewritten = link; + }; + } else { + if (link.startsWith('.')) { + let offset = 1; + if (link.startsWith('..')) { + offset = 2; + } + let file = link.substr(link.indexOf('.') + 1 + offset, link.length) - rewriteSrcset(sample) { - return sample.split(',').map(e => { - return (e.split(' ').map(a => { - if (a.startsWith('http') || (a.startsWith('/') && !a.startsWith(this.prefix))) { - var url = this.rewriteUrl(a) + rewritten = this.url.hostname + file + } else { + if (link.startsWith('/')) { + rewritten = this.host + link + } else { + rewritten = this.host + '/' + link; + } + } } - return a.replace(a, (url || a)) - }).join(' ')) - }).join(',') - } + + var exceptions = ['about:', 'mailto:', 'javascript:', 'data:'] + let needstowrite = true; + for (let i = 0; i < exceptions.length; i++) { + if (link.startsWith(exceptions[i])) { + needstowrite = false + } + } + + if (needstowrite) { + rewritten = location.protocol + '//' + this.bareEndpoint + '/' + rewritten + return rewritten; + } else { + return link; + } + } + + rewriteSrcset(sample) { + return sample.split(',').map(e => { + return (e.split(' ').map(a => { + if (a.startsWith('http') || (a.startsWith('/') && !a.startsWith(this.prefix))) { + var url = this.rewriteUrl(a) + } + return a.replace(a, (url || a)) + }).join(' ')) + }).join(',') + } } self.addEventListener('fetch', function(event) { - var uri = new URL(event.request.url); + var uri = new URL(event.request.url); - if (!uri.pathname.startsWith('/service') && uri.pathname == "/facicon.ico") { - var tmp = uri.href; - - event.respondWith( - fetch("https://Cyclone2.jimmynuetron.repl.co/service/"+tmp) - ) - } -}); + if (!uri.pathname.startsWith('/service') && uri.pathname == "/facicon.ico") { + var tmp = uri.href; + + event.respondWith( + fetch("https://Cyclone2.jimmynuetron.repl.co/service/" + tmp) + ) + } +}); \ No newline at end of file diff --git a/static/cyclone.js b/static/cyclone.js deleted file mode 100644 index 7c8a57f..0000000 --- a/static/cyclone.js +++ /dev/null @@ -1,442 +0,0 @@ -const config = { - -} - -class Cyclone { - constructor() { - this.tmp = location.pathname.split('/service')[1] - - this.tmp = this.tmp.substring(1, this.tmp.length); - this.tmp = this.tmp.replace("http://", '') - this.tmp = this.tmp.replace("https://", '') - this.tmp = this.tmp.replace("http:/", '') - this.tmp = this.tmp.replace("https:/", '') - this.tmp = location.protocol + "//" + this.tmp - - document._location = new URL(this.tmp); - var l = new URL(this.tmp); - - this.url = new URL(document._location.href); - - this.prefix = location.pathname.split('/')[1] - this.bareEndpoint = location.host + "/" + this.prefix - - if (this.url.pathname == "/") { - this.paths = ['/'] - } else { - this.paths = this.url.pathname.split('/') - } - this.host = 'https://' + this.url.host - - this.targetAttrs = ['href', 'src', 'action', 'srcdoc', 'srcset']; - - if (!document.cycloneInjected) { - console.log("Cyclone Injected with paths of:", this.paths, this.url.pathname) - document.cycloneInjected = true - } - - const LocationHandler = { - get(target, prop, reciver) { - return document._location[prop] - }, - set(target, prop, val) { - return false - } - } - - //const locProxy = new Proxy(document.location, LocationHandler) - Object.defineProperty(document, '_location', { - writable: true, - configurable: true, - enumerable: true, - value: l - }); - Object.defineProperty(window.document, '_location', { - writable: true, - configurable: true, - enumerable: true, - value: l - }); - Object.defineProperty(window, '_location', { - writable: true, - configurable: true, - enumerable: true, - value: l - }); - } - - rewriteUrl(link) { - if (!link) { - link = ""; - } - - var rewritten; - - if (link.startsWith('https://') || link.startsWith('http://') || link.startsWith('//')) { - if (link.startsWith('//')) { - rewritten = 'https:' + link; - } else { - rewritten = link; - }; - } else { - if (link.startsWith('.')) { - let offset = 1; - if (link.startsWith('..')) { - offset = 2; - } - let file = link.substr(link.indexOf('.') + 1 + offset, link.length) - - rewritten = this.url.hostname + file - } else { - if (link.startsWith('/')) { - rewritten = this.host + link - } else { - rewritten = this.host + '/' + link; - } - } - } - - var exceptions = ['about:', 'mailto:', 'javascript:', 'data:'] - let needstowrite = true; - for (let i = 0; i < exceptions.length; i++) { - if (link.startsWith(exceptions[i])) { - needstowrite = false - } - } - - - if (needstowrite) { - rewritten = location.protocol + '//' + this.bareEndpoint + '/' + rewritten - return rewritten; - } else { - return link; - } - } - - rewriteSrcset(sample) { - return sample.split(',').map(e => { - return (e.split(' ').map(a => { - if (a.startsWith('http') || (a.startsWith('/') && !a.startsWith(this.prefix))) { - var url = this.rewriteUrl(url); - } - return a.replace(a, (url || a)) - }).join(' ')) - }).join(',') - } -} - -// Rewriting of data types - -// CSS -class CSSRewriter extends Cyclone { - rewriteCSS(tag) { - var styles = window.getComputedStyle(tag) - var _values = styles['_values'] - - var prop = styles.getPropertyValue('background-image') - var name = "background-image" - - if (prop == "") { - if (!styles.getPropertyValue('background') == "") { - prop = styles.getPropertyValue('background') - name = "background" - } else { - name = ""; - prop = ""; - } - } - - if (prop.includes("url(")) { - var start = prop.indexOf('url(') + 4 - var end = prop.indexOf(')') - 4 - - var url = prop.substring(start, end).toString('ascii'); - - if (url.startsWith(location.origin)) { - url = url.split(location.origin) - } else { - url = url.slice(url.indexOf(location.origin)); - } - - url = this.rewriteUrl(url) - tag.style[name] = url - } - } -} - -// JS - -class JavaScriptRewriter extends Cyclone { - constructor(proxy) { - super(); - //Proxied methods - this.setAttrCy = HTMLElement.prototype.setAttribute; - this.getAttrCy = HTMLElement.prototype.getAttribute; - this.proxy = proxy - } - - rewriteJavascript(js) { - var javascript = js.replace(/window\.location/g, 'window._dlocation') - javascript = javascript.replace(/document\.location/g, 'document._dlocation') - javascript = javascript.replace(/location\./g, '_location.') - return javascript - } - - setAttribute(attr, value, mode) { - const setAttrCy = HTMLElement.prototype.setAttribute; - - if (mode) { - this.setAttrCy.call(this, attr, value); - } else { - var url = attr - if (cyclone.targetAttrs.includes(attr)) { - url = cyclone.rewriteUrl(url); - } - - setAttrCy.call(this, attr, value); - } - } - - getAttribute(attrN, mode) { - const getAttrCy = HTMLElement.prototype.getAttribute; - - if (mode) { - return getAttrCy.call(this, attrN); - } else { - var val = getAttrCy.call(this, attrN); - if (cyclone.targetAttrs.includes(attrN)) { - val = getAttrCy.call(this, 'data-origin-' + attrN); - } - - return val; - } - } -} - -// HTML -class HTMLRewriter extends Cyclone { - rewriteElement(element) { - var targetAttrs = this.targetAttrs; - var attrs; - try { - attrs = [...element.attributes || {}].reduce((attrs, attribute) => { - attrs[attribute.name] = attribute.value; - return attrs; - }, {}); - } catch { - attrs = {}; - } - - if (element.__proto__.getAttribute) { - var jsWrite = new JavaScriptRewriter(); - var elementAttributes = []; - - for (var i = 0; i < targetAttrs.length; i++) { - var attr = targetAttrs[i] - var attrName = Object.keys(attrs)[i]; - var data = { - name: attr, - value: element.getAttribute('data-origin-' + attr, 'cyclone') || element.getAttribute(attr, 'cyclone') - } - - if (data.value) { - elementAttributes.push(data); - } - - if (element.nonce) { - element.setAttribute('nononce', element.nonce, '') - element.removeAttribute('nonce') - } - if (element.integrity) { - element.setAttribute('nointegrity', element.integrity, '') - element.removeAttribute('integrity') - } - - if (element.tagName == "script") { - if (!element.getAttribute('src')) { - var jsRewrite = new JavaScriptRewriter(); - element.innerHTML = jsRewrite.rewriteJavascript(element.innerHTML) - } - } - - // Css - var cssRewrite = new CSSRewriter(); - cssRewrite.rewriteCSS(element) - } - - for (var i = 0; i < elementAttributes.length; i++) { - var attr = elementAttributes[i]; - var attrName = attr.name; - var value = attr.value; - - var bareValue = this.rewriteUrl(value); - if (attrName == "srcset" || attrName == 'srcset') { - bareValue = this.rewriteSrcset(value); - } - - element.setAttribute(attrName, bareValue); - element.setAttribute("data-origin-" + attrName, value); - } - } - } - - rewriteDocument() { - var docElements = document.querySelectorAll('*'); - for (var i = 0; i < docElements.length; i++) { - var element = docElements[i]; - - this.rewriteElement(element) - } - } - - rewriteiFrame(iframe) { - var frameDoc = (iframe.contentWindow || iframe.contentDocument || iframe.document); - - let tags = frameDoc.querySelectorAll('*') - - for (var i = 0; i < tags.length; i++) { - var tag = tags[i] - this.rewriteElement(tag) - } - } -} - -const cyclone = new Cyclone(); - -const htmlRewriter = new HTMLRewriter(); - -const FetchIntercept = window.fetch; -window.fetch = async (...args) => { - let [resource, config] = args; - resource = cyclone.rewriteUrl(resource); - - const response = await FetchIntercept(resource, config); - return response; -} - -const MessageIntercept = window.postMessage; -const messageInterceptionFunc = (...args) => { - let [message, target, config] = args; - target = cyclone.rewriteUrl(target); - - const response = MessageIntercept(message, target, config); - console.log(response); - return response; -} - -Object.defineProperty(window, 'postMessage', { - writable: false, - value: messageInterceptionFunc -} -) - -var CWOriginal = Object.getOwnPropertyDescriptor(window.HTMLIFrameElement.prototype, 'contentWindow') - -Object.defineProperty(window.HTMLIFrameElement.prototype, 'contentWindow', { - get() { - var iWindow = CWOriginal.get.call(this); - htmlRewriter.rewriteiFrame(iWindow); - - return iWindow - }, - set() { - return false; - } -}) - - -const open = XMLHttpRequest.prototype.open; -XMLHttpRequest.prototype.open = function(method, url, ...rest) { - url = cyclone.rewriteUrl(url) - - return open.call(this, method, url, ...rest); -}; - -var oPush = window.history.pushState; -var oPlace = window.history.replaceState; - -function CycloneStates(dat, unused, url) { - var cyUrl = cyclone.rewriteUrl(url); - - oPush.call(this, dat, unused, cyUrl); -} - -window.history.pushState = CycloneStates -window.history.replaceState = CycloneStates -history.pushState = CycloneStates -history.replaceState = CycloneStates - -const OriginalWebsocket = window.WebSocket -const ProxiedWebSocket = function() { - const ws = new OriginalWebsocket(...arguments) - - const originalAddEventListener = ws.addEventListener - const proxiedAddEventListener = function() { - if (arguments[0] === "message") { - const cb = arguments[1] - arguments[1] = function() { - var origin = arguments[0].origin - arguments[0].origin = cyclone.rewriteUrl(origin); - - return cb.apply(this, arguments) - } - } - return originalAddEventListener.apply(this, arguments) - } - ws.addEventListener = proxiedAddEventListener - - Object.defineProperty(ws, "onmessage", { - set(func) { - return proxiedAddEventListener.apply(this, [ - "message", - func, - false - ]); - } - }); - return ws; -}; - -window.WebSocket = ProxiedWebSocket; - -const nwtb = window.open - -function openNewTab(url, target, features) { - url = cyclone.rewriteUrl(url) - nwtb(url, target, features) -} - -window.open = openNewTab; - -window.onload = function() { - for (var i = 0; i < 50; i++) { - setTimeout(() => { - htmlRewriter.rewriteDocument(); - }, 500) - } -} - -let mutationE = new MutationObserver((mutationList, observer) => { - for (const mutation of mutationList) { - mutation.addedNodes.forEach(node => { - htmlRewriter.rewriteElement(node); - }); - } -}).observe(document, { - childList: true, - subtree: true -}) - -//For intercepting all requests -if (!document.serviceWorkerRegistered) { - if ('serviceWorker' in navigator) { - window.addEventListener('load', function() { - navigator.serviceWorker.register(location.origin + '/cySw.js').then(function(registration) { - console.log('Service worker registered with scope: ', registration.scope); - }, function(err) { - console.log('ServiceWorker registration failed: ', err); - }); - }); - } - document.serviceWorkerRegistered = true -} diff --git a/static/cyclone/cyclone.js b/static/cyclone/cyclone.js new file mode 100644 index 0000000..fd7e4be --- /dev/null +++ b/static/cyclone/cyclone.js @@ -0,0 +1,476 @@ +const config = { + +} + +const encryptWithAES = (text) => { + const passphrase = '123'; + return CryptoJS.AES.encrypt(text, passphrase).toString(); +}; + +const decryptWithAES = (ciphertext) => { + const passphrase = '123'; + const bytes = CryptoJS.AES.decrypt(ciphertext, passphrase); + const originalText = bytes.toString(CryptoJS.enc.Utf8); + return originalText; +}; + +class Cyclone { + constructor() { + this.tmp = (location.pathname.split('/service/')[1]); + + this.tmp = this.tmp.substring(0, this.tmp.length); + this.tmp = this.tmp.replace("http://", '') + this.tmp = this.tmp.replace("https://", '') + this.tmp = this.tmp.replace("http:/", '') + this.tmp = this.tmp.replace("https:/", '') + this.tmp = location.protocol + "//" + this.tmp + + document._location = new URL(this.tmp); + var l = new URL(this.tmp); + + this.url = new URL(document._location.href); + + this.prefix = (location.pathname).split('/')[1]; + this.bareEndpoint = location.host + "/" + this.prefix; + + if (this.url.pathname == "/") { + this.paths = ['/'] + } else { + this.paths = this.url.pathname.split('/') + } + this.host = 'https://' + this.url.host + + this.targetAttrs = ['href', 'src', 'action', 'srcdoc', 'srcset']; + + if (!document.cycloneInjected) { + console.log("Cyclone Injected with paths of:", this.paths, this.url.pathname) + document.cycloneInjected = true + } + + const LocationHandler = { + get(target, prop, reciver) { + return document._location[prop] + }, + set(target, prop, val) { + return false + } + } + + //const locProxy = new Proxy(document.location, LocationHandler) + Object.defineProperty(document, '_location', { + writable: true, + configurable: true, + enumerable: true, + value: l + }); + Object.defineProperty(window.document, '_location', { + writable: true, + configurable: true, + enumerable: true, + value: l + }); + Object.defineProperty(window, '_location', { + writable: true, + configurable: true, + enumerable: true, + value: l + }); + } + + rewriteUrl(link) { + if (!link) { + link = ""; + } + + var rewritten; + + if (link.startsWith('https://') || link.startsWith('http://') || link.startsWith('//')) { + if (link.startsWith('//')) { + rewritten = 'https:' + link; + } else { + rewritten = link; + }; + } else { + if (link.startsWith('.')) { + let offset = 1; + if (link.startsWith('..')) { + offset = 2; + } + let file = link.substr(link.indexOf('.') + 1 + offset, link.length) + + rewritten = this.url.hostname + file + } else { + if (link.startsWith('/')) { + rewritten = this.host + link + } else { + rewritten = this.host + '/' + link; + } + } + } + + var exceptions = ['about:', 'mailto:', 'javascript:', 'data:'] + let needstowrite = true; + for (let i = 0; i < exceptions.length; i++) { + if (link.startsWith(exceptions[i])) { + needstowrite = false + } + } + + + if (needstowrite) { + rewritten = location.protocol + '//' + this.bareEndpoint + '/' + rewritten + return (rewritten); + } else { + return link; + } + } + + rewriteSrcset(sample) { + return sample.split(',').map(e => { + return (e.split(' ').map(a => { + if (a.startsWith('http') || (a.startsWith('/') && !a.startsWith(this.prefix))) { + var url = this.rewriteUrl(url); + } + return a.replace(a, (url || a)) + }).join(' ')) + }).join(',') + } +} + +// Rewriting of data types + +// CSS +class CSSRewriter extends Cyclone { + rewriteCSS(tag) { + var styles = window.getComputedStyle(tag) + var _values = styles['_values'] + + var prop = styles.getPropertyValue('background-image') + var name = "background-image" + + if (prop == "") { + if (!styles.getPropertyValue('background') == "") { + prop = styles.getPropertyValue('background') + name = "background" + } else { + name = ""; + prop = ""; + } + } + + if (prop.includes("url(")) { + var start = prop.indexOf('url(') + 4 + var end = prop.indexOf(')') - 4 + + var url = prop.substring(start, end).toString('ascii'); + + if (url.startsWith(location.origin)) { + url = url.split(location.origin) + } else { + url = url.slice(url.indexOf(location.origin)); + } + + url = this.rewriteUrl(url) + tag.style[name] = url + } + } +} + +// JS + +class JavaScriptRewriter extends Cyclone { + constructor(proxy) { + super(); + //Proxied methods + this.setAttrCy = HTMLElement.prototype.setAttribute; + this.getAttrCy = HTMLElement.prototype.getAttribute; + this.proxy = proxy + } + + rewriteJavascript(js) { + var javascript = js.replace(/window\.location/g, 'document._location') + javascript = javascript.replace(/document\.location/g, 'document._location') + return javascript + } + + setAttribute(attr, value, mode) { + const setAttrCy = HTMLElement.prototype.setAttribute; + + if (mode) { + this.setAttrCy.call(this, attr, value); + } else { + var url = attr + if (cyclone.targetAttrs.includes(attr)) { + url = cyclone.rewriteUrl(url); + } + + setAttrCy.call(this, attr, value); + } + } + + getAttribute(attrN, mode) { + const getAttrCy = HTMLElement.prototype.getAttribute; + + if (mode) { + return getAttrCy.call(this, attrN); + } else { + var val = getAttrCy.call(this, attrN); + if (cyclone.targetAttrs.includes(attrN)) { + val = getAttrCy.call(this, 'data-origin-' + attrN); + } + + return val; + } + } +} + +// HTML +class HTMLRewriter extends Cyclone { + rewriteElement(element) { + var targetAttrs = this.targetAttrs; + var attrs; + try { + attrs = [...element.attributes || {}].reduce((attrs, attribute) => { + attrs[attribute.name] = attribute.value; + return attrs; + }, {}); + } catch { + attrs = {}; + } + + if (element.__proto__.getAttribute) { + var jsWrite = new JavaScriptRewriter(); + var elementAttributes = []; + + for (var i = 0; i < targetAttrs.length; i++) { + var attr = targetAttrs[i] + var attrName = Object.keys(attrs)[i]; + var data = { + name: attr, + value: element.getAttribute('data-origin-' + attr, 'cyclone') || element.getAttribute(attr, 'cyclone') + } + + if (data.value) { + elementAttributes.push(data); + } + + if (element.nonce) { + element.setAttribute('nononce', element.nonce, '') + element.removeAttribute('nonce') + } + if (element.integrity) { + element.setAttribute('nointegrity', element.integrity, '') + element.removeAttribute('integrity') + } + + if (element.tagName == "script") { + if (!element.getAttribute('src')) { + var jsRewrite = new JavaScriptRewriter(); + element.innerHTML = jsRewrite.rewriteJavascript(element.innerHTML) + } + } + + // Css + var cssRewrite = new CSSRewriter(); + cssRewrite.rewriteCSS(element) + } + + for (var i = 0; i < elementAttributes.length; i++) { + var attr = elementAttributes[i]; + var attrName = attr.name; + var value = attr.value; + + var bareValue = this.rewriteUrl(value); + if (attrName == "srcset" || attrName == 'srcset') { + bareValue = this.rewriteSrcset(value); + } + + element.setAttribute(attrName, bareValue); + element.setAttribute("data-origin-" + attrName, value); + } + } + } + + rewriteDocument() { + var docElements = document.querySelectorAll('*'); + for (var i = 0; i < docElements.length; i++) { + var element = docElements[i]; + + this.rewriteElement(element) + } + } + + rewriteiFrame(iframe) { + var frameDoc = (iframe.contentWindow || iframe.contentDocument || iframe.document); + + let tags = frameDoc.querySelectorAll('*') + + for (var i = 0; i < tags.length; i++) { + var tag = tags[i] + this.rewriteElement(tag) + } + } + + rewriteDocObject(docObj) { + var docElements = docObj.querySelectorAll('*'); + for (var i = 0; i < docElements.length; i++) { + var element = docElements[i]; + + this.rewriteElement(element) + } + } +} + +const cyclone = new Cyclone(); + +const htmlRewriter = new HTMLRewriter(); + +const FetchIntercept = window.fetch; +window.fetch = async(...args) => { + let [resource, config] = args; + resource = cyclone.rewriteUrl(resource); + + const response = await FetchIntercept(resource, config); + return response; +} + +const MessageIntercept = window.postMessage; +const messageInterceptionFunc = (...args) => { + let [message, target, config] = args; + target = cyclone.rewriteUrl(target); + + const response = MessageIntercept(message, target, config); + console.log(response); + return response; +} + +Object.defineProperty(window, 'postMessage', { + writable: false, + value: messageInterceptionFunc +}) + +var CWOriginal = Object.getOwnPropertyDescriptor(window.HTMLIFrameElement.prototype, 'contentWindow') + +Object.defineProperty(window.HTMLIFrameElement.prototype, 'contentWindow', { + get() { + var iWindow = CWOriginal.get.call(this); + htmlRewriter.rewriteiFrame(iWindow); + + return iWindow + }, + set() { + return false; + } +}) + + +const open = XMLHttpRequest.prototype.open; +XMLHttpRequest.prototype.open = function(method, url, ...rest) { + url = cyclone.rewriteUrl(url) + + return open.call(this, method, url, ...rest); +}; + +var oPush = window.history.pushState; +var oPlace = window.history.replaceState; + +function CycloneStates(dat, unused, url) { + var cyUrl = cyclone.rewriteUrl(url); + + oPush.call(this, dat, unused, cyUrl); +} + +window.history.pushState = CycloneStates +window.history.replaceState = CycloneStates +history.pushState = CycloneStates +history.replaceState = CycloneStates + +const OriginalWebsocket = window.WebSocket +const ProxiedWebSocket = function() { + const ws = new OriginalWebsocket(...arguments) + + const originalAddEventListener = ws.addEventListener + const proxiedAddEventListener = function() { + if (arguments[0] === "message") { + const cb = arguments[1] + arguments[1] = function() { + var origin = arguments[0].origin + arguments[0].origin = cyclone.rewriteUrl(origin); + + return cb.apply(this, arguments) + } + } + return originalAddEventListener.apply(this, arguments) + } + ws.addEventListener = proxiedAddEventListener + + Object.defineProperty(ws, "onmessage", { + set(func) { + return proxiedAddEventListener.apply(this, [ + "message", + func, + false + ]); + } + }); + return ws; +}; + +window.WebSocket = ProxiedWebSocket; + +// Request +var requestProxyHandler = { + get(target, prop, receiver) { + console.log(target); + if (prop == "url") { + return 'the j'; + } + + return Reflect.get(...arguments); + } +} + +Request.prototype = new Proxy(Request.prototype, requestProxyHandler); +Request.__proto__ = new Proxy(Request.__proto__, requestProxyHandler); + +const nwtb = window.open + +function openNewTab(url, target, features) { + url = cyclone.rewriteUrl(url) + nwtb(url, target, features) +} + +window.open = openNewTab; + +window.onload = function() { + for (var i = 0; i < 50; i++) { + setTimeout(() => { + htmlRewriter.rewriteDocument(); + }, 500) + } +} + +let mutationE = new MutationObserver((mutationList, observer) => { + for (const mutation of mutationList) { + mutation.addedNodes.forEach(node => { + htmlRewriter.rewriteElement(node); + }); + } +}).observe(document, { + childList: true, + subtree: true +}) + +//For intercepting all requests +if (!document.serviceWorkerRegistered) { + if ('serviceWorker' in navigator) { + window.addEventListener('load', function() { + navigator.serviceWorker.register(location.origin + '/cySw.js').then(function(registration) { + console.log('Service worker registered with scope: ', registration.scope); + }, function(err) { + console.log('ServiceWorker registration failed: ', err); + }); + }); + } + document.serviceWorkerRegistered = true +} \ No newline at end of file diff --git a/static/cyclone/filter.cyclone.mjs b/static/cyclone/filter.cyclone.mjs new file mode 100644 index 0000000..95dc031 --- /dev/null +++ b/static/cyclone/filter.cyclone.mjs @@ -0,0 +1,82 @@ +import fs from 'fs'; + +const xor = { + encode: (url) => encodeURIComponent(url.toString().split("").map((char, ind) => ind % 2 ? String + .fromCharCode(char.charCodeAt() ^ 2) : char).join("")), + decode: (url) => decodeURIComponent(url.split("?")[0]).split("").map((char, ind) => ind % 2 ? String + .fromCharCode(char.charCodeAt(0) ^ 2) : char).join("") + (url.split("?").slice(1).length ? "?" + + url.split("?").slice(1).join("?") : "") +} + +function getBlockPage(site, reason) { + return ` + + + + + + + +
+

Access Denied

+ +
+ +
+ + + Looks like ${site} is blocked for ${reason} + + +
+ + + +` +} + +const blacklist = [ + 'netflix.com', + 'www.netflix.com', + 'accounts.google.com', +] + +function filter(req, res) { + var decode = req.url.split("/service/")[1]; + + decode = decode.replace("http://", '') + decode = decode.replace("https://", '') + decode = decode.replace("http:/", '') + decode = decode.replace("https:/", '') + + decode = 'https://' + decode; + + var uri = new URL(decode); + + var toBlock = (blacklist.includes(uri.host)); + + if (toBlock) { + var b = getBlockPage(uri.host, 'cyclone__DenyURL'); + res.end(b); + return true; + } else { + return false + } +} + +export { + filter as + default +} // don't want Netflix's legal team to go sicko mode \ No newline at end of file diff --git a/static/cyclone/security.cyclone.mjs b/static/cyclone/security.cyclone.mjs new file mode 100644 index 0000000..22920f3 --- /dev/null +++ b/static/cyclone/security.cyclone.mjs @@ -0,0 +1,18 @@ +import CryptoJS from 'crypto-js'; + +const encryptWithAES = (text) => { + const passphrase = '123'; + return CryptoJS.AES.encrypt(text, passphrase).toString(); +}; + +const decryptWithAES = (ciphertext) => { + const passphrase = '123'; + const bytes = CryptoJS.AES.decrypt(ciphertext, passphrase); + const originalText = bytes.toString(CryptoJS.enc.Utf8); + return originalText; +}; + +export { + encryptWithAES as encrypt, + decryptWithAES as decrypt +} \ No newline at end of file diff --git a/static/index.html b/static/index.html index 1597579..553b2cf 100644 --- a/static/index.html +++ b/static/index.html @@ -1,5 +1,5 @@ - + Nebula @@ -7,14 +7,13 @@ - - + @@ -27,7 +26,7 @@