Replaced Node with Alloy locally.

This commit is contained in:
TheEmeraldStarr 2020-09-10 19:02:31 -07:00
parent a9683c8086
commit 53bc98d6f3
15 changed files with 889 additions and 353 deletions

View file

@ -1,2 +1,69 @@
# HolyUB
A website that can be used to bypass web filters; both online and firewall.
# Alloy Proxy
A node.js proxy that features URL encoding, and amazing compatablity!
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/titaniumnetwork-dev/alloyproxy/)
# How to install and use:
`git clone https://github.com/titaniumnetwork-dev/alloyproxy.git`
`cd alloyproxy`
`npm install`
`npm start`
The default place for the proxy when its started is `http://localhost:8080` but feel free to change it in config.json!
# How the proxy works:
The proxy works by using node-fetch (Basically Window.fetch ported to Node-js).
Basically what the app is doing is node-fetch is sending the request to the server then
the app sends the response back to the server with the modifactions made to the attributes and elements.
When a attribute is rewritten, depending on the contents inside. It will turn:
`href="/assets/js/main.js"` into `href="/fetch/websiteURL/assets/js/main.js"`.
A porition of its rewriting is in client-side JS so `Element.setAttribute`, `window.fetch()`, XMLHttpRequest, and more are rewritten.
# Extra information:
If your gonna have an external website redirect to this proxy. Then we recommend you have the value base64 encoded and redirected to `/alloy?url=` then value.
# Deploying to Heroku:
If your gonna be hosting this on something like Heroku. You need to make sure SSL mode is turned off so this will work.
# Known websites that work
- Google Search
- Discord
- LittleBigSnake
- Surviv.io
- Youtube
- Y8
- 1v1.LOL
- Old Reddit
and plenty more!
# Known issues that need to be fixed
- Better POST body parsing instead of using body-parser.
- Cookie header rewriting
# Updates to come in the future
- Full URL encoding / encryption mode
- Websocket proxing

88
alloy/assets/error.html Normal file
View file

@ -0,0 +1,88 @@
<html>
<head>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap" rel="stylesheet">
<style>
body {
background-color: #222;
font-family: "Roboto";
color: #FFF;
margin: 0;
}
input {
background-color: #111;
color :#FFF;
border-radius: 4px;
border: none;
padding-top: 3px;
padding-bottom: 3px;
width: 300px;
font-size: 19px;
height: 45px;
margin-bottom: 5px;
font-family: 'Roboto';
text-align: center;
}
button {
background-color: #3333cc;
color :#FFF;
border-radius: 4px;
border: none;
padding-top: 3px;
padding-bottom: 3px;
width: 300px;
font-size: 19px;
height: 45px;
padding-left: 0;
padding-right: 0;
transition: 0.3s;
}
button:hover{
cursor: pointer;
background-color: #4d4dff;
}
.container p {
margin-bottom: 10px;
font-size: 30px;
}
.top {
top: 0;
left: 0;
right: 0;
border-bottom: #FFF solid 1px;
}
.top p {
font-family: "Noto Sans JP";
font-size: 30px;
margin: 22px 22px;
display: block
}
#error {
padding: 0px 5px;
font-size: 22px;
}
</style>
</head>
<body>
<div class="top">
<p>AlloyProxy</p>
</div>
<p id="error">%ERROR%</p>
</body>
</html>

209
alloy/assets/inject.js Normal file
View file

