├── README.md
├── index.js
├── lib
├── dom.js
├── error.html
├── index.js
└── window.js
├── package.json
└── public
├── index.html
└── stargazers.html
/README.md:
--------------------------------------------------------------------------------
1 | # tProxy v2
2 | ## Whats new in v2?
3 | - New looks
4 | - Updated links to my pages
5 | - Stargazers page, free promotion ig
6 | - You no longer have to provide http or https protocol, It just guesses it so you can just type example.com
7 | - It now redirects instead of using an iframe, that annoying URL bar was in the way
8 | ## Upcoming
9 | - Cloaking
10 | - Built-in UnblockedHardest
11 | - Deploy tProxy buttons
12 | - Better error pages
13 | - Site compatibility list
14 | - Use better and faster backend
15 | - Exploits page
16 | - Alert user if tProxy gets blocked after 5 fetch() requests to the main page
17 | ## Setup
18 | Use npm to setup tProxy
19 | ```
20 | npm i
21 | npm start
22 | ```
23 | or use yarn, yarn is better tbh
24 | ```
25 | yarn
26 | node .
27 | ```
28 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | const http = require('http');
2 | const https = require('https');
3 | const fs = require('fs');
4 |
5 | // CONFIGURATION
6 | const prefix = '/web'; // Set your prefix here
7 | const localAddresses = []; // Set your local addresses here
8 | const blockedHostnames = ["https://sevenworks.eu.org/bad-site"]; // Set your blocked hostnames here
9 | const ssl = false; // Set SSL configuration here
10 | const port = 6969; // Set the desired port
11 | const index_file = 'index.html'; // Set index file shown by the browser
12 | // END OF CONFIGURATION
13 |
14 | const proxy = new (require('./lib/index'))(prefix, {
15 | localAddress: localAddresses,
16 | blacklist: blockedHostnames
17 | });
18 |
19 | const atob = str => Buffer.from(str, 'base64').toString('utf-8');
20 |
21 | const app = (req, res) => {
22 | if (req.url.startsWith(prefix)) {
23 | proxy.http(req, res);
24 | return;
25 | }
26 |
27 | req.pathname = req.url.split('#')[0].split('?')[0];
28 | req.query = {};
29 | req.url
30 | .split('#')[0]
31 | .split('?')
32 | .slice(1)
33 | .join('?')
34 | .split('&')
35 | .forEach(query => (req.query[query.split('=')[0]] = query.split('=').slice(1).join('=')));
36 |
37 | if (req.query.url && (req.pathname == '/prox' || req.pathname == '/prox/' || req.pathname == '/session' || req.pathname == '/session/')) {
38 | var url = atob(req.query.url);
39 |
40 | if (url.startsWith('https://') || url.startsWith('http://')) url = url;
41 | else if (url.startsWith('//')) url = 'http:' + url;
42 | else url = 'http://' + url;
43 |
44 | res.writeHead(301, { location: prefix + proxy.proxifyRequestURL(url) });
45 | res.end('');
46 | return;
47 | }
48 |
49 | const publicPath = __dirname + '/public' + req.pathname;
50 |
51 | const error = () => {
52 | res.statusCode = 404;
53 | res.end(fs.readFileSync(__dirname + '/lib/error.html', 'utf-8').replace('%ERR%', `Cannot ${req.method} ${req.pathname}`));
54 | };
55 |
56 | fs.lstat(publicPath, (err, stats) => {
57 | if (err) return error();
58 |
59 | if (stats.isDirectory()) {
60 | fs.existsSync(publicPath + index_file) ? fs.createReadStream(publicPath + index_file).pipe(res) : error();
61 | } else if (stats.isFile()) {
62 | !publicPath.endsWith('/') ? fs.createReadStream(publicPath).pipe(res) : error();
63 | } else {
64 | error();
65 | }
66 | });
67 | };
68 |
69 | const server = ssl
70 | ? https.createServer({ key: fs.readFileSync('./ssl/default.key'), cert: fs.readFileSync('./ssl/default.crt') }, app)
71 | : http.createServer(app);
72 |
73 | proxy.ws(server);
74 | server.listen(process.env.PORT || port, () => console.log(`${ssl ? 'https://' : 'http://'}0.0.0.0:${port}`));
75 |
--------------------------------------------------------------------------------
/lib/error.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
26 |
27 |
28 |
29 |
30 |
31 |
%ERR%
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | const http = require('http'),
2 | https = require('https'),
3 | fs = require('fs'),
4 | zlib = require('zlib'),
5 | querystring = require('querystring'),
6 | WebSocket = require('ws'),
7 | btoa = str => new Buffer.from(str).toString('base64'),
8 | atob = str => new Buffer.from(str, 'base64').toString('utf-8');
9 |
10 | module.exports = class {
11 |
12 | constructor(prefix = "/web/", config = {}) {
13 | this.prefix = prefix;
14 | this.config = config;
15 | this.proxifyRequestURL = (url, type) => type ? atob(url.split('_').slice(1).splice(0, 1).join()) + url.split('_').slice(2).join('_') : `_${btoa(url.split('/').splice(0, 3).join('/'))}_/${url.split('/').splice(3).join('/')}`
16 |
17 | if (!prefix.startsWith('/')) this.prefix = '/' + prefix;
18 | if (!prefix.endsWith('/')) this.prefix = prefix + '/';
19 | };
20 |
21 | http(req, res, next = () => res.end('')) {
22 |
23 | if (!req.url.startsWith(this.prefix)) return next();
24 |
25 | req.path = req.url.replace(this.prefix.slice(1), '');
26 | req.pathname = req.path.split('#')[0].split('?')[0];
27 |
28 | if (req.pathname == '/client_hook' || req.pathname == '/client_hook/') return res.end(fs.readFileSync(__dirname + '/window.js', 'utf-8'));
29 |
30 | try {
31 | new URL(this.proxifyRequestURL(req.path, true))
32 | } catch {
33 | return res.end('URL Parse Error')
34 | };
35 |
36 | var proxyURL = {
37 | href: this.proxifyRequestURL(req.path, true),
38 | origin: this.proxifyRequestURL(req.path, true).split('/').splice(0, 3).join('/'),
39 | hostname: this.proxifyRequestURL(req.path, true).split('/').splice(0, 3).slice(2).join('/')
40 | },
41 | proxify = {},
42 | isBlocked = false,
43 | protocol = proxyURL.href.startsWith('https://') ? https : http,
44 | proxyOptions = {
45 | headers: Object.assign({}, req.headers),
46 | method: req.method,
47 | rejectUnauthorized: false
48 | };
49 |
50 | if (proxyURL.href.startsWith('https://') || proxyURL.href.startsWith('http://'));
51 | else return res.end('URL Parse Error');
52 |
53 | delete proxyOptions.headers['host'];
54 |
55 | if (typeof this.config.blacklist == 'object' && this.config.blacklist.length != 0) this.config.blacklist.forEach(blacklisted => proxyURL.hostname == blacklisted ? isBlocked = true : isBlocked = false);
56 | if (isBlocked) return res.end('The URL you are trying to access is not permitted for use.')
57 |
58 | if (!req.path.startsWith(`/_${btoa(proxyURL.origin)}_/`)) return (res.writeHead(308, {
59 | location: this.prefix + `_${btoa(proxyURL.origin)}_/`
60 | }), res.end(''));
61 |
62 | if (proxyOptions.headers['origin']) {
63 | var proxified_header = this.proxifyRequestURL(`/${proxyOptions.headers['origin'].split('/').splice(3).join('/')}`.replace(this.prefix, ''), true);
64 | if (proxified_header.startsWith('https://') || proxified_header.startsWith('http://')) proxified_header = proxified_header.split('/').splice(0, 3).join('/');
65 | else proxified_header = proxyURL.origin;
66 | proxyOptions.headers['origin'] = proxified_header;
67 | }
68 |
69 | if (proxyOptions.headers['referer']) {
70 |
71 | var proxified_header = this.proxifyRequestURL('/' + proxyOptions.headers['referer'].split('/').splice(3).join('/').replace(this.prefix, ''), true);
72 | if (proxified_header.startsWith('https://') || proxified_header.startsWith('http://')) proxified_header = proxified_header;
73 | else proxified_header = proxyURL.href;
74 |
75 | proxyOptions.headers['referer'] = proxified_header;
76 |
77 | }
78 |
79 | if (proxyOptions.headers['cookie']) {
80 | var new_cookie = [],
81 | cookie_array = proxyOptions.headers['cookie'].split('; ');
82 |
83 | cookie_array.forEach(cookie => {
84 |
85 | const cookie_name = cookie.split('=').splice(0, 1).join(),
86 | cookie_value = cookie.split('=').splice(1).join();
87 |
88 | if (proxyURL.hostname.includes(cookie_name.split('@').splice(1).join())) new_cookie.push(cookie_name.split('@').splice(0, 1).join() + '=' + cookie_value);
89 |
90 | });
91 |
92 | proxyOptions.headers['cookie'] = new_cookie.join('; ');
93 | };
94 |
95 | if (typeof this.config.localAddress == 'object' && this.config.localAddress.length != 0) proxyOptions.localAddress = this.config.localAddress[Math.floor(Math.random() * this.config.localAddress.length)];
96 |
97 | var makeRequest = protocol.request(proxyURL.href, proxyOptions, proxyResponse => {
98 |
99 | var rawData = [],
100 | sendData = '';
101 |
102 | proxyResponse.on('data', data => rawData.push(data)).on('end', () => {
103 |
104 | const inject_config = {
105 | prefix: this.prefix,
106 | url: proxyURL.href
107 | }
108 |
109 | proxify.url = url => {
110 |
111 | if (url.match(/^(#|about:|data:|blob:|mailto:|javascript:|{|\*)/)) return url;
112 |
113 | if (url.startsWith('//')) url = new URL('http:' + url);
114 | else if (url.startsWith('/')) url = new URL(proxyURL.origin + url);
115 | else if (url.startsWith('https://') || url.startsWith('http://')) url = new URL(url);
116 | else url = new URL(proxyURL.href.split('/').slice(0, -1).join('/') + '/' + url);
117 |
118 | if (url.protocol == 'https:' || url.protocol == 'http:') return this.prefix + this.proxifyRequestURL(url.href);
119 | else return url.href;
120 |
121 | };
122 |
123 | proxify.js = buffer => buffer.toString().replace(/(,| |=|\()document.location(,| |=|\)|\.)/gi, str => {
124 | return str.replace('.location', `.alloyLocation`);
125 | })
126 | .replace(/(,| |=|\()window.location(,| |=|\)|\.)/gi, str => {
127 | return str.replace('.location', `.alloyLocation`);
128 | })
129 | .replace(/(,| |=|\()location(,| |=|\)|\.)/gi, str => {
130 | return str.replace('location', `alloyLocation`);
131 | });
132 |
133 | proxify.css = buffer => {
134 | return buffer.replace(/url\("(.*?)"\)/gi, str => {
135 | var url = str.replace(/url\("(.*?)"\)/gi, '$1');
136 | return `url("${proxify.url(url)}")`;
137 | }).replace(/url\('(.*?)'\)/gi, str => {
138 | var url = str.replace(/url\('(.*?)'\)/gi, '$1');
139 | return `url('${proxify.url(url)}')`;
140 | }).replace(/url\((.*?)\)/gi, str => {
141 | var url = str.replace(/url\((.*?)\)/gi, '$1');
142 |
143 | if (url.startsWith(`"`) || url.startsWith(`'`)) return str;
144 |
145 | return `url("${proxify.url(url)}")`;
146 | }).replace(/@import (.*?)"(.*?)";/gi, str => {
147 | var url = str.replace(/@import (.*?)"(.*?)";/, '$2');
148 | return `@import "${proxify.url(url)}";`
149 | }).replace(/@import (.*?)'(.*?)';/gi, str => {
150 | var url = str.replace(/@import (.*?)'(.*?)';/, '$2');
151 | return `@import '${proxify.url(url)}';`
152 | })
153 | };
154 |
155 | proxify.html = body => {
156 |
157 | const html = new(require('./dom')).JSDOM(body, {
158 | contentType: 'text/html'
159 | }),
160 | document = html.window.document;
161 |
162 | var base_tag = false;
163 |
164 | if (document.querySelector('head base')) base_tag = document.querySelector('head base').getAttribute('href');
165 |
166 | if (base_tag) {
167 |
168 | if (base_tag.includes('#') || base_tag.includes('?')) base_tag = base_tag.split('#')[0].split('?')[0];
169 |
170 | if (base_tag.startsWith('//')) base_tag = 'http:' + base_tag;
171 |
172 | if (base_tag.startsWith('https://') || base_tag.startsWith('http://')) base_tag = new URL(base_tag).href;
173 | else if (base_tag.startsWith('/')) base_tag = new URL(proxyURL.origin + base_tag).href;
174 | else base_tag = new URL(proxyURL.href.split('/').slice(0, -1).join('/') + '/' + base_tag).href;
175 |
176 | inject_config.baseURL = base_tag;
177 |
178 | };
179 |
180 | proxify.attribute = attribute => {
181 | if (attribute.startsWith('https://') || attribute.startsWith('http://') || attribute.startsWith('//')) return proxify.url(attribute);
182 | else if (base_tag) {
183 | if (attribute.startsWith('/')) return attribute = proxify.url(base_tag.split('/').splice(0, 3).join('/') + attribute);
184 | else return attribute = proxify.url(base_tag.split('/').slice(0, -1).join('/') + '/' + attribute);
185 | } else return proxify.url(attribute);
186 | };
187 |
188 | document.querySelectorAll('*').forEach(node => {
189 | if (node.getAttribute('nonce')) node.removeAttribute('nonce');
190 | if (node.getAttribute('integrity')) node.removeAttribute('integrity');
191 | if (node.getAttribute('style')) node.setAttribute('style', proxify.css(node.getAttribute('style')));
192 | });
193 |
194 | document.querySelectorAll("script, embed, iframe, audio, video, img, input, source, track").forEach(node => {
195 | if (node.src) node.src = proxify.attribute(node.src);
196 | if (node.tagName.toLowerCase() == 'script' && node.innerHTML != '') node.innerHTML = proxify.js(node.innerHTML);
197 | });
198 |
199 | document.querySelectorAll("img[srcset], source[srcset]").forEach(node => {
200 | var arr = [];
201 |
202 | node.srcset.split(',').forEach(url => {
203 | url = url.trimStart().split(' ');
204 | url[0] = proxify.attribute(url[0]);
205 | arr.push(url.join(' '));
206 | });
207 |
208 | node.srcset = arr.join(', ')
209 | });
210 |
211 | document.querySelectorAll("a, link, area").forEach(node => {
212 | if (node.href) node.href = proxify.attribute(node.href);
213 | });
214 |
215 | document.querySelectorAll('base').forEach(node => node.href = proxify.attribute(node.href));
216 |
217 | document.querySelectorAll('form').forEach(node => {
218 | if (node.action) node.action = proxify.attribute(node.action);
219 | });
220 |
221 | document.querySelectorAll('style').forEach(node => {
222 | node.textContent = proxify.css(node.textContent);
223 | });
224 |
225 | const inject_script = document.createElement('script');
226 |
227 | inject_script.src = this.prefix + 'client_hook';
228 | inject_script.setAttribute('data-config', btoa(JSON.stringify(inject_config)));
229 |
230 | document.querySelector('head').insertBefore(inject_script, document.querySelector('head').childNodes[0])
231 |
232 | return html.serialize();
233 |
234 | };
235 |
236 | if (rawData.length != 0) switch (proxyResponse.headers['content-encoding']) {
237 | case 'gzip':
238 | sendData = zlib.gunzipSync(Buffer.concat(rawData));
239 | break;
240 | case 'deflate':
241 | sendData = zlib.inflateSync(Buffer.concat(rawData));
242 | break;
243 | case 'br':
244 | sendData = zlib.brotliDecompressSync(Buffer.concat(rawData));
245 | break;
246 | default:
247 | sendData = Buffer.concat(rawData);
248 | break;
249 | };
250 |
251 | Object.entries(proxyResponse.headers).forEach(([header_name, header_value]) => {
252 | if (header_name == 'set-cookie') {
253 | const cookie_array = [];
254 | header_value.forEach(cookie => cookie_array.push(cookie.replace(/Domain=(.*?);/gi, `Domain=` + req.headers['host'] + ';').replace(/(.*?)=(.*?);/, '$1' + '@' + proxyURL.hostname + `=` + '$2' + ';')));
255 | proxyResponse.headers[header_name] = cookie_array;
256 |
257 | };
258 |
259 | 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') || header_name.startsWith('content-length')) delete proxyResponse.headers[header_name];
260 |
261 | if (header_name == 'location') proxyResponse.headers[header_name] = proxify.url(header_value);
262 | });
263 |
264 | if (proxyResponse.headers['content-type'] && proxyResponse.headers['content-type'].startsWith('text/html')) sendData = proxify.html(sendData.toString());
265 | else if (proxyResponse.headers['content-type'] && (proxyResponse.headers['content-type'].startsWith('application/javascript') || proxyResponse.headers['content-type'].startsWith('text/javascript'))) sendData = proxify.js(sendData.toString());
266 | else if (proxyResponse.headers['content-type'] && proxyResponse.headers['content-type'].startsWith('text/css')) sendData = proxify.css(sendData.toString());
267 |
268 | res.writeHead(proxyResponse.statusCode, proxyResponse.headers);
269 | res.end(sendData);
270 |
271 | });
272 |
273 | });
274 |
275 | makeRequest.on('error', err => res.end(err.toString()))
276 |
277 | if (!res.writableEnded) req.on('data', data => makeRequest.write(data)).on('end', () => makeRequest.end());
278 |
279 | };
280 |
281 | ws(server) {
282 | new WebSocket.Server({
283 | server: server
284 | }).on('connection', (cli, req) => {
285 |
286 | var queryParams = querystring.parse(req.url.split('?').splice(1).join('?')),
287 | proxyURL, options = {
288 | headers: {},
289 | followRedirects: true
290 | },
291 | protocol = [];
292 |
293 | if (!queryParams.ws) return cli.close();
294 |
295 | proxyURL = atob(queryParams.ws);
296 |
297 | try {
298 | new URL(proxyURL)
299 | } catch {
300 | return cli.close()
301 | };
302 |
303 | Object.entries(req.headers).forEach(([header_name, header_value]) => {
304 | if (header_name == 'sec-websocket-protocol') header_value.split(', ').forEach(proto => protocol.push(proto));
305 | if (header_name.startsWith('cf-') || header_name.startsWith('cdn-loop'));
306 | else if (!header_name.startsWith('sec-websocket')) options.headers[header_name] = header_value;
307 | })
308 |
309 | if (queryParams.origin)(options.origin = atob(queryParams.origin), options.headers.origin = atob(queryParams.origin));
310 |
311 | delete options.headers['host'];
312 | delete options.headers['cookie'];
313 |
314 | if (typeof this.config.localAddress == 'object' && this.config.localAddress.length != 0) options.localAddress = this.config.localAddress[Math.floor(Math.random() * this.config.localAddress.length)];
315 |
316 | const proxy = new WebSocket(proxyURL, protocol, options),
317 | before_open = [];
318 |
319 | if (proxy.readyState == 0) cli.on('message', data => before_open.push(data));
320 |
321 | cli.on('close', () => proxy.close());
322 | proxy.on('close', () => cli.close());
323 | cli.on('error', () => proxy.terminate())
324 | proxy.on('error', () => cli.terminate());
325 |
326 | proxy.on('open', () => {
327 |
328 | if (before_open.length != 0) before_open.forEach(data => proxy.send(data))
329 |
330 | cli.on('message', data => proxy.send(data));
331 | proxy.on('message', data => cli.send(data));
332 |
333 | });
334 |
335 | });
336 | };
337 | };
--------------------------------------------------------------------------------
/lib/window.js:
--------------------------------------------------------------------------------
1 | // Alloy sucks but its a proxy that works with some of my sites so im forced to use it
2 | // Switching to a different backend soon
3 | // Cry about it TitaniumNetwork
4 |
5 | var alloy = JSON.parse(atob(document.currentScript.getAttribute('data-config')));
6 | alloy.url = new URL(alloy.url)
7 |
8 | window.alloyLocation = new Proxy({}, {
9 | set(obj, prop, value) {
10 |
11 | if (prop == 'assign' || prop == 'reload' || prop == 'replace' || prop == 'toString') return;
12 |
13 | console.log(proxify.url(alloy.url.href.replace(alloy.url[prop], value)));
14 |
15 | console.log((alloy.url.href.replace(alloy.url[prop], value)));
16 |
17 | return location[prop] = proxify.url(alloy.url.href.replace(alloy.url[prop], value));
18 | },
19 | get(obj, prop) {
20 |
21 | if (alloy.url.origin == atob('aHR0cHM6Ly9kaXNjb3JkLmNvbQ==') && alloy.url.pathname == '/app') return window.location[prop];
22 |
23 | if (prop == 'assign' || prop == 'reload' || prop == 'replace' || prop == 'toString') return {
24 | assign: arg => window.location.assign(proxify.url(arg)),
25 | replace: arg => window.location.replace(proxify.url(arg)),
26 | reload: () => window.location.reload(),
27 | toString: () => { return alloy.url.href }
28 | }[prop];
29 | else return alloy.url[prop];
30 | }
31 | });
32 |
33 | window.document.alloyLocation = window.alloyLocation;
34 |
35 | Object.defineProperty(document, 'domain', {
36 | get() {
37 | return alloy.url.hostname;
38 | },
39 | set(value) {
40 | return value;
41 | }
42 | });
43 |
44 | var proxify = {
45 | url: (url, type) => {
46 |
47 | if (!url) return;
48 |
49 | var proxified;
50 |
51 | switch(type) {
52 | case true:
53 | proxified = atob(url.replace(alloy.prefix, '').split('_').slice(1).splice(0, 1).join()) + url.split('_').slice(2).join('_');
54 | break;
55 |
56 | default:
57 |
58 | if (url.match(/^(#|about:|data:|blob:|mailto:|javascript:|{|\*)/) || url.startsWith(alloy.prefix) || url.startsWith(window.location.origin + alloy.prefix)) return url;
59 |
60 | if (url.startsWith(window.location.origin + '/') && !url.startsWith(window.location.origin + alloy.prefix)) url = '/' + url.split('/').splice(3).join('/');
61 |
62 | if (url.startsWith('//')) url = 'http:' + url;
63 | if (url.startsWith('/') && !url.startsWith(alloy.prefix)) url = alloy.url.origin + url;
64 |
65 | if (url.startsWith('https://') || url.startsWith('http://')) url = new URL(url);
66 | else url = new URL(alloy.url.href.split('/').slice(0, -1).join('/') + '/' + url);
67 |
68 | proxified = alloy.prefix + '_' + btoa(url.href.split('/').splice(0, 3).join('/')) + '_' + "/" + url.href.split('/').splice(3).join('/');
69 |
70 | break;
71 | }
72 | return proxified;
73 | }
74 | };
75 |
76 | proxify.url_http = url => {
77 |
78 | if (url.match(/^(#|about:|data:|blob:|mailto:|javascript:|{|\*)/) || url.startsWith(alloy.prefix) || url.startsWith(window.location.origin + alloy.prefix)) return url;
79 |
80 | if (url.startsWith('https://') || url.startsWith('http://') || url.startsWith('//')) return proxify.url(url);
81 | else if (alloy.baseURL) {
82 | if (url.startsWith('/')) return url = proxify.url(alloy.baseURL.split('/').splice(0, 3).join('/') + url);
83 | else return url = proxify.url(alloy.baseURL.split('/').slice(0, -1).join('/') + '/' + url);
84 | } else return proxify.url(url);
85 | };
86 |
87 | let originalFetch = window.fetch,
88 | originalXMLOpen = window.XMLHttpRequest.prototype.open,
89 | originalOpen = window.open,
90 | originalPostMessage = window.postMessage,
91 | originalSendBeacon = window.Navigator.prototype.sendBeacon;
92 |
93 | window.fetch = function(url, options) {
94 |
95 | if (url) (url.replace(location.hostname, alloy.url.hostname), url = proxify.url_http(url));
96 | return originalFetch.apply(this, arguments);
97 | };
98 | window.XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
99 | if (url) (url.replace(location.hostname, alloy.url.hostname), url = proxify.url_http(url));
100 | return originalXMLOpen.apply(this, arguments);
101 | };
102 | window.open = function(url, windowName, windowFeatures) {
103 | if (url) url = proxify.url(url);
104 | return originalOpen.apply(this, arguments);
105 | };
106 | window.postMessage = function(msg, origin, transfer) {
107 | if (origin) origin = location.origin;
108 | return originalPostMessage.apply(this, arguments);
109 | };
110 | window.Navigator.prototype.sendBeacon = function(url, data) {
111 | if (url) url = proxify.url(url);
112 | return originalSendBeacon.apply(this, arguments);
113 | };
114 |
115 | window.WebSocket = new Proxy(window.WebSocket, {
116 | construct(target, args) {
117 | var protocol;
118 | if (location.protocol == 'https:') protocol = 'wss://'; else protocol = 'ws://';
119 |
120 | args[0] = protocol + location.origin.split('/').splice(2).join('/') + alloy.prefix + '?ws=' + btoa(args[0]) + '&origin=' + btoa(alloy.url.origin);
121 |
122 | return Reflect.construct(target, args);
123 | }
124 | });
125 |
126 | proxify.elementHTML = element_array => {
127 | element_array.forEach(element => {
128 | Object.defineProperty(element.prototype, 'innerHTML', {
129 | set(value) {
130 | const elem = new DOMParser().parseFromString(Object.getOwnPropertyDescriptor(window.Element.prototype, "outerHTML").get.call(this), 'text/html').body.querySelectorAll('*')[0];
131 | Object.getOwnPropertyDescriptor(window.Element.prototype, "innerHTML").set.call(elem, value);
132 | elem.querySelectorAll("script[src], iframe[src], embed[src], audio[src], img[src], input[src], source[src], track[src], video[src]").forEach(node => node.setAttribute('src', node.getAttribute('src')));
133 | elem.querySelectorAll("object[data]").forEach(node => node.setAttribute('data', node.getAttribute('data')));
134 | elem.querySelectorAll("a[href], link[href], area[href").forEach(node => node.setAttribute('href', node.getAttribute('href')));
135 | return Object.getOwnPropertyDescriptor(window.Element.prototype, "innerHTML").set.call(this, elem.innerHTML);
136 | },
137 | get() {
138 | return Object.getOwnPropertyDescriptor(window.Element.prototype, "innerHTML").get.call(this);
139 | }
140 | });
141 | Object.defineProperty(element.prototype, 'outerHTML', {
142 | set(value) {
143 | const elem = new DOMParser().parseFromString(Object.getOwnPropertyDescriptor(window.Element.prototype, "outerHTML").get.call(this), 'text/html').body;
144 | Object.getOwnPropertyDescriptor(window.Element.prototype, "outerHTML").set.call(elem.querySelectorAll('*')[0], value);
145 | elem.querySelectorAll("script[src], iframe[src], embed[src], audio[src], img[src], input[src], source[src], track[src], video[src]").forEach(node => node.setAttribute('src', node.getAttribute('src')));
146 | elem.querySelectorAll("object[data]").forEach(node => node.setAttribute('data', node.getAttribute('data')));
147 | elem.querySelectorAll("a[href], link[href], area[href").forEach(node => node.setAttribute('href', node.getAttribute('href')));
148 | return Object.getOwnPropertyDescriptor(window.Element.prototype, "outerHTML").set.call(this, elem.innerHTML);
149 | },
150 | get() {
151 | return Object.getOwnPropertyDescriptor(window.Element.prototype, "outerHTML").get.call(this);
152 | }
153 | });
154 | });
155 | };
156 |
157 | proxify.elementAttribute = (element_array, attribute_array) => {
158 | element_array.forEach(element => {
159 |
160 | if (element == window.HTMLScriptElement) {
161 | Object.defineProperty(element.prototype, 'integrity', {
162 | set(value) {
163 | return this.removeAttribute('integrity')
164 | },
165 | get() {
166 | return this.getAttribute('integrity');
167 | }
168 | });
169 | Object.defineProperty(element.prototype, 'nonce', {
170 | set(value) {
171 | return this.removeAttribute('nonce')
172 | },
173 | get() {
174 | return this.getAttribute('nonce');
175 | }
176 | });
177 | }
178 |
179 | element.prototype.setAttribute = new Proxy(element.prototype.setAttribute, {
180 | apply(target, thisArg, [ element_attribute, value ]) {
181 | attribute_array.forEach(array_attribute => {
182 |
183 | if (array_attribute == 'srcset' && element_attribute.toLowerCase() == array_attribute) {
184 | var arr = [];
185 |
186 | value.split(',').forEach(url => {
187 | url = url.trimStart().split(' ');
188 | url[0] = proxify.url_http(url[0]);
189 | arr.push(url.join(' '));
190 | });
191 |
192 | return Reflect.apply(target, thisArg, [ element_attribute, arr.join(', ') ]);
193 | };
194 |
195 | if (element_attribute.toLowerCase() == array_attribute) value = proxify.url_http(value);
196 | });
197 | return Reflect.apply(target, thisArg, [ element_attribute, value ]);
198 | }
199 | });
200 |
201 | attribute_array.forEach(attribute => {
202 |
203 | Object.defineProperty(element.prototype, attribute, {
204 | set(value) {
205 | return this.setAttribute(attribute, value);
206 | },
207 | get() {
208 | return this.getAttribute(attribute);
209 | }
210 | });
211 |
212 | });
213 |
214 | });
215 | };
216 |
217 | document.write = new Proxy(document.write, {
218 | apply(target, thisArg, args) {
219 | var processedHTML = new DOMParser().parseFromString(args[0], 'text/html');
220 |
221 | processedHTML.querySelectorAll("script[src], iframe[src], embed[src], audio[src], img[src], input[src], source[src], track[src], video[src]").forEach(node => node.setAttribute('src', node.getAttribute('src')));
222 | processedHTML.querySelectorAll("object[data]").forEach(node => node.setAttribute('data', node.getAttribute('data')));
223 | processedHTML.querySelectorAll("a[href], link[href], area[href").forEach(node => node.setAttribute('href', node.getAttribute('href')));
224 |
225 | return Reflect.apply(target, thisArg, [ processedHTML.querySelector('html').outerHTML ]);
226 |
227 | }
228 | });
229 |
230 | proxify.elementHTML([ window.HTMLDivElement ]);
231 |
232 | proxify.elementAttribute([ window.HTMLAnchorElement, window.HTMLLinkElement, window.HTMLAreaElement ], [ 'href' ]);
233 |
234 | proxify.elementAttribute([ window.HTMLScriptElement, window.HTMLIFrameElement, window.HTMLEmbedElement, window.HTMLAudioElement, window.HTMLInputElement, window.HTMLTrackElement, window.HTMLVideoElement ], [ 'src' ]);
235 |
236 | proxify.elementAttribute([ window.HTMLImageElement, HTMLSourceElement ], [ 'src', 'srcset' ]);
237 |
238 | proxify.elementAttribute([ window.HTMLObjectElement ], [ 'data' ]);
239 |
240 | proxify.elementAttribute([ window.HTMLFormElement ], [ 'action' ]);
241 |
242 | window.History.prototype.pushState = new Proxy(window.History.prototype.pushState, {
243 | apply(target, thisArg, args) {
244 |
245 | if (alloy.url.origin == atob('aHR0cHM6Ly9kaXNjb3JkLmNvbQ==') && args[2] == '/app') {
246 | args[2] = proxify.url(args[2])
247 | Reflect.apply(target, thisArg, args);
248 | return window.location.reload();
249 | }
250 |
251 | args[2] = proxify.url(args[2])
252 | return Reflect.apply(target, thisArg, args)
253 | }
254 | });
255 |
256 | window.History.prototype.replaceState = new Proxy(window.History.prototype.replaceState, {
257 | apply(target, thisArg, args) {
258 | args[2] = proxify.url(args[2])
259 | return Reflect.apply(target, thisArg, args)
260 | }
261 | });
262 |
263 | window.Worker = new Proxy(window.Worker, {
264 | construct(target, args) {
265 | args[0] = proxify.url(args[0]);
266 | return Reflect.construct(target, args);
267 | }
268 | });
269 |
270 | Object.defineProperty(document, 'cookie', {
271 | get() {
272 | var cookie = Object.getOwnPropertyDescriptor(window.Document.prototype, 'cookie').get.call(this),
273 | new_cookie = [],
274 | cookie_array = cookie.split('; ');
275 |
276 | cookie_array.forEach(cookie => {
277 |
278 | const cookie_name = cookie.split('=').splice(0, 1).join(),
279 | cookie_value = cookie.split('=').splice(1).join();
280 |
281 | if (alloy.url.hostname.includes(cookie_name.split('@').splice(1).join())) new_cookie.push(cookie_name.split('@').splice(0, 1).join() + '=' + cookie_value);
282 |
283 | });
284 | return new_cookie.join('; ');;
285 | },
286 | set(value) {
287 | return Object.getOwnPropertyDescriptor(window.Document.prototype, 'cookie').set.call(this, value);
288 | }
289 | });
290 |
291 | document.currentScript.remove();
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tProxy",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "directories": {
7 | "lib": "lib"
8 | },
9 | "scripts": {
10 | "test": "echo \"Error: no test specified\" && exit 1",
11 | "start": "node index.js"
12 | },
13 | "keywords": [],
14 | "author": "",
15 | "license": "ISC",
16 | "dependencies": {
17 | "jsdom": "^16.7.0",
18 | "ws": "^7.5.7"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | tProxy
7 |
8 |
51 |
52 |
53 | tProxy v2
54 |
55 |
56 |
62 |
63 |
68 |
69 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/public/stargazers.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Stargazers
7 |
8 |
9 | Stargazers - Star the repo on GitHub to be here!
10 |
11 |
36 |
37 |
38 |
--------------------------------------------------------------------------------