From b83e2fece42898daecf7df874a9310d0eb05da22 Mon Sep 17 00:00:00 2001
From: TheEmeraldStarr <46467239+Epicloudygamer@users.noreply.github.com>
Date: Tue, 13 Oct 2020 09:34:59 -0700
Subject: [PATCH] Updated Alloy (v2.3)
---
app.js | 539 ++++++++++++++++++++---------------------
blocklist.json | 4 +-
package.json | 5 +-
utils/assets/inject.js | 32 ++-
ws-proxy.js | 87 +++++++
5 files changed, 391 insertions(+), 276 deletions(-)
create mode 100644 ws-proxy.js
diff --git a/app.js b/app.js
index 3af5e7b8..d9ab09e4 100644
--- a/app.js
+++ b/app.js
@@ -1,310 +1,307 @@
-const express = require('express'),
- app = express(),
- http = require('http'),
- https = require('https'),
- fs = require('fs'),
- querystring = require('querystring'),
- session = require('express-session'),
- sanitizer = require('sanitizer'),
- fetch = require('node-fetch');
+ const express = require('express'),
+ app = express(),
+ http = require('http'),
+ https = require('https'),
+ fs = require('fs'),
+ querystring = require('querystring'),
+ session = require('express-session'),
+ sanitizer = require('sanitizer'),
+ websocket = require('./ws-proxy.js'),
+ fetch = require('node-fetch');
-const config = JSON.parse(fs.readFileSync('./config.json', { encoding: 'utf8' }));
-if (!config.prefix.startsWith('/')) {
- config.prefix = `/${config.prefix}`;
-}
+ const config = JSON.parse(fs.readFileSync('./config.json', { encoding: 'utf8' }));
+ if (!config.prefix.startsWith('/')) {
+ config.prefix = `/${config.prefix}`;
+ }
-if (!config.prefix.endsWith('/')) {
- config.prefix = `${config.prefix}/`;
-}
+ if (!config.prefix.endsWith('/')) {
+ config.prefix = `${config.prefix}/`;
+ }
-let server;
-let server_protocol;
-const server_options = {
- key: fs.readFileSync('./ssl/default.key'),
- cert: fs.readFileSync('./ssl/default.crt')
-}
-if (config.ssl == true) {
- server = https.createServer(server_options, app);
- server_protocol = 'https://';
-} else {
- server = http.createServer(app);
- server_protocol = 'http://';
-};
+ let server;
+ let server_protocol;
+ const server_options = {
+ key: fs.readFileSync('./ssl/default.key'),
+ cert: fs.readFileSync('./ssl/default.crt')
+ }
+ if (config.ssl == true) { server = https.createServer(server_options, app);
+ server_protocol = 'https://'; } else { server = http.createServer(app);
+ server_protocol = 'http://'; };
+
+ // WebSocket Proxying
+ websocket(server);
+
+ console.log(`Alloy Proxy now running on ${server_protocol}0.0.0.0:${config.port}! Proxy prefix is "${config.prefix}"!`);
+ server.listen(process.env.PORT || config.port);
+
+ btoa = (str) => {
+ str = new Buffer.from(str).toString('base64');
+ return str;
+ };
+
+ atob = (str) => {
+ str = new Buffer.from(str, 'base64').toString('utf-8');
+ return str;
+ };
+
+ rewrite_url = (dataURL, option) => {
+ var websiteURL;
+ var websitePath;
+ if (option == 'decode') {
+ websiteURL = atob(dataURL.split('/').splice(0, 1).join('/'));
+ websitePath = '/' + dataURL.split('/').splice(1).join('/');
+ } else {
+ websiteURL = btoa(dataURL.split('/').splice(0, 3).join('/'));
+ websitePath = '/' + dataURL.split('/').splice(3).join('/');
+ }
+ if (websitePath == '/') { return `${websiteURL}`; } else return `${websiteURL}${websitePath}`;
+ };
+
+ var login = require('./auth');
+
+ app.use(session({
+ secret: 'alloy',
+ saveUninitialized: true,
+ resave: true
+ }));
+ // We made our own version of body-parser instead, due to issues.
+ app.use((req, res, next) => {
+ if (req.method == 'POST') {
+ req.raw_body = '';
+ req.on('data', chunk => {
+ req.raw_body += chunk.toString(); // convert Buffer to string
+ });
+ req.on('end', () => {
+ req.str_body = req.raw_body;
+ try {
+ req.body = JSON.parse(req.raw_body);
+ } catch (err) {
+ req.body = {}
+ }
+ next();
+ });
+ } else return next();
+ });
+
+ app.use(`${config.prefix}utils/`, async(req, res, next) => {
+ if (req.url.startsWith('/assets/')) { res.sendFile(__dirname + '/utils' + req.url); }
+ if (req.query.url) {
+ let url = atob(req.query.url);
+ if (url.startsWith('https://') || url.startsWith('http://')) {
+ url = url;
+ } else if (url.startsWith('//')) {
+ url = 'http:' + url;
+ } else {
+ url = 'http://' + url;
+ }
+ return res.redirect(307, config.prefix + rewrite_url(url));
+ }
+ });
+
+ app.post(`${config.prefix}session/`, async(req, res, next) => {
+ let url = querystring.parse(req.raw_body).url;
+ if (url.startsWith('//')) { url = 'http:' + url; } else if (url.startsWith('https://') || url.startsWith('http://')) { url = url } else { url = 'http://' + url };
+ return res.redirect(config.prefix + rewrite_url(url));
+ });
+
+ app.use(config.prefix, async(req, res, next) => {
+ var proxy = {};
+ proxy.url = rewrite_url(req.url.slice(1), 'decode');
+ proxy.url = {
+ href: proxy.url,
+ hostname: proxy.url.split('/').splice(2).splice(0, 1).join('/'),
+ origin: proxy.url.split('/').splice(0, 3).join('/'),
+ encoded_origin: btoa(proxy.url.split('/').splice(0, 3).join('/')),
+ path: '/' + proxy.url.split('/').splice(3).join('/'),
+ protocol: proxy.url.split('\:').splice(0, 1).join(''),
+ }
+
+ proxy.url.encoded_origin = btoa(proxy.url.origin);
+
+ proxy.requestHeaders = req.headers;
+ proxy.requestHeaders['host'] = proxy.url.hostname;
+ if (proxy.requestHeaders['referer']) {
+ let referer = '/' + String(proxy.requestHeaders['referer']).split('/').splice(3).join('/');
+
+ referer = rewrite_url(referer.replace(config.prefix, ''), 'decode');
+
+ if (referer.startsWith('https://') || referer.startsWith('http://')) {
+ referer = referer;
+
+ } else referer = proxy.url.href;
+
+ proxy.requestHeaders['referer'] = referer;
+ }
-console.log(`Alloy Proxy now running on ${server_protocol}0.0.0.0:${config.port}! Proxy prefix is "${config.prefix}"!`);
-server.listen(process.env.PORT || config.port);
+ if (proxy.requestHeaders['origin']) {
+ let origin = '/' + String(proxy.requestHeaders['origin']).split('/').splice(3).join('/');
+ origin = rewrite_url(origin.replace(config.prefix, ''), 'decode');
-var login = require('./auth');
+ if (origin.startsWith('https://') || origin.startsWith('http://')) {
+ origin = origin.split('/').splice(0, 3).join('/');
-btoa = (str) => {
- str = new Buffer.from(str).toString('base64');
- return str;
-};
+ } else origin = proxy.url.origin;
-atob = (str) => {
- str = new Buffer.from(str, 'base64').toString('utf-8');
- return str;
-};
+ proxy.requestHeaders['origin'] = origin;
+ }
+ if (proxy.requestHeaders.cookie) {
+ delete proxy.requestHeaders.cookie;
+ }
+ const httpAgent = new http.Agent({
+ keepAlive: true
+ });
+ const httpsAgent = new https.Agent({
+ rejectUnauthorized: false,
+ keepAlive: true
+ });
+ proxy.options = {
+ method: req.method,
+ headers: proxy.requestHeaders,
+ redirect: 'manual',
+ agent: function(_parsedURL) {
+ if (_parsedURL.protocol == 'http:') {
+ return httpAgent;
+ } else {
+ return httpsAgent;
+ }
+ }
+ };
-rewrite_url = (dataURL, option) => {
- var websiteURL;
- var websitePath;
- if (option == 'decode') {
- websiteURL = atob(dataURL.split('/').splice(0, 1).join('/'));
- websitePath = '/' + dataURL.split('/').splice(1).join('/');
- } else {
- websiteURL = btoa(dataURL.split('/').splice(0, 3).join('/'));
- websitePath = '/' + dataURL.split('/').splice(3).join('/');
- }
- if (websitePath == '/') { return `${websiteURL}`; } else return `${websiteURL}${websitePath}`;
-};
+ if (req.method == 'POST') {
+ proxy.options.body = req.str_body;
+ }
+ if (proxy.url.hostname == 'discord.com' && proxy.url.path == '/') { return res.redirect(307, config.prefix + rewrite_url('https://discord.com/login')); };
-app.use(session({
- secret: 'alloy',
- saveUninitialized: true,
- resave: true
-}));
-// We made our own version of body-parser instead, due to issues.
-app.use((req, res, next) => {
- if (req.method == 'POST') {
- req.raw_body = '';
- req.on('data', chunk => {
- req.raw_body += chunk.toString(); // convert Buffer to string
- });
- req.on('end', () => {
- req.str_body = req.raw_body;
- try {
- req.body = JSON.parse(req.raw_body);
- } catch (err) {
- req.body = {}
- }
- next();
- });
- } else return next();
-});
+ if (proxy.url.hostname == 'www.reddit.com') { return res.redirect(307, config.prefix + rewrite_url('https://old.reddit.com')); };
-app.use(`${config.prefix}utils/`, async(req, res, next) => {
- if (req.url.startsWith('/assets/')) { res.sendFile(__dirname + '/utils' + req.url); }
- if (req.query.url) {
- let url = atob(req.query.url);
- if (url.startsWith('https://') || url.startsWith('http://')) {
- url = url;
- } else if (url.startsWith('//')) {
- url = 'http:' + url;
- } else {
- url = 'http://' + url;
- }
- return res.redirect(307, config.prefix + rewrite_url(url));
- }
-});
+ if (!req.url.slice(1).startsWith(`${proxy.url.encoded_origin}/`)) { return res.redirect(307, config.prefix + proxy.url.encoded_origin + '/'); };
-app.post(`${config.prefix}session/`, async(req, res, next) => {
- let url = querystring.parse(req.raw_body).url;
- if (url.startsWith('//')) { url = 'http:' + url; } else if (url.startsWith('https://') || url.startsWith('http://')) { url = url } else { url = 'http://' + url };
- return res.redirect(config.prefix + rewrite_url(url));
-});
+ const blocklist = JSON.parse(fs.readFileSync('./blocklist.json', { encoding: 'utf8' }));
-app.use(config.prefix, async(req, res, next) => {
- var proxy = {};
- proxy.url = rewrite_url(req.url.slice(1), 'decode');
- proxy.url = {
- href: proxy.url,
- hostname: proxy.url.split('/').splice(2).splice(0, 1).join('/'),
- origin: proxy.url.split('/').splice(0, 3).join('/'),
- encoded_origin: btoa(proxy.url.split('/').splice(0, 3).join('/')),
- path: '/' + proxy.url.split('/').splice(3).join('/'),
- protocol: proxy.url.split('\:').splice(0, 1).join(''),
- }
+ let is_blocked = false;
- proxy.url.encoded_origin = btoa(proxy.url.origin);
+ Array.from(blocklist).forEach(blocked_hostname => {
+ if (proxy.url.hostname == blocked_hostname) {
+ is_blocked = true;
+ }
+ });
- proxy.requestHeaders = req.headers;
- proxy.requestHeaders['host'] = proxy.url.hostname;
- if (proxy.requestHeaders['referer']) {
- let referer = '/' + String(proxy.requestHeaders['referer']).split('/').splice(3).join('/');
+ if (is_blocked == true) { return res.send(fs.readFileSync('./utils/error/error.html', 'utf8').toString().replace('%ERROR%', `Error 401: The website '${sanitizer.sanitize(proxy.url.hostname)}' is not permitted!`)) }
- referer = rewrite_url(referer.replace(config.prefix, ''), 'decode');
+ proxy.response = await fetch(proxy.url.href, proxy.options).catch(err => res.send(fs.readFileSync('./utils/error/error.html', 'utf8').toString().replace('%ERROR%', `Error 400: Could not make request to '${sanitizer.sanitize(proxy.url.href)}'!`)));
- if (referer.startsWith('https://') || referer.startsWith('http://')) {
- referer = referer;
+ if (typeof proxy.response.buffer != 'function') return;
- } else referer = proxy.url.href;
+ proxy.buffer = await proxy.response.buffer();
- proxy.requestHeaders['referer'] = referer;
- }
+ proxy.content_type = 'text/plain';
+ proxy.response.headers.forEach((e, i, a) => {
+ if (i == 'content-type') proxy.content_type = e;
+ });
+ if (proxy.content_type == null || typeof proxy.content_type == 'undefined') proxy.content_type = 'text/html';
- if (proxy.requestHeaders['origin']) {
- let origin = '/' + String(proxy.requestHeaders['origin']).split('/').splice(3).join('/');
+ proxy.sendResponse = proxy.buffer;
- origin = rewrite_url(origin.replace(config.prefix, ''), 'decode');
+ // Parsing the headers from the response to remove square brackets so we can set them as the response headers.
+ proxy.headers = Object.fromEntries(
+ Object.entries(JSON.parse(JSON.stringify(proxy.response.headers.raw())))
+ .map(([key, val]) => [key, val[0]])
+ );
- if (origin.startsWith('https://') || origin.startsWith('http://')) {
+ // Parsing all the headers to remove all of the bad headers that could affect proxies performance.
+ Object.entries(proxy.headers).forEach(([header_name, header_value]) => {
+ if (header_name.startsWith('content-encoding') || header_name.startsWith('x-') || header_name.startsWith('cf-') || header_name.startsWith('strict-transport-security') || header_name.startsWith('content-security-policy')) {
+ delete proxy.headers[header_name];
+ }
+ });
- origin = origin.split('/').splice(0, 3).join('/');
+ // If theres a location for a redirect in the response, then the proxy will get the response location then redirect you to the proxied version of the url.
+ if (proxy.response.headers.get('location')) {
+ return res.redirect(307, config.prefix + rewrite_url(String(proxy.response.headers.get('location'))));
+ }
- } else origin = proxy.url.origin;
+ res.status(proxy.response.status);
+ res.set(proxy.headers);
+ res.contentType(proxy.content_type);
+ if (proxy.content_type.startsWith('text/html')) {
+ req.session.url = proxy.url.origin;
+ proxy.sendResponse = proxy.sendResponse.toString()
+ .replace(/integrity="(.*?)"/gi, '')
+ .replace(/nonce="(.*?)"/gi, '')
+ .replace(/(href|src|poster|data|action|srcset)="\/\/(.*?)"/gi, `$1` + `="http://` + `$2` + `"`)
+ .replace(/(href|src|poster|data|action|srcset)='\/\/(.*?)'/gi, `$1` + `='http://` + `$2` + `'`)
+ .replace(/(href|src|poster|data|action|srcset)="\/(.*?)"/gi, `$1` + `="${config.prefix}${proxy.url.encoded_origin}/` + `$2` + `"`)
+ .replace(/(href|src|poster|data|action|srcset)='\/(.*?)'/gi, `$1` + `='${config.prefix}${proxy.url.encoded_origin}/` + `$2` + `'`)
+ .replace(/'(https:\/\/|http:\/\/)(.*?)'/gi, function(str) {
+ str = str.split(`'`).slice(1).slice(0, -1).join(``);
+ return `'${config.prefix}${rewrite_url(str)}'`
+ })
+ .replace(/"(https:\/\/|http:\/\/)(.*?)"/gi, function(str) {
+ str = str.split(`"`).slice(1).slice(0, -1).join(``);
+ return `"${config.prefix}${rewrite_url(str)}"`
+ })
+ .replace(/(window|document).location.href/gi, `"${proxy.url.href}"`)
+ .replace(/(window|document).location.hostname/gi, `"${proxy.url.hostname}"`)
+ .replace(/(window|document).location.pathname/gi, `"${proxy.url.path}"`)
+ .replace(/location.href/gi, `"${proxy.url.href}"`)
+ .replace(/location.hostname/gi, `"${proxy.url.hostname}"`)
+ .replace(/location.pathname/gi, `"${proxy.url.path}"`)
+ .replace(//gi, ``);
- proxy.requestHeaders['origin'] = origin;
- }
- if (proxy.requestHeaders.cookie) {
- delete proxy.requestHeaders.cookie;
- }
- const httpAgent = new http.Agent({
- keepAlive: true
- });
- const httpsAgent = new https.Agent({
- rejectUnauthorized: false,
- keepAlive: true
- });
- proxy.options = {
- method: req.method,
- headers: proxy.requestHeaders,
- redirect: 'manual',
- agent: function(_parsedURL) {
- if (_parsedURL.protocol == 'http:') {
- return httpAgent;
- } else {
- return httpsAgent;
- }
- }
- };
+ // Temp hotfix for Youtube search bar until my script injection can fix it.
- if (req.method == 'POST') {
- proxy.options.body = req.str_body;
- }
- if (proxy.url.hostname == 'discord.com' && proxy.url.path == '/') { return res.redirect(307, config.prefix + rewrite_url('https://discord.com/login')); };
+ if (proxy.url.hostname == 'www.youtube.com') { proxy.sendResponse = proxy.sendResponse.replace(/\/results/gi, `${config.prefix}${proxy.url.encoded_origin}/results`); };
+ } else if (proxy.content_type.startsWith('text/css')) {
+ proxy.sendResponse = proxy.sendResponse.toString()
+ .replace(/url\("\/\/(.*?)"\)/gi, `url("http://` + `$1` + `")`)
+ .replace(/url\('\/\/(.*?)'\)/gi, `url('http://` + `$1` + `')`)
+ .replace(/url\(\/\/(.*?)\)/gi, `url(http://` + `$1` + `)`)
+ .replace(/url\("\/(.*?)"\)/gi, `url("${config.prefix}${proxy.url.encoded_origin}/` + `$1` + `")`)
+ .replace(/url\('\/(.*?)'\)/gi, `url('${config.prefix}${proxy.url.encoded_origin}/` + `$1` + `')`)
+ .replace(/url\(\/(.*?)\)/gi, `url(${config.prefix}${proxy.url.encoded_origin}/` + `$1` + `)`)
+ .replace(/"(https:\/\/|http:\/\/)(.*?)"/gi, function(str) {
+ str = str.split(`"`).slice(1).slice(0, -1).join(``);
+ return `"${config.prefix}${rewrite_url(str)}"`
+ })
+ .replace(/'(https:\/\/|http:\/\/)(.*?)'/gi, function(str) {
+ str = str.split(`'`).slice(1).slice(0, -1).join(``);
+ return `'${config.prefix}${rewrite_url(str)}'`
+ })
+ .replace(/\((https:\/\/|http:\/\/)(.*?)\)/gi, function(str) {
+ str = str.split(`(`).slice(1).join(``).split(')').slice(0, -1).join('');
+ return `(${config.prefix}${rewrite_url(str)})`
+ });
- if (proxy.url.hostname == 'www.reddit.com') { return res.redirect(307, config.prefix + rewrite_url('https://old.reddit.com')); };
+ };
+ // We send the response from the server rewritten.
+ res.send(proxy.sendResponse);
+ });
- if (!req.url.slice(1).startsWith(`${proxy.url.encoded_origin}/`)) { return res.redirect(307, config.prefix + proxy.url.encoded_origin + '/'); };
+ app.use('/', express.static('public'));
- const blocklist = JSON.parse(fs.readFileSync('./blocklist.json', { encoding: 'utf8' }));
+ app.use(async(req, res, next) => {
+ if (req.headers['referer']) {
- let is_blocked = false;
+ let referer = '/' + String(req.headers['referer']).split('/').splice(3).join('/');
- Array.from(blocklist).forEach(blocked_hostname => {
- if (proxy.url.hostname == blocked_hostname) {
- is_blocked = true;
- }
- });
+ referer = rewrite_url(referer.replace(config.prefix, ''), 'decode').split('/').splice(0, 3).join('/');
- if (is_blocked == true) { return res.send(fs.readFileSync('./utils/error/error.html', 'utf8').toString().replace('%ERROR%', `Error 401: The website '${sanitizer.sanitize(proxy.url.hostname)}' is not permitted!`)) }
+ if (referer.startsWith('https://') || referer.startsWith('http://')) {
+ res.redirect(307, config.prefix + btoa(referer) + req.url)
+ } else {
+ if (req.session.url) {
- proxy.response = await fetch(proxy.url.href, proxy.options).catch(err => res.send(fs.readFileSync('./utils/error/error.html', 'utf8').toString().replace('%ERROR%', `Error 400: Could not make request to '${sanitizer.sanitize(proxy.url.href)}'!`)));
+ res.redirect(307, config.prefix + btoa(req.session.url) + req.url)
- if (typeof proxy.response.buffer != 'function') return;
+ } else return next();
+ }
+ } else if (req.session.url) {
- proxy.buffer = await proxy.response.buffer();
+ res.redirect(307, config.prefix + btoa(req.session.url) + req.url)
- proxy.content_type = 'text/plain';
-
- proxy.response.headers.forEach((e, i, a) => {
- if (i == 'content-type') proxy.content_type = e;
- });
- if (proxy.content_type == null || typeof proxy.content_type == 'undefined') proxy.content_type = 'text/html';
-
- proxy.sendResponse = proxy.buffer;
-
- // Parsing the headers from the response to remove square brackets so we can set them as the response headers.
- proxy.headers = Object.fromEntries(
- Object.entries(JSON.parse(JSON.stringify(proxy.response.headers.raw())))
- .map(([key, val]) => [key, val[0]])
- );
-
- // Parsing all the headers to remove all of the bad headers that could affect proxies performance.
- Object.entries(proxy.headers).forEach(([header_name, header_value]) => {
- if (header_name.startsWith('content-encoding') || header_name.startsWith('x-') || header_name.startsWith('cf-') || header_name.startsWith('strict-transport-security') || header_name.startsWith('content-security-policy')) {
- delete proxy.headers[header_name];
- }
- });
-
- // If theres a location for a redirect in the response, then the proxy will get the response location then redirect you to the proxied version of the url.
- if (proxy.response.headers.get('location')) {
- return res.redirect(307, config.prefix + rewrite_url(String(proxy.response.headers.get('location'))));
- }
-
- res.status(proxy.response.status);
- res.set(proxy.headers);
- res.contentType(proxy.content_type);
- if (proxy.content_type.startsWith('text/html')) {
- req.session.url = proxy.url.origin;
- proxy.sendResponse = proxy.sendResponse.toString()
- .replace(/integrity="(.*?)"/gi, '')
- .replace(/nonce="(.*?)"/gi, '')
- .replace(/(href|src|poster|data|action|srcset)="\/\/(.*?)"/gi, `$1` + `="http://` + `$2` + `"`)
- .replace(/(href|src|poster|data|action|srcset)='\/\/(.*?)'/gi, `$1` + `='http://` + `$2` + `'`)
- .replace(/(href|src|poster|data|action|srcset)="\/(.*?)"/gi, `$1` + `="${config.prefix}${proxy.url.encoded_origin}/` + `$2` + `"`)
- .replace(/(href|src|poster|data|action|srcset)='\/(.*?)'/gi, `$1` + `='${config.prefix}${proxy.url.encoded_origin}/` + `$2` + `'`)
- .replace(/'(https:\/\/|http:\/\/)(.*?)'/gi, function(str) {
- str = str.split(`'`).slice(1).slice(0, -1).join(``);
- return `'${config.prefix}${rewrite_url(str)}'`
- })
- .replace(/"(https:\/\/|http:\/\/)(.*?)"/gi, function(str) {
- str = str.split(`"`).slice(1).slice(0, -1).join(``);
- return `"${config.prefix}${rewrite_url(str)}"`
- })
- .replace(/(window|document).location.href/gi, `"${proxy.url.href}"`)
- .replace(/(window|document).location.hostname/gi, `"${proxy.url.hostname}"`)
- .replace(/(window|document).location.pathname/gi, `"${proxy.url.path}"`)
- .replace(/location.href/gi, `"${proxy.url.href}"`)
- .replace(/location.hostname/gi, `"${proxy.url.hostname}"`)
- .replace(/location.pathname/gi, `"${proxy.url.path}"`)
- .replace(//gi, ``);
-
- // Temp hotfix for Youtube search bar until my script injection can fix it.
-
- if (proxy.url.hostname == 'www.youtube.com') { proxy.sendResponse = proxy.sendResponse.replace(/\/results/gi, `${config.prefix}${proxy.url.encoded_origin}/results`); };
- } else if (proxy.content_type.startsWith('text/css')) {
- proxy.sendResponse = proxy.sendResponse.toString()
- .replace(/url\("\/\/(.*?)"\)/gi, `url("http://` + `$1` + `")`)
- .replace(/url\('\/\/(.*?)'\)/gi, `url('http://` + `$1` + `')`)
- .replace(/url\(\/\/(.*?)\)/gi, `url(http://` + `$1` + `)`)
- .replace(/url\("\/(.*?)"\)/gi, `url("${config.prefix}${proxy.url.encoded_origin}/` + `$1` + `")`)
- .replace(/url\('\/(.*?)'\)/gi, `url('${config.prefix}${proxy.url.encoded_origin}/` + `$1` + `')`)
- .replace(/url\(\/(.*?)\)/gi, `url(${config.prefix}${proxy.url.encoded_origin}/` + `$1` + `)`)
- .replace(/"(https:\/\/|http:\/\/)(.*?)"/gi, function(str) {
- str = str.split(`"`).slice(1).slice(0, -1).join(``);
- return `"${config.prefix}${rewrite_url(str)}"`
- })
- .replace(/'(https:\/\/|http:\/\/)(.*?)'/gi, function(str) {
- str = str.split(`'`).slice(1).slice(0, -1).join(``);
- return `'${config.prefix}${rewrite_url(str)}'`
- })
- .replace(/\((https:\/\/|http:\/\/)(.*?)\)/gi, function(str) {
- str = str.split(`(`).slice(1).join(``).split(')').slice(0, -1).join('');
- return `(${config.prefix}${rewrite_url(str)})`
- });
-
- };
- // We send the response from the server rewritten.
- res.send(proxy.sendResponse);
-});
-
-app.use('/', express.static('public'));
-
-app.use(async(req, res, next) => {
- if (req.headers['referer']) {
-
- let referer = '/' + String(req.headers['referer']).split('/').splice(3).join('/');
-
- referer = rewrite_url(referer.replace(config.prefix, ''), 'decode').split('/').splice(0, 3).join('/');
-
- if (referer.startsWith('https://') || referer.startsWith('http://')) {
- res.redirect(307, config.prefix + btoa(referer) + req.url)
- } else {
- if (req.session.url) {
-
- res.redirect(307, config.prefix + btoa(req.session.url) + req.url)
-
- } else return next();
- }
- } else if (req.session.url) {
-
- res.redirect(307, config.prefix + btoa(req.session.url) + req.url)
-
- } else return next();
-});
\ No newline at end of file
+ } else return next();
+ });
\ No newline at end of file
diff --git a/blocklist.json b/blocklist.json
index 093b2077..4676dedc 100644
--- a/blocklist.json
+++ b/blocklist.json
@@ -1,3 +1,3 @@
[
- "example.com"
-]
\ No newline at end of file
+ "add-your-website-url.blocked"
+]
diff --git a/package.json b/package.json
index 6493c266..0c3b2325 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "alloy-proxy",
- "version": "2.2.0",
+ "version": "2.3.0",
"description": "A web proxy capable of proxying websites!",
"main": "app.js",
"scripts": {
@@ -21,6 +21,7 @@
"node-fetch": "^2.6.1",
"sanitizer": "^0.1.3",
"session": "^0.1.0",
- "cookies": "0.4"
+ "cookies": "0.4",
+ "ws": "^7.3.1"
}
}
\ No newline at end of file
diff --git a/utils/assets/inject.js b/utils/assets/inject.js
index 391b9ac0..e539cb77 100644
--- a/utils/assets/inject.js
+++ b/utils/assets/inject.js
@@ -71,9 +71,39 @@ let setattribute_rewrite = window.Element.prototype.setAttribute; window.Element
return setattribute_rewrite.apply(this, arguments)
}
+// Rewriting all incoming websocket request.
+
+ WebSocket = new Proxy(WebSocket, {
+
+ construct(target, args_array) {
+
+ var protocol;
+
+ if (location.protocol == 'https:') { protocol = 'wss://' } else { protocol = 'ws://' }
+
+ args_array[0] = protocol + location.origin.split('/').splice(2).join('/') + prefix + 'ws/' + btoa(args_array[0]);
+
+ return new target(args_array);
+ }
+
+ });
+
+ // Rewriting incoming pushstate.
+
+ history.pushState = new Proxy(history.pushState, {
+
+ apply: (target, thisArg, args_array) => {
+
+ args_array[2] = rewrite_url(args_array[2])
+
+ return target.apply(thisArg, args_array)
+ }
+
+ });
+
var previousState = window.history.state;
setInterval(function() {
if (!window.location.pathname.startsWith(`${prefix}${btoa(url.origin)}/`)) {
history.replaceState('', '', `${prefix}${btoa(url.origin)}/${window.location.href.split('/').splice(3).join('/')}`);
}
-}, 0.1);
\ No newline at end of file
+}, 0.1);
diff --git a/ws-proxy.js b/ws-proxy.js
new file mode 100644
index 00000000..1c8f2aac
--- /dev/null
+++ b/ws-proxy.js
@@ -0,0 +1,87 @@
+ const WebSocket = require('ws'),
+ fs = require('fs');
+
+ const config = JSON.parse(fs.readFileSync('./config.json', {encoding:'utf8'}));
+
+ if (!config.prefix.startsWith('/')) {
+
+ config.prefix = `/${config.prefix}`;
+
+ }
+
+ if (!config.prefix.endsWith('/')) {
+
+ config.prefix = `${config.prefix}/`;
+
+ }
+
+ btoa = (str) => {
+
+ str = new Buffer.from(str).toString('base64');
+
+ return str;
+
+ };
+
+ atob = (str) => {
+
+ str = new Buffer.from(str, 'base64').toString('utf-8');
+
+ return str;
+
+ };
+
+ module.exports = (server) => {
+
+ const wss = new WebSocket.Server({ server: server });
+
+ wss.on('connection', (cli, req) => {
+
+ try {
+
+ const svr = new WebSocket(atob(req.url.toString().replace(`${config.prefix}ws/`, '')));
+
+ svr.on('message', (data) => {
+
+ try { cli.send(data) } catch(err){}
+
+ });
+
+ svr.on('open', () => {
+
+ cli.on('message', (data) => {
+
+ svr.send(data)
+
+ });
+
+ });
+
+
+ cli.on('close', (code) => {
+
+ try { svr.close(code); } catch(err) { svr.close(1006) };
+
+ });
+
+ svr.on('close', (code) => {
+
+ try { cli.close(code); } catch(err) { cli.close(1006) };
+
+ });
+
+ cli.on('error', (err) => {
+
+ try { svr.close(1001); } catch(err) { svr.close(1006) };
+
+ });
+
+ svr.on('error', (err) => {
+
+ try { cli.close(1001); } catch(err) { cli.close(1006) };
+
+ });
+
+ } catch(err) { cli.close(1001); }
+ });
+ }