@ -0,0 +1,209 @@
// Ajax Rewriting
let apData = document.getElementById('alloyData');
let urlData = apData.getAttribute('data-alloyURL');
function rewriteURL(url, encoding) {
var websiteURL
if (encoding == 'base64') {
websiteURL = btoa(url.split('/').splice(0, 3).join('/'))
} else {
websiteURL = url.split('/').splice(0, 3).join('/')
}
const path = '/' + url.split('/').splice(3).join('/')
var rewritten
if (path == '/') {
rewritten = '/fetch/' + websiteURL
} else {
rewritten = `/fetch/${websiteURL}${path}`
}
return rewritten
}
let ajaxRewrite = window.XMLHttpRequest.prototype.open;window.XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
if (url.startsWith(`${window.location.protocol}//${window.location.hostname}`) && !url.startsWith(`${window.location.protocol}//${window.location.hostname}/fetch/`)) {
url = `/fetch/${urlData}/` + url.split('/').splice(3).join('/')
} else if (url.startsWith('http')) {
const hostname = url.split('/').slice(0, 3).join('/')
const path = url.split('/').slice(3).join('/')
const encodedHost = btoa(hostname)
const fullURL = encodedHost + '/' + path
url = '/fetch/' + fullURL
} else if (url.startsWith('//')) {
const encodedURL = btoa('http:' + url)
url = '/alloy/?url=' + encodedURL
} else if (url.startsWith('/')) {
if (url.startsWith('/fetch')) {
url = url
} else if (url.startsWith('/alloy')) {
url = url
} else {
let apData = document.getElementById('alloyData');
let urlData = apData.getAttribute('data-alloyURL');
url = '/fetch/' + urlData + url
}
}
return ajaxRewrite.apply(this, arguments);
}
let windowFetchRewrite = window.fetch;window.fetch = function(url) {
if (url.startsWith(`https://${window.location.hostname}`)) {
url = url
} else if (url.startsWith('http')) {
const hostname = url.split('/').slice(0, 3).join('/')
const path = url.split('/').slice(3).join('/')
const encodedHost = btoa(hostname)
const fullURL = encodedHost + '/' + path
url = '/fetch/' + fullURL
} else if (url.startsWith('//')) {
const encodedURL = btoa('http:' + url)
url = '/alloy/?url=' + encodedURL
} else if (url.startsWith('/')) {
if (url.startsWith('/fetch')) {
url = url
} else if (url.startsWith('/alloy')) {
url = url
} else {
let apData = document.getElementById('alloyData');
let urlData = apData.getAttribute('data-alloyURL');
url = '/fetch/' + urlData + url
}
}
return windowFetchRewrite.apply(this, arguments);
}
//Create Element rewriting
var original = document.createElement;
document.createElement = function (tag) {
var element = original.call(document, tag);
if (tag.toLowerCase() === 'script') {
Object.defineProperty(element.__proto__, 'src', {
set: function(newValue) {
if (newValue.startsWith('/fetch/')) {
element.setAttribute('src', newValue)
} else if (newValue.startsWith('/alloy/')) {
element.setAttribute('src', newValue)
} else if (newValue.startsWith(`https://${window.location.hostname}`)) {
element.setAttribute('src', newValue)
} else if (newValue.startsWith('//')) {
const encodedURL = btoa('http:' + newValue)
element.setAttribute('src', '/alloy/?url=' + encodedURL)
} else if (newValue.startsWith('https://')) {
const encodedURL = btoa(newValue)
element.setAttribute('src', '/alloy/?url=' + encodedURL)
} else if (newValue.startsWith('http://')) {
const encodedURL = btoa(newValue)
element.setAttribute('src', '/alloy/?url=' + encodedURL)
} else if (newValue.startsWith('/')) {
element.setAttribute('src', '/fetch/' + urlData + newValue)
} else {
element.setAttribute('src', newValue)
}
}
});
} else if (tag.toLowerCase() === 'iframe') {
Object.defineProperty(element.__proto__, 'src', {
set: function(newValue) {
if (newValue.startsWith('/fetch/')) {
element.setAttribute('src', newValue)
} else if (newValue.startsWith('/alloy/')) {
element.setAttribute('src', newValue)
} else if (newValue.startsWith(`https://${window.location.hostname}`)) {
element.setAttribute('src', newValue)
} else if (newValue.startsWith('//')) {
const encodedURL = btoa('http:' + newValue)
element.setAttribute('src', '/alloy/?url=' + encodedURL)
} else if (newValue.startsWith('https://')) {
const encodedURL = btoa(newValue)
element.setAttribute('src', '/alloy/?url=' + encodedURL)
} else if (newValue.startsWith('http://')) {
const encodedURL = btoa(newValue)
element.setAttribute('src', '/alloy/?url=' + encodedURL)
} else if (newValue.startsWith('/')) {
element.setAttribute('src', '/fetch/' + urlData + newValue)
} else {
element.setAttribute('src', newValue)
}
}
});
}
else if (tag.toLowerCase() === 'link') {
Object.defineProperty(element.__proto__, 'href', {
set: function(newValue) {
if (newValue.startsWith('/fetch/')) {
element.setAttribute('href', newValue)
} else if (newValue.startsWith('/alloy/')) {
element.setAttribute('href', newValue)
} else if (newValue.startsWith(`https://${window.location.hostname}`)) {
element.setAttribute('href', newValue)
} else if (newValue.startsWith('//')) {
const encodedURL = btoa('http:' + newValue)
element.setAttribute('href', '/alloy/?url=' + encodedURL)
} else if (newValue.startsWith('https://')) {
const encodedURL = btoa(newValue)
element.setAttribute('href', '/alloy/?url=' + encodedURL)
} else if (newValue.startsWith('http://')) {
const encodedURL = btoa(newValue)
element.setAttribute('href', '/alloy/?url=' + encodedURL)
} else if (newValue.startsWith('/')) {
element.setAttribute('href', '/fetch/' + urlData + newValue)
} else {
element.setAttribute('href', newValue)
}
}
});
}
return element;
}
let setAttributeRewrite = window.Element.prototype.setAttribute;window.Element.prototype.setAttribute = function(name, value) {
switch(name) {
case 'src':
if (value.startsWith('/fetch/')) {
value = value
} else if (value.startsWith('/alloy/')) {
value = value
} else if (value.startsWith('//')) {
value = rewriteURL('http:' + value, 'base64')
} else if (value.startsWith('/')) {
value = rewriteURL(urlData + value)
break;
} else if (value.startsWith('https://') || value.startsWith('http://')) {
value = rewriteURL(value, 'base64')
} else {
value = value
}
break;
case 'href':
if (value.startsWith('/fetch/')) {
value = value
} else if (value.startsWith('//')) {
value = rewriteURL('http:' + value, 'base64')
} else if (value.startsWith('/')) {
value = rewriteURL(urlData + value)
break;
} else if (value.startsWith('https://') || value.startsWith('http://')) {
value = rewriteURL(value, 'base64')
} else {
value = value
}
break;
}
return setAttributeRewrite.apply(this, arguments);
}
var previousState = window.history.state;
setInterval(function() {
if (!window.location.pathname.startsWith(`/fetch/${urlData}/`)) {
history.replaceState('', '', `/fetch/${urlData}/${window.location.href.split('/').splice(3).join('/')}`);
}
}, 0.1);

385
app.js
View file

