├── 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 |
57 | 58 |
59 | 60 |
61 |
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 | --------------------------------------------------------------------------------