@ -1,79 +1,334 @@
/***************
* node-unblocker: Web Proxy for evading firewalls and content filters,
* similar to CGIProxy or PHProxy
*
*
* This project is hosted on github: https://github.com/nfriedly/nodeunblocker.com
*
* By Nathan Friedly - http://nfriedly.com
* Released under the terms of the Affero GPL v3
*/
var url = require('url');
var querystring = require('querystring');
var https = require('https');
var http = require('http');
var fetch = require('node-fetch');
var express = require('express');
var unblocker = require('unblocker');
var Transform = require('stream').Transform;
var fs = require('fs');
var app = express();
var cookieParser = require('cookie-parser');
var session = require('express-session');
var google_analytics_id = process.env.GA_ID || null;
var config = JSON.parse(fs.readFileSync('config.json', 'utf-8')),
httpsAgent = new https.Agent({
rejectUnauthorized: false,
keepAlive: true,
}),
httpAgent = new http.Agent({
rejectUnauthorized: false,
keepAlive: true,
}),
ssl = { key: fs.readFileSync('ssl/default.key', 'utf8'), cert: fs.readFileSync('ssl/default.crt', 'utf8') },
server,
port = process.env.PORT || config.port,
ready = (() => {
var a = 'http://', b = config.listenip;
if (config.ssl) a = 'https://';
if (b == '0.0.0.0' || b == '127.0.0.1') b = 'localhost';
console.log('AlloyProxy is now running at', a + b + ':' + port);
});
function addGa(html) {
if (google_analytics_id) {
var ga = [
"<script type=\"text/javascript\">",
"var _gaq = []; // overwrite the existing one, if any",
"_gaq.push(['_setAccount', '" + google_analytics_id + "']);",
"_gaq.push(['_trackPageview']);",
"(function() {",
" var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;",
" ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';",
" var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);",
"})();",
"</script>"
].join("\n");
html = html.replace("</body>", ga + "\n\n</body>");
}
return html;
}
http.globalAgent.maxSockets = Infinity;
https.globalAgent.maxSockets = Infinity;
function googleAnalyticsMiddleware(data) {
if (data.contentType == 'text/html') {
if (config.ssl) server = https.createServer(ssl, app).listen(port, config.listenip, ready);
else server = http.createServer(app).listen(port, config.listenip, ready);
// https://nodejs.org/api/stream.html#stream_transform
data.stream = data.stream.pipe(new Transform({
decodeStrings: false,
transform: function(chunk, encoding, next) {
this.push(addGa(chunk.toString()));
next();
}
}));
}
}
app.use(cookieParser());
app.use(session({
secret: 'alloy',
saveUninitialized: true,
resave: true
}));
var unblockerConfig = {
prefix: '/call/',
responseMiddleware: [
googleAnalyticsMiddleware
]
};
app.use((req, res, next)=>{
// nice bodyparser alternative that wont cough up errors
req.setEncoding('utf8');
req.raw_body = ''
req.body = new Object()
req.on('data', chunk=>{ req.raw_body += chunk });
// this line must appear before any express.static calls (or anything else that sends responses)
app.use(unblocker(unblockerConfig));
req.on('end', ()=>{
req.str_body = req.raw_body.toString('utf8');
// serve up static files *after* the proxy is run
app.use('/', express.static(__dirname + '/public'));
try{
var result = new Object();
// this is for users who's form actually submitted due to JS being disabled or whatever
app.get("/b", function(req, res) {
// grab the "url" parameter from the querystring
var site = querystring.parse(url.parse(req.url).query).url;
// and redirect the user to /proxy/url
res.redirect(unblockerConfig.prefix + site);
req.str_body.split('&').forEach((pair)=>{
pair = pair.split('=');
req.body[pair[0]] = decodeURIComponent(pair[1] || '');
});
}catch(err){
req.body = {}
}
return next();
});
});
// for compatibility with gatlin and other servers, export the app rather than passing it directly to http.createServer
module.exports = app;
function base64Encode(data) {
return new Buffer.from(data).toString('base64')
}
// How to use: base64Decode('string') will return any input base64 decoded
function base64Decode(data) {
return new Buffer.from(data, 'base64').toString('ascii')
}
// How to use: rewritingURL('https://example.org/assets/main.js') will rewrite any external URL. Output: aHR0cHM6Ly9leGFtcGxlLm9yZw==/assets/main.js
function rewriteURL(dataURL, option) {
var websiteURL
var websitePath
if (option == 'decode') {
websiteURL = base64Decode(dataURL.split('/').splice(0, 1).join('/'))
websitePath = '/' + dataURL.split('/').splice(1).join('/')
} else {
websiteURL = base64Encode(dataURL.split('/').splice(0, 3).join('/'))
websitePath = '/' + dataURL.split('/').splice(3).join('/')
}
if (websitePath == '/') {
return `${websiteURL}`
} else return `${websiteURL}${websitePath}`
}
// To be used with res.send() to send error. Example: res.send(error('404', 'No valid directory or file was found!'))
function error(statusCode, info) {
if (statusCode && info) {
return fs.readFileSync('alloy/assets/error.html', 'utf8').toString().replace('%ERROR%', `Error ${statusCode}: ${info}`)
}
if (info && !statusCode) {
return fs.readFileSync('alloy/assets/error.html', 'utf8').toString().replace('%ERROR%', `Error: ${info}`)
}
if (statusCode && !info) {
return fs.readFileSync('alloy/assets/error.html', 'utf8').toString().replace('%ERROR%', `Error ${statusCode}`)
}
return fs.readFileSync('public/assets/error.html', 'utf8').toString().replace('%ERROR%', `An error has occurred!`)
}
app.post('/createSession', async (req, res) => {
if (req.body.url.startsWith('//')) {
req.body.url = 'http:' + req.body.url;
} else if (req.body.url.startsWith('https://') || req.body.url.startsWith('http://')) {
req.body.url = req.body.url;
} else {
req.body.url = 'http://' + req.body.url;
}
if (req.body.rv) {
req.session.rvURL = String(req.body.url).split('/').splice(0, 3).join('/')
return res.redirect('/fetch/rv/' + String(req.body.url).split('/').splice(3).join('/'))
} else {
return res.redirect('/fetch/' + rewriteURL(String(req.body.url)))
}
})
var prefix = '/fetch';
app.use(prefix, async (req, res, next) => {
var location = rewriteURL(req.url.slice(1), 'decode');
if (req.url.startsWith('/rv') && !req.session.rvURL) {
res.send(error('400', 'No valid session URL for reverse proxy mode was found!'))
}
if (req.url.startsWith('/rv') && req.session.rvURL) {
location = req.session.rvURL + req.url.slice(3)
}
location = {
href: location,
hostname : location.split('/').splice(2).splice(0, 1).join('/'),
origin : location.split('/').splice(0, 3).join('/'),
origin_encoded : base64Encode(location.split('/').splice(0, 3).join('/')),
path : '/' + location.split('/').splice(3).join('/'),
protocol : location.split('\:').splice(0, 1).join(''),
}
var httpAgent = new http.Agent({
keepAlive: true
});
var httpsAgent = new https.Agent({
keepAlive: true
});
var fetchHeaders = req.headers
fetchHeaders['referer'] = location.href
fetchHeaders['origin'] = location.origin
fetchHeaders['host'] = location.hostname
if (fetchHeaders['cookie']) {
delete fetchHeaders['cookie']
}
var options = {
method: req.method,
headers: fetchHeaders,
redirect: 'manual',
agent: function(_parsedURL) {
if (_parsedURL.protocol == 'http:') {
return httpAgent;
} else {
return httpsAgent;
}
}
};
if (req.method == 'POST') {
// Have to do try catch for this POST data parser until we create our own one that won't have a syntax error sometimes.
try {
// str_body is a string containing the requests body
options['body'] = req.str_body;
}catch(err){
return;
}
}
if (req.url.startsWith('/rv')) {
location.origin_encoded = 'rv'
}
if (!req.url.startsWith(`/${location.origin_encoded}/`)) {
try{
return res.redirect(307,`/fetch/${location.origin_encoded}/`)
}catch(err){
return;
}
}
if (location.href == 'https://discord.com' || location.href == 'https://discord.com/new') {
return res.redirect(307, `/fetch/${location.origin_encoded}/login`)
}
if (location.origin == 'https://www.reddit.com') {
if (req.url.startsWith('/rv') && req.session.rvURL) {
req.session.rvURL = 'https://old.reddit.com'
return res.redirect(307, '/fetch/rv' + location.path)
}
return res.redirect(307, '/fetch/' + base64Encode('https://old.reddit.com') + location.path)
}
const response = await fetch(location.href, options).catch(err => res.send(error('404', `"${location.href}" was not found!`)));
if(typeof response.buffer != 'function')return;
var resbody = await response.buffer();
var contentType = 'text/plain'
response.headers.forEach((e, i, a) => {
if (i == 'content-type') contentType = e;
});
if (contentType == null || typeof contentType == 'undefined') ct = 'text/html';
var serverHeaders = Object.fromEntries(
Object.entries(JSON.parse(JSON.stringify(response.headers.raw())))
.map(([key, val]) => [key, val[0]])
);
if (serverHeaders['location']) {
if (req.url.startsWith('/rv') && req.session.rvURL) {
req.session.rvURL = String(serverHeaders['location']).split('/').splice(0, 3).join('/')
return res.redirect(307, '/fetch/rv/' + String(serverHeaders['location']).split('/').splice(3).join('/'))
} else return res.redirect(307, '/fetch/' + rewriteURL(String(serverHeaders['location'])))
}
delete serverHeaders['content-encoding']
delete serverHeaders['x-frame-options']
delete serverHeaders['strict-transport-security']
delete serverHeaders['content-security-policy']
delete serverHeaders['location']
res.status(response.status)
res.set(serverHeaders)
res.contentType(contentType)
if (response.redirected == true) {
if (req.url.startsWith('/rv') && req.session.rvURL) {
req.session.rvURL = response.url.split('/').splice(0, 3).join('/')
return res.redirect(307, '/fetch/rv/' + response.url.split('/').splice(3).join('/'))
} else return res.redirect(307, '/fetch/' + rewriteURL(response.url))
}
if (contentType.startsWith('text/html')) {
req.session.fetchURL = location.origin_encoded
resbody = resbody.toString()
.replace(/integrity="(.*?)"/gi, '')
.replace(/nonce="(.*?)"/gi, '')
.replace(/(href|src|poster|data|action)="\/\/(.*?)"/gi, `$1` + `="http://` + `$2` + `"`)
.replace(/(href|src|poster|data|action)='\/\/(.*?)'/gi, `$1` + `='http://` + `$2` + `'`)
.replace(/(href|src|poster|data|action)="\/(.*?)"/gi, `$1` + `="/fetch/${location.origin_encoded}/` + `$2` + `"`)
.replace(/(href|src|poster|data|action)='\/(.*?)'/gi, `$1` + `='/fetch/${location.origin_encoded}/` + `$2` + `'`)
.replace(/'(https:\/\/|http:\/\/)(.*?)'/gi, function(str) {
str = str.split(`'`).slice(1).slice(0, -1).join(``);
return `'/fetch/${rewriteURL(str)}'`
})
.replace(/"(https:\/\/|http:\/\/)(.*?)"/gi, function(str) {
str = str.split(`"`).slice(1).slice(0, -1).join(``);
return `"/fetch/${rewriteURL(str)}"`
})
.replace(/(window|document).location.href/gi, `"${location.href}"`)
.replace(/(window|document).location.hostname/gi, `"${location.hostname}"`)
.replace(/(window|document).location.pathname/gi, `"${location.path}"`)
.replace(/location.href/gi, `"${location.href}"`)
.replace(/location.hostname/gi, `"${location.hostname}"`)
.replace(/location.pathname/gi, `"${location.path}"`)
.replace(/<html(.*?)>/gi, '<html' + '$1' + '><script id="alloyData" data-alloyURL="' + location.origin_encoded + '"' + ' src="/alloy/assets/inject.js"></script>')
} else if (contentType.startsWith('text/css')) {
resbody = resbody.toString()
.replace(/url\("\/\/(.*?)"\)/gi, `url("http://` + `$1` + `")`)
.replace(/url\('\/\/(.*?)'\)/gi, `url('http://` + `$1` + `')`)
.replace(/url\(\/\/(.*?)\)/gi, `url(http://` + `$1` + `)`)
.replace(/url\("\/(.*?)"\)/gi, `url("/fetch/${location.origin_encoded}/` + `$1` + `")`)
.replace(/url\('\/(.*?)'\)/gi, `url('/fetch/${location.origin_encoded}/` + `$1` + `')`)
.replace(/url\(\/(.*?)\)/gi, `url(/fetch/${location.origin_encoded}/` + `$1` + `)`)
.replace(/"(https:\/\/|http:\/\/)(.*?)"/gi, function(str) {
str = str.split(`"`).slice(1).slice(0, -1).join(``);
return `"/fetch/${rewriteURL(str)}"`
})
.replace(/'(https:\/\/|http:\/\/)(.*?)'/gi, function(str) {
str = str.split(`'`).slice(1).slice(0, -1).join(``);
return `'/fetch/${rewriteURL(str)}'`
})
.replace(/\((https:\/\/|http:\/\/)(.*?)\)/gi, function(str) {
str = str.split(`(`).slice(1).join(``).split(')').slice(0, -1).join('');
return `(/fetch/${rewriteURL(str)})`
})
} else if (contentType.startsWith('text/javascript') || contentType.startsWith('application/javascript')) {
resbody = resbody.toString()
.replace(/xhttp.open\("GET",(.*?)"http(.*?)"(.*?),(.*?)true\);/gi, ' xhttp.open("GET",' + '$1' + '"/alloy/url/http' + '$2' + '"' + '$3' + ',' + '$4' + 'true')
.replace(/xhttp.open\("POST",(.*?)"http(.*?)"(.*?),(.*?)true\);/gi, ' xhttp.open("POST",' + '$1' + '"/alloy/url/http' + '$2' + '"' + '$3' + ',' + '$4' + 'true')
.replace(/xhttp.open\("OPTIONS",(.*?)"http(.*?)"(.*?),(.*?)true\);/gi, ' xhttp.open("OPTIONS",' + '$1' + '"/alloy/url/http' + '$2' + '"' + '$3' + ',' + '$4' + 'true')
.replace(/xhr.open\("GET",(.*?)"http(.*?)"(.*?),(.*?)true\);/gi, ' xhr.open("GET",' + '$1' + '"/alloy/url/http' + '$2' + '"' + '$3' + ',' + '$4' + 'true')
.replace(/xhr.open\("POST",(.*?)"http(.*?)"(.*?),(.*?)true\);/gi, ' xhr.open("POST",' + '$1' + '"/alloy/url/http' + '$2' + '"' + '$3' + ',' + '$4' + 'true')
.replace(/xhr.open\("OPTIONS",(.*?)"http(.*?)"(.*?),(.*?)true\);/gi, ' xhr.open("OPTIONS",' + '$1' + '"/alloy/url/http' + '$2' + '"' + '$3' + ',' + '$4' + 'true')
.replace(/ajax\("http:\/\/(.*?)"\)/gi, 'ajax("/alloy/url/http://' + '$1' + '")')
.replace(/ajax\("https:\/\/(.*?)"\)/gi, 'ajax("/alloy/url/https://' + '$1' + '")')
}
res.send(resbody)
})
app.use('/alloy/url/',function (req, res, next) {
const mainurl = req.url.split('/').slice(1).join('/')
const host = mainurl.split('/').slice(0, 3).join('/')
const buff = new Buffer(host);
const host64 = buff.toString('base64');
const path = mainurl.split('/').slice(3).join('/')
const fullURL = host64 + '/' + path
res.redirect(307, '/fetch/' + fullURL)
})
app.use('/alloy/',function (req, res, next) {
if (req.query.url) {
var clientInput = base64Decode(req.query.url)
var fetchURL;
if (clientInput.startsWith('//')) {
fetchURL = rewriteURL('http:' + clientInput)
} else if (clientInput.startsWith('http://') || clientInput.startsWith('https://')) {
fetchURL = rewriteURL(clientInput)
} else {
fetchURL = rewriteURL('http://' + clientInput)
}
return res.redirect(307, '/fetch/' + fetchURL)
}
res.sendFile(__dirname + '/alloy' + req.url, function (err) {
if (err) {
if (req.session.fetchURL) {
return res.redirect(307, '/fetch/' + req.session.fetchURL + req.url)
} else return res.redirect(307, '/')
}
})
})
app.use(express.static('public'))
app.use(function (req, res ,next) {
if (req.session.fetchURL) {
return res.redirect(307, '/fetch/' + req.session.fetchURL + req.url)
} else return res.send(error('404', 'No valid directory or file was found!'))
})

View file

@ -1,5 +1,7 @@
{
"name": "Holy Unblocker",
"description": "A website that can be used to bypass web filters; both online and firewall.",
"repository": "https://github.com/QuiteAFancyEmerald/HolyUB"
"name": "Alloy Proxy",
"description": "A node.js web proxy featuring URL encoding, and amazing compatablity!",
"repository": "https://github.com/titaniumnetwork-dev/alloyproxy/",
"logo": "https://avatars1.githubusercontent.com/u/47227492?s=200&v=4",
"keywords": ["node", "proxy", "unblocker"]
}

5
config.json Normal file
View file

@ -0,0 +1,5 @@
{
"listenip":"0.0.0.0",
"port":8080,
"ssl":false
}

View file

@ -1,24 +0,0 @@
/**
* New Relic agent configuration.
*
* See lib/config.defaults.js in the agent distribution for a more complete
* description of configuration variables and their potential values.
*/
exports.config = {
/**
* Array of application names.
*/
app_name: ['Node Unblocker'],
/**
* Your New Relic license key.
*/
license_key: process.env.NEW_RELIC_LICENSE_KEY,
logging: {
/**
* Level at which to log. 'trace' is most useful to New Relic when diagnosing
* issues with the agent, 'info' and higher will impose the least overhead on
* production applications.
*/
level: 'info'
}
};

300
package-lock.json generated
View file

@ -1,5 +1,5 @@
{
"name": "nodeunblocker.com",
"name": "alloyproxy",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
@ -18,11 +18,6 @@
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
"async": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz",
"integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw=="
},
"body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
@ -63,6 +58,15 @@
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
},
"cookie-parser": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.5.tgz",
"integrity": "sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw==",
"requires": {
"cookie": "0.4.0",
"cookie-signature": "1.0.6"
}
},
"cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
@ -143,6 +147,33 @@
"vary": "~1.1.2"
}
},
"express-session": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz",
"integrity": "sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==",
"requires": {
"cookie": "0.4.0",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "~2.0.0",
"on-headers": "~1.0.2",
"parseurl": "~1.3.3",
"safe-buffer": "5.2.0",
"uid-safe": "~2.1.5"
},
"dependencies": {
"depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
},
"safe-buffer": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
}
}
},
"finalhandler": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
@ -157,6 +188,11 @@
"unpipe": "~1.0.0"
}
},
"follow-redirects": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz",
"integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA=="
},
"forwarded": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
@ -167,14 +203,6 @@
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
},
"gatling": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gatling/-/gatling-1.2.0.tgz",
"integrity": "sha1-rCDViqwTo82ntjtc0rO247MLEHw=",
"requires": {
"optimist": "~0.6.0"
}
},
"http-errors": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
@ -205,11 +233,6 @@
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
},
"lodash": {
"version": "4.17.20",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
},
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@ -243,11 +266,6 @@
"mime-db": "1.44.0"
}
},
"minimist": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
"integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@ -258,148 +276,10 @@
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
"newrelic": {
"version": "1.40.0",
"resolved": "https://registry.npmjs.org/newrelic/-/newrelic-1.40.0.tgz",
"integrity": "sha1-JUjfFMRB6/ydO465idE397aaHW8=",
"requires": {
"concat-stream": "^1.5.0",
"https-proxy-agent": "^0.3.5",
"json-stringify-safe": "^5.0.0",
"readable-stream": "^1.1.13",
"semver": "^5.3.0"
},
"dependencies": {
"concat-stream": {
"version": "1.6.0",
"bundled": true,
"requires": {
"inherits": "^2.0.3",
"readable-stream": "^2.2.2",
"typedarray": "^0.0.6"
},
"dependencies": {
"inherits": {
"version": "2.0.3",
"bundled": true
},
"readable-stream": {
"version": "2.2.11",
"bundled": true,
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "~1.0.0",
"process-nextick-args": "~1.0.6",
"safe-buffer": "~5.0.1",
"string_decoder": "~1.0.0",
"util-deprecate": "~1.0.1"
},
"dependencies": {
"core-util-is": {
"version": "1.0.2",
"bundled": true
},
"isarray": {
"version": "1.0.0",
"bundled": true
},
"process-nextick-args": {
"version": "1.0.7",
"bundled": true
},
"safe-buffer": {
"version": "5.0.1",
"bundled": true
},
"string_decoder": {
"version": "1.0.2",
"bundled": true,
"requires": {
"safe-buffer": "~5.0.1"
}
},
"util-deprecate": {
"version": "1.0.2",
"bundled": true
}
}
},
"typedarray": {
"version": "0.0.6",
"bundled": true
}
}
},
"https-proxy-agent": {
"version": "0.3.6",
"bundled": true,
"requires": {
"agent-base": "~1.0.1",
"debug": "2",
"extend": "3"
},
"dependencies": {
"agent-base": {
"version": "1.0.2",
"bundled": true
},
"debug": {
"version": "2.6.8",
"bundled": true,
"requires": {
"ms": "2.0.0"
},
"dependencies": {
"ms": {
"version": "2.0.0",
"bundled": true
}
}
},
"extend": {
"version": "3.0.1",
"bundled": true
}
}
},
"json-stringify-safe": {
"version": "5.0.1",
"bundled": true
},
"readable-stream": {
"version": "1.1.14",
"bundled": true,
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
},
"dependencies": {
"core-util-is": {
"version": "1.0.2",
"bundled": true
},
"inherits": {
"version": "2.0.3",
"bundled": true
},
"isarray": {
"version": "0.0.1",
"bundled": true
},
"string_decoder": {
"version": "0.10.31",
"bundled": true
}
}
},
"semver": {
"version": "5.3.0",
"bundled": true
}
}
"node-fetch": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
"integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
},
"on-finished": {
"version": "2.3.0",
@ -409,14 +289,15 @@
"ee-first": "1.1.1"
}
},
"optimist": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
"integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
"requires": {
"minimist": "~0.0.1",
"wordwrap": "~0.0.2"
}
"on-headers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
"integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="
},
"parse-raw-http": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/parse-raw-http/-/parse-raw-http-0.0.1.tgz",
"integrity": "sha512-GndQvIQXviId7eHnc+fEcmtEjkj1tQ96EhNOplPwXA8L1jgOnrlx/xLmmOEew8Yj4ZoZpmoAh0IvypAaeMbILg=="
},
"parseurl": {
"version": "1.3.3",
@ -442,6 +323,11 @@
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
},
"random-bytes": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
"integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs="
},
"range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
@ -506,11 +392,6 @@
"send": "0.17.1"
}
},
"set-cookie-parser": {
"version": "2.4.6",
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.4.6.tgz",
"integrity": "sha512-mNCnTUF0OYPwYzSHbdRdCfNNHqrne+HS5tS5xNb6yJbdP9wInV0q5xPLE0EyfV/Q3tImo3y/OXpD8Jn0Jtnjrg=="
},
"setprototypeof": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
@ -521,16 +402,6 @@
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
},
"through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
},
"tld": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/tld/-/tld-0.0.2.tgz",
"integrity": "sha1-9g442CzaB14NzHlgHOXWgpzASd4="
},
"toidentifier": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
@ -545,48 +416,12 @@
"mime-types": "~2.1.24"
}
},
"unblocker": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/unblocker/-/unblocker-2.0.5.tgz",
"integrity": "sha512-dzt6dcfzC7W8MZ04nxsAKwF4uJBaYPLpZyab0pXdwTDVrJrxwU79PWO2ayxl9cavVAW4a7jJW7TSySDWibVmHA==",
"uid-safe": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
"integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
"requires": {
"async": "^3.1.0",
"content-type": "^1.0.4",
"cookie": "^0.4.0",
"debug": "^4.1.1",
"iconv-lite": "^0.5.0",
"lodash": "^4.17.15",
"mime": "^2.4.4",
"set-cookie-parser": "^2.4.1",
"tld": "0.0.2"
},
"dependencies": {
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"requires": {
"ms": "^2.1.1"
}
},
"iconv-lite": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz",
"integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
},
"mime": {
"version": "2.4.6",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz",
"integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA=="
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}
"random-bytes": "~1.0.0"
}
},
"unpipe": {
@ -603,11 +438,6 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
"wordwrap": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
"integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="
}
}
}

View file

@ -1,22 +1,32 @@
{
"name": "nodeunblocker.com",
"description": "Web proxy for evading internet censorship",
"author": "Nathan Friedly - http://nfriedly.com",
"name": "alloyproxy",
"version": "1.0.0",
"private": true,
"homepage": "https://github.com/nfriedly/nodeunblocker.com/",
"dependencies": {
"express": "^4.13.0",
"gatling": "~1.2.0",
"newrelic": "^1.20.2",
"through": "^2.3.8",
"unblocker": "*"
},
"engines": {
"node": ">=6"
},
"description": "A powerful web proxy!",
"main": "app.js",
"scripts": {
"start": "node ./node_modules/gatling/gatling.js ./app.js"
"test": "proxy",
"start": "node app.js"
},
"license": "AGPL-3.0"
"repository": {
"type": "git",
"url": "git+https://github.com/titaniumnetwork-dev/alloyproxy.git"
},
"keywords": [
"web-proxy"
],
"author": "titaniumnetwork-dev",
"license": "ISC",
"bugs": {
"url": "https://github.com/titaniumnetwork-dev/alloyproxy/issues"
},
"homepage": "https://github.com/titaniumnetwork-dev/alloyproxy#readme",
"dependencies": {
"body-parser": "^1.19.0",
"cookie-parser": "^1.4.5",
"express": "^4.17.1",
"express-session": "^1.17.1",
"follow-redirects": "^1.13.0",
"node-fetch": "^2.6.0",
"parse-raw-http": "0.0.1"
}
}

View file

@ -65,7 +65,7 @@
var url = $('url').value;
var det = document.domain;
var domain = det.replace('www.', '').split(/[/?#]/)[0];
window.location.href = "https://a." + domain + "/alloy?url=" + url;
window.location.href = "https://" + domain + "/alloy?url=" + url;
return false;
};
window.onload = function() {

22
ssl/default.crt Normal file
View file

@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDqzCCApOgAwIBAgIJAJnCkScWtmL0MA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMRgwFgYDVQQKDA9UaXRhbml1bU5l
dHdvcmsxDjAMBgNVBAsMBWdhbWVyMR4wHAYDVQQDDBUqLnRpdGFuaXVtbmV0d29y
ay5vcmcwHhcNMjAwNjEzMTg0OTU2WhcNMjEwNjEzMTg0OTU2WjBsMQswCQYDVQQG
EwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEYMBYGA1UECgwPVGl0YW5pdW1OZXR3
b3JrMQ4wDAYDVQQLDAVnYW1lcjEeMBwGA1UEAwwVKi50aXRhbml1bW5ldHdvcmsu
b3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwPL69+RE6r8RrFh4
njzC8ZRnLB+yNtuGw14C0dvNb5JwgdLl5g9/wK/s0V5NGlqwxlQlxQ/gUSuYEcUR
6MYjcnaUmZZe/gaKVV0fkfkuigOWhLnI5AQxx7rhkzx1ujuyJ9D2pkDtZpSvv0yn
2yrvWhJMtjuxGYip8jaLuRpbXoafvR7nrlDaNcE/GwIjnCCxsRnY2bGbxYK840mN
fuMfF2nz+fXKPuQ/9PT48e3wOo9vM5s7yKhiHYwrogqzGN4cH4sSr1FE8C7flFyT
Yw101u7fUaopfeGCo9Pg6IrfzyzE5Qb7OlqlVk2IkvXx7pPqVc6lZCJEhOX/qF9o
n3mFqwIDAQABo1AwTjAdBgNVHQ4EFgQUC561ob2kGtFQ4az6y64b98+Fy+IwHwYD
VR0jBBgwFoAUC561ob2kGtFQ4az6y64b98+Fy+IwDAYDVR0TBAUwAwEB/zANBgkq
hkiG9w0BAQsFAAOCAQEAotvUsSLSzFyxQz329tEPyH6Tmi19FQoA5ZbLg6EqeTI9
08qOByDGkSYJi0npaIlPO1I557NxRzdO0PxK3ybol6lnzuSlqCJP5nb1dr0z2Eax
wgKht9P+ap/yozU5ye05ah2nkpcaeDPnwnnWFmfsnYNfgu62EshOS+5FETWEKVUb
LXQhGInOdJq8KZvhoLZWJoUhyAqxBfW4oVvaqs+Ff96A2NNKrvbiAVYX30rVa+x0
KIl0/DoVvDx2Q6TiL396cAXdKUW7edRQcSsGFcxwIrU5lePm0V05aN+oCoEBvXBG
ArPN+a5kpGjJwfcpcBVf9cJ6IsvptGS9de3eTHoTyw==
-----END CERTIFICATE-----

28
ssl/default.key Normal file
View file

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDA8vr35ETqvxGs
WHiePMLxlGcsH7I224bDXgLR281vknCB0uXmD3/Ar+zRXk0aWrDGVCXFD+BRK5gR
xRHoxiNydpSZll7+BopVXR+R+S6KA5aEucjkBDHHuuGTPHW6O7In0PamQO1mlK+/
TKfbKu9aEky2O7EZiKnyNou5Gltehp+9HueuUNo1wT8bAiOcILGxGdjZsZvFgrzj
SY1+4x8XafP59co+5D/09Pjx7fA6j28zmzvIqGIdjCuiCrMY3hwfixKvUUTwLt+U
XJNjDXTW7t9Rqil94YKj0+Doit/PLMTlBvs6WqVWTYiS9fHuk+pVzqVkIkSE5f+o
X2ifeYWrAgMBAAECggEAbihK8Ev6rKr5RBQeiPjXs2SuoppV/MvIXLHHmliLKS/J
29S0PGyM202VPtM/4dP1KMXR6nft8WmaIEsKtoKoqijZHfajtRO21pWb+JLy5wi1
XoFTGBrs8MLZFl5mODTsuZ6rsq9O2kn5LJZvHsmcbSgVc9UQfytvG0HY840ArS3g
kSDtUFb1xRui6wtCBKzHVvCT+FXhSBbwkHalmbqP6BefhJ3lW2VonkOcHDrdXPfW
CEN18IJ2v8QYgXqZP6VUlAweNXLJ33ZOl+jXGdygcOG24MFqdw0VtP0XFGk0jnSS
W6dX67BZKeZ71EKaTy02jw5LpQNXA70ismPJHQ2uQQKBgQDuROawnBIW1fC3xOle
m+JmP0eMe0eIQycxRsMXsXhYAA0wV3qYZSLZrNK2eRhmSNt+ODSmZ2Vt11dwOv5u
bo8WONrRlM097SmitS2S+8o7ASem2VKQzyRE72Y9517Q+aNBdLRVtjrRNSw/hfSu
ayLuG36+yukSH7wq7mfoUX34ZwKBgQDPTrgyyw8n5XhZT/qTTRnQJ2GTvPxDzNoJ
IAGhGJGFAb6wgLoSpGx6BC122vuRxcTjkjAiMDci5N2zNW+YZVni+F0KTVvNFfU2
pOTJUg3luRTygCra6O02PxwpbP/9KCBAKq/kYw/eBW+gxhPwP3ZrbAirvBjgBh0I
kIrFijNOHQKBgGUUAbFGZD4fwCCVflLOWnr5uUaVPcFGi6fR1w2EEgNy8iVh1vYz
YVdqg3E5aepqWgLvoRY+or64LbXEsQ70A+tvbxSdxXvR0mnd5lmGS0JAuSuE4gvg
dAhybrMwJf8NB/7KnX4G8mix3/WKxEQB2y2bqGcT+U/g+phTzuy1NXVdAoGBAIrl
jVjK4J60iswcYCEteWwT1rbr2oF60WNnxG+xTF63apJLzWAMNnoSLnwCAKgMv/xR
yFo/v9FrUnduCBUtYupFyeDLMATa/27bUEbq6VDPjw9jfFMr2TONWUsQMvvlVKZp
c2wsS0dQkRhBXr6LZsZWngCiiHAg6HcCkVgFXpapAoGBAJ/8oLGt0Ar+0MTl+gyk
xSqgHnsc5jgqhix3nIoI5oEAbfibdGmRD1S3rtWD9YsnPxMIl+6E5bOAHrmd+Zr8
O7EP+CLvbz4JXidaaa85h9ThXSG5xk1A1UTtSFrp+KolLE1Vvmjjd+R844XsM2wZ
OAHbihzk0iPPphjEWR4lU4Av
-----END PRIVATE KEY-----

17
ssl/localhost.crt Normal file
View file

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICwzCCAaugAwIBAgIJAMN1fA0fbQDSMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV
BAMTCWxvY2FsaG9zdDAeFw0yMDA2MDcyMDIyMDRaFw0zMDA2MDUyMDIyMDRaMBQx
EjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAPVHYq820Hi8Vy4ZAgmH/0Cl51TxWIWeoEgyQZEErgm1Vv49KuM0I1Ejk23+
+tbKxY489dc7Gj/PqPv5F7SASNcxcKi5zbJPC6eEJBh2lHh6ldzF1aMfaYnuh25a
3uhzoLpZPRsoTBysXkQZqC/6ZP6kBcwJnMZd12Uj4JIbdJwpyUorOYOv4GO6f7SA
dUPUhSJpfUMZ4EFnkgrGJ18iqml/afhKj0g6KDxDGc1l2ioVMxiSjEfP06mbfkZ4
zG16CmfITgyBFv8J9eF7exHCzqhbzgqWSfUNKazEKMbfCoegeZI196xtGIUbPYcf
U8a5M+/pSmojMvdqsppqro0qwa0CAwEAAaMYMBYwFAYDVR0RBA0wC4IJbG9jYWxo
b3N0MA0GCSqGSIb3DQEBBQUAA4IBAQBazEct+iiNe7/TY7c+l8wQBaCIhLtWxmfA
JLGBu5Jt+HPAMskU5+rK0nWPMIW5le+xhHXXRnmjqH1pm157hR1LvanLoHpWsPTc
eNx7utePC49t77UID1L2NHnmm9SAG/OhPJr3hh0AWG4GjJlWpK+9xeq7b9BoUsl7
umU/X/02ZJmXWSwrqhspxtz3dSNaozAVVZs4Bokf7WiU27ACgffa7pCh9E8WTgyV
jkvG5ZbmOeje7n+Fa0PEbTrm8SBtF/Rn96VkoZGJBC4+wia/0T5Gmjk8Ds9VhjVK
bCyEsgPbkjwRdT/eRO4gEOgJI36CrheluWLnqjiidregyKYHQhwA
-----END CERTIFICATE-----

27
ssl/localhost.key Normal file
View file

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA9UdirzbQeLxXLhkCCYf/QKXnVPFYhZ6gSDJBkQSuCbVW/j0q
4zQjUSOTbf761srFjjz11zsaP8+o+/kXtIBI1zFwqLnNsk8Lp4QkGHaUeHqV3MXV
ox9pie6Hblre6HOgulk9GyhMHKxeRBmoL/pk/qQFzAmcxl3XZSPgkht0nCnJSis5
g6/gY7p/tIB1Q9SFIml9QxngQWeSCsYnXyKqaX9p+EqPSDooPEMZzWXaKhUzGJKM
R8/TqZt+RnjMbXoKZ8hODIEW/wn14Xt7EcLOqFvOCpZJ9Q0prMQoxt8Kh6B5kjX3
rG0YhRs9hx9Txrkz7+lKaiMy92qymmqujSrBrQIDAQABAoIBAQCQ6tFqlmdLvnN/
3/StLvXn+12XeVUE9Xjbzx2gEfTF9adlZTxuqwJm0S8tISaRO5LHfEsAFIJoy0eb
QEv6MIVY53QZrFXVERDgs5kj/wOvvzXGD/kufMO9Y/oOgJANJSwEje8lmYSGuGyl
rccKOdXsAXsPV2qSZSV7M1xe1uvpyzpoUaX5aEfl44Kz1U6pURCpjqCj3OwVoaXa
vlnDSI7LArhvVTR2Xifl9/MSz1qGlnlKTJTUJi5z+XEnIEqZmhYQOUnp2Wi4KWOR
SqKnLOgfSJKb3yrdHukpLBsakF7U1urLB2wUjweZdn7zI9qbzIt9GIy1mRjYXTXL
YwPDFOfBAoGBAP5Pi3+E8HV2L+6XOl9MYtKxn2KRvHQdR13IepmF+umhOxjfc6uC
NhVeutfwuYfTXWmiEOHPKhH6NLloPbKkpfl6YxaKsAPfeEUI8PEA9J9TiNvGIP6m
MZVsp5VS4Q/O2UTT9SG5dc3zOMmys1CJMIDZkzvub9HY1EiAiqRY/y+RAoGBAPbo
e1yl/O2Z4L/ILaqo0QpIOgOdpWGZUIshUp5LEUzcYcflnCzdh1CYXWOAnPlvhh3H
k4rTBMWJ4DaFWdNhYcOLowu0pk1Cm9q0akarmCr0DhKj98qubU/0QdzJ9q80eqYA
3/pfFNs+baIGqcqOeD+da4ZrbLoefO7eBE1qJdpdAoGAFJjkt4NQ5nKYFz7wX1+U
cXQpcJZVKSJl8VaXd2++jsWcP7t5Zt64+qodf/fjTvjzi+awb1mUEritJIco2Bs1
xir/c4fwEaA74XuD6EEnju/5GbPGYFmdknimahW4XMtoFYcFR6H5xKB6bPuoQlGa
OBVnM2dwbxKcvvKKSB1dLcECgYEAhQ4xdHMKwyv6Xr9MRLxmsijMAqjQt7C8I83Y
TO9dKlNU6jlFGTRkOD1zjix/6zd7Sc8EJnqjBqTPS/I+vteqrIsyWRuHxvjPLmOt
JdpQzUzpzIfJ/9JRnBWf7JB1vGMGeTDdgnn8rk2NHRSEKWDvUjDOAgkf9Yh6gOrp
3KIINg0CgYEA5VURroq8FtoLUeiyueKwJ8pBeWVa1IOy9OyG7MaebYVcs5XqDyMk
t/5dRHEbzjeM94qsi15BnwYtAy53RlIpA6VCsTxjgP53oj6emucoyj0eW4BRtTq1
Er5OUU3Sl6JrILXmefjGTKha97boBWpUZQrJ/zgiqR4KvyGIBq4lqLo=
-----END RSA PRIVATE KEY-----