first commit
This commit is contained in:
commit
c51c98aacd
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
node_modules
|
221
404.txt
Normal file
221
404.txt
Normal file
@ -0,0 +1,221 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>My-MC.LINK - Peer Not Found! </title>
|
||||
<link rel="canonical" href="https://codepen.io/ricardpriet/pen/zPqyvY">
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css?family=Montserrat:400,600,700');
|
||||
@import url('https://fonts.googleapis.com/css?family=Catamaran:400,800');
|
||||
.error-container {
|
||||
text-align: center;
|
||||
font-size: 180px;
|
||||
font-family: 'Catamaran', sans-serif;
|
||||
font-weight: 800;
|
||||
margin: 20px 15px;
|
||||
}
|
||||
.error-container > span {
|
||||
display: inline-block;
|
||||
line-height: 0.7;
|
||||
position: relative;
|
||||
color: #FFB485;
|
||||
}
|
||||
.error-container > span {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.error-container > span:nth-of-type(1) {
|
||||
color: #D1F2A5;
|
||||
animation: colordancing 4s infinite;
|
||||
}
|
||||
.error-container > span:nth-of-type(3) {
|
||||
color: #F56991;
|
||||
animation: colordancing2 4s infinite;
|
||||
}
|
||||
.error-container > span:nth-of-type(2) {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border-radius: 999px;
|
||||
}
|
||||
.error-container > span:nth-of-type(2):before,
|
||||
.error-container > span:nth-of-type(2):after {
|
||||
border-radius: 0%;
|
||||
content:"";
|
||||
position: absolute;
|
||||
top: 0; left: 0;
|
||||
width: inherit; height: inherit;
|
||||
border-radius: 999px;
|
||||
box-shadow: inset 30px 0 0 rgba(209, 242, 165, 0.4),
|
||||
inset 0 30px 0 rgba(239, 250, 180, 0.4),
|
||||
inset -30px 0 0 rgba(255, 196, 140, 0.4),
|
||||
inset 0 -30px 0 rgba(245, 105, 145, 0.4);
|
||||
animation: shadowsdancing 4s infinite;
|
||||
}
|
||||
.error-container > span:nth-of-type(2):before {
|
||||
-webkit-transform: rotate(45deg);
|
||||
-moz-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.screen-reader-text {
|
||||
position: absolute;
|
||||
top: -9999em;
|
||||
left: -9999em;
|
||||
}
|
||||
@keyframes shadowsdancing {
|
||||
0% {
|
||||
box-shadow: inset 30px 0 0 rgba(209, 242, 165, 0.4),
|
||||
inset 0 30px 0 rgba(239, 250, 180, 0.4),
|
||||
inset -30px 0 0 rgba(255, 196, 140, 0.4),
|
||||
inset 0 -30px 0 rgba(245, 105, 145, 0.4);
|
||||
}
|
||||
25% {
|
||||
box-shadow: inset 30px 0 0 rgba(245, 105, 145, 0.4),
|
||||
inset 0 30px 0 rgba(209, 242, 165, 0.4),
|
||||
inset -30px 0 0 rgba(239, 250, 180, 0.4),
|
||||
inset 0 -30px 0 rgba(255, 196, 140, 0.4);
|
||||
}
|
||||
50% {
|
||||
box-shadow: inset 30px 0 0 rgba(255, 196, 140, 0.4),
|
||||
inset 0 30px 0 rgba(245, 105, 145, 0.4),
|
||||
inset -30px 0 0 rgba(209, 242, 165, 0.4),
|
||||
inset 0 -30px 0 rgba(239, 250, 180, 0.4);
|
||||
}
|
||||
75% {
|
||||
box-shadow: inset 30px 0 0 rgba(239, 250, 180, 0.4),
|
||||
inset 0 30px 0 rgba(255, 196, 140, 0.4),
|
||||
inset -30px 0 0 rgba(245, 105, 145, 0.4),
|
||||
inset 0 -30px 0 rgba(209, 242, 165, 0.4);
|
||||
}
|
||||
100% {
|
||||
box-shadow: inset 30px 0 0 rgba(209, 242, 165, 0.4),
|
||||
inset 0 30px 0 rgba(239, 250, 180, 0.4),
|
||||
inset -30px 0 0 rgba(255, 196, 140, 0.4),
|
||||
inset 0 -30px 0 rgba(245, 105, 145, 0.4);
|
||||
}
|
||||
}
|
||||
@keyframes colordancing {
|
||||
0% {
|
||||
color: #D1F2A5;
|
||||
}
|
||||
25% {
|
||||
color: #F56991;
|
||||
}
|
||||
50% {
|
||||
color: #FFC48C;
|
||||
}
|
||||
75% {
|
||||
color: #EFFAB4;
|
||||
}
|
||||
100% {
|
||||
color: #D1F2A5;
|
||||
}
|
||||
}
|
||||
@keyframes colordancing2 {
|
||||
0% {
|
||||
color: #FFC48C;
|
||||
}
|
||||
25% {
|
||||
color: #EFFAB4;
|
||||
}
|
||||
50% {
|
||||
color: #D1F2A5;
|
||||
}
|
||||
75% {
|
||||
color: #F56991;
|
||||
}
|
||||
100% {
|
||||
color: #FFC48C;
|
||||
}
|
||||
}
|
||||
|
||||
/* demo stuff */
|
||||
* {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
background-color: #416475;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
html, button, input, select, textarea {
|
||||
font-family: 'Montserrat', Helvetica, sans-serif;
|
||||
color: #92a4ad;
|
||||
}
|
||||
h1 {
|
||||
text-align: center;
|
||||
margin: 30px 15px;
|
||||
}
|
||||
.zoom-area {
|
||||
max-width: 550px;
|
||||
margin: 30px auto 30px;
|
||||
font-size: 19px;
|
||||
text-align: center;
|
||||
}
|
||||
.link-container {
|
||||
text-align: center;
|
||||
}
|
||||
a.more-link {
|
||||
text-transform: uppercase;
|
||||
font-size: 13px;
|
||||
background-color: #92a4ad;
|
||||
padding: 10px 15px;
|
||||
border-radius: 0;
|
||||
color: #416475;
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
margin-bottom: 5px;
|
||||
line-height: 1.5;
|
||||
text-decoration: none;
|
||||
margin-top: 50px;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.console = window.console || function(t) {};
|
||||
</script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const errorMessages = [
|
||||
"Whoopsie daisy! Our code took a coffee break.",
|
||||
"Houston, we have a problem...with our code.",
|
||||
"Error 404: Sense of Direction Not Found.",
|
||||
"Looks like our code is doing the electric slide...backward.",
|
||||
"Oops! Did someone trip over the server cable again?",
|
||||
"404 Error: Wit Not Found. Please try again later.",
|
||||
"This wasn't in the developer manual!",
|
||||
"Well, that's a funny way to say 'Hello, World!'",
|
||||
"Looks like our code decided to go on a spontaneous vacation.",
|
||||
"Hold on tight, we're experiencing technical turbulence.",
|
||||
"Error 101: Gremlins in the System.",
|
||||
"If at first you don't succeed, call IT support.",
|
||||
"Congratulations! You've found the hidden feature...of bugs.",
|
||||
"Looks like our code got lost in translation.",
|
||||
"Abandon hope, all ye who debug here.",
|
||||
"Error 418: I'm a teapot. But seriously, something's wrong.",
|
||||
"Well, this is awkward...even for code.",
|
||||
"Have you tried turning it off and on again? No, seriously.",
|
||||
"Error 505: Brain.exe has stopped responding.",
|
||||
"Looks like our code took a wrong turn at Albuquerque."];
|
||||
let currentMessageIndex = 0;
|
||||
const errorMessageElement = document.getElementById('error-message');
|
||||
setInterval(() => {
|
||||
currentMessageIndex = (currentMessageIndex + 1) % errorMessages.length;
|
||||
errorMessageElement.textContent = errorMessages[currentMessageIndex];
|
||||
}, 3000); // Change message every 5 seconds
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body translate="no">
|
||||
<h1 id="error-message">Look's like we did not get that quite right... </h1>
|
||||
<p class="zoom-area"><b>Routing Error: Invalid hash or connection timeout.</b><BR>Please reset your link and try again. </p>
|
||||
<section class="error-container">
|
||||
<span>4</span>
|
||||
<span><span class="screen-reader-text">0</span></span>
|
||||
<span>4</span>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
132
README.md
Normal file
132
README.md
Normal file
@ -0,0 +1,132 @@
|
||||
|
||||
# hyperMC-Web-Relay
|
||||
|
||||
This relays Hyper Relay connection hashes over wildcard DNS and wildcard virtualhost reverse proxy to allow for automatic URLs via connection topics.
|
||||
|
||||
Set up instructions:
|
||||
|
||||
This will require a server listening to a connection topic using our version of hyper-relay:
|
||||
|
||||
|
||||
https://git.ssh.surf/hypermc/hyper-relay
|
||||
|
||||
`git clone git@git.ssh.surf:hypermc/hyper-relay.git`
|
||||
|
||||
`cd hyper-relay`
|
||||
|
||||
`npm i`
|
||||
|
||||
Now listen to a TCP port over the Hyper Network:
|
||||
```
|
||||
root@server:/hyper-relay# node server.js 80 hellothere
|
||||
w7zpwusw6ljrgbffxtklak23rkhaxwhs2kskozteme6ofefevlia
|
||||
```
|
||||
|
||||
The result above shows the connection hash for your hyper port.
|
||||
|
||||
This will be the hash used as your subdomain later in this process.
|
||||
|
||||
NOTE: The "hellothere" above is the connection "topic" this is used to generate the hash and it can be any string or key phrase you wish.
|
||||
|
||||
|
||||
# The Reverse proxy
|
||||
|
||||
We will proxy all of the traffic to their specific peers using a reverse proxy method, in this example, we will utilize httpd/apache below you will find the standard configuration that will work for our purposes.
|
||||
|
||||
```
|
||||
<VirtualHost *:443>
|
||||
SSLProxyEngine On
|
||||
ServerAlias *.your-tld.here
|
||||
ServerAdmin webmaster@your-tld.here
|
||||
DocumentRoot /var/www/html
|
||||
|
||||
ErrorLog /var/log/error.log
|
||||
CustomLog /var/log/access.log combined
|
||||
|
||||
SSLCertificateFile /path/to/fullchain.pem
|
||||
SSLCertificateKeyFile /path/to/privkey.pem
|
||||
|
||||
# Reverse Proxy for subdomains
|
||||
<Proxy *>
|
||||
Require all granted
|
||||
</Proxy>
|
||||
|
||||
ProxyPreserveHost On
|
||||
RequestHeader set X-Forwarded-Proto https
|
||||
ProxyPass "/" "http://localhost:8081/"
|
||||
ProxyPassReverse "/" "http://localhost:8081/"
|
||||
</VirtualHost>
|
||||
|
||||
```
|
||||
|
||||
NOTE 1: This requires `mod_proxy` and `mod_ssl` to work properly.
|
||||
|
||||
NOTE 2: This requires the full use of the wildcard *.your-told.here you will not be able to use any subdomain within this scope unless it runs via a hyper-relay.
|
||||
|
||||
We highly reccomend using SSL only for this reverse connection, however, you may configure your proxy pass as desired.
|
||||
|
||||
# Wildcard DNS Entry
|
||||
|
||||
In order to serve your subdomain hashes without the need to generate an A record create a wildcard subdomain record.
|
||||
|
||||
Example:
|
||||
`*.example.com. IN A 192.0.2.1`
|
||||
|
||||
This system does work well with cloudflare proxy, feel free to proxy your traffic!
|
||||
|
||||
# Running the Web Relay ServerAdmin
|
||||
|
||||
`git clone git@git.ssh.surf:hypermc/hyperMC-Web-Relay.git`
|
||||
|
||||
`cd hyperMC-Web-Relay`
|
||||
|
||||
`npm i`
|
||||
|
||||
There are two servers provided within this repo.
|
||||
|
||||
One will work without the use of workers, and it can work well for static content sites.
|
||||
|
||||
To deploy this server, run `node non-worker-server.js`
|
||||
|
||||
The relay will begin listening on port 8081, this port may be changed in the script.
|
||||
```
|
||||
[root@server hyperMC-Web-Relay]# node fullyworking_proxy.js
|
||||
Creating HyperDHT server...
|
||||
HyperDHT server created and ready.
|
||||
HTTP server listening on port 8081
|
||||
```
|
||||
|
||||
To deploy a multi worker server, run `node worker-server.js`
|
||||
|
||||
The server will start workers based off your CPU count and then start those workers listening for connections:
|
||||
|
||||
```
|
||||
[root@server hyper-web-relay]# node worker-server.js
|
||||
Master 703855 is running
|
||||
Total Workers 4
|
||||
Worker 703885 started
|
||||
Worker 703878 started
|
||||
Worker 703904 started
|
||||
Worker 703929 started
|
||||
Worker 703878 listening on port 8081
|
||||
Worker 703965 listening on port 8081
|
||||
Worker 704044 listening on port 8081
|
||||
Worker 703885 listening on port 8081
|
||||
```
|
||||
|
||||
You now can make a request from a hyper-relay connection hash:
|
||||
|
||||
```
|
||||
~ ❯ curl -IL https://w7zpwusw6ljrgbffxtklak23rkhaxwhs2kskozteme6ofefevlia.your-tld.here/
|
||||
HTTP/2 200
|
||||
date: Fri, 29 Mar 2024 06:39:38 GMT
|
||||
content-type: text/html; charset=UTF-8
|
||||
last-modified: Tue, 19 Mar 2024 05:07:41 GMT
|
||||
vary: Accept-Encoding
|
||||
cf-cache-status: DYNAMIC
|
||||
report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=mGhuDrFp%2B2lMm9iQ45CshdOmN7Sbf%2Fs1dgWKD3PtcISbcBi6uB4YZIG2qTTmfRpL1C1f3vqF01IFERjjpDspEuQ98dRfgQpelyODFjd99aeUY5uGQcPxQoAusjb%2BBxwRWkI6ZQE0EPKy4m%2BeGbY0%2FGLVndHc%2F52vEvvAIIhzR%2FqMIweFqgyAwGAaELc7sUIDayE%3D"}],"group":"cf-nel","max_age":604800}
|
||||
nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
|
||||
server: cloudflare
|
||||
cf-ray: 86bddd2349cf8bbb-ATL
|
||||
alt-svc: h3=":443"; ma=86400
|
||||
```
|
141
non-worker-server.js
Normal file
141
non-worker-server.js
Normal file
@ -0,0 +1,141 @@
|
||||
const fs = require('fs');
|
||||
const http = require('http');
|
||||
const httpProxy = require('http-proxy');
|
||||
const HyperDHTServer = require('hyperdht');
|
||||
const libNet = require('hyper-cmd-lib-net');
|
||||
const goodbye = require('graceful-goodbye');
|
||||
const libKeys = require('hyper-cmd-lib-keys');
|
||||
const b32 = require("hi-base32");
|
||||
const net = require("net");
|
||||
const pump = require("pump");
|
||||
let invalid = false;
|
||||
|
||||
let mod = 0;
|
||||
const tunnels = {};
|
||||
const agent = new http.Agent({ maxSockets: Number.MAX_VALUE });
|
||||
const content = fs.readFileSync('404.txt', 'utf8');
|
||||
const DEBUG = 0; // Set DEBUG to 1 to enable debug mode
|
||||
// Enabling DEBUG mode will slow down the code, please only enable this if you need
|
||||
// Information about connections coming in because you need to validate connection hashes.
|
||||
|
||||
const startServer = async () => {
|
||||
console.log("Creating HyperDHT server...");
|
||||
const dhtServer = new HyperDHTServer();
|
||||
await dhtServer.ready();
|
||||
console.log("HyperDHT server created and ready.");
|
||||
|
||||
const proxy = httpProxy.createProxyServer({
|
||||
ws: true,
|
||||
agent: agent,
|
||||
timeout: 360000
|
||||
});
|
||||
|
||||
const server = http.createServer(async function (req, res) {
|
||||
try {
|
||||
console.log("Incoming HTTP request...");
|
||||
const split = req.headers.host.split('.');
|
||||
if (DEBUG === 1) console.log("Request Headers Host Split: ", split);
|
||||
const publicKey = Buffer.from(b32.decode.asBytes(split[0].toUpperCase()));
|
||||
if (DEBUG === 1) {
|
||||
console.log("Public Key Buffer: ", publicKey);
|
||||
console.log("Length: " + publicKey.length);
|
||||
}
|
||||
if (!(publicKey.length >= 32)) {
|
||||
console.log("Invalid Connection!")
|
||||
res.writeHead(404, { 'Content-Type': 'text/html' });
|
||||
res.end(content);
|
||||
invalid = true
|
||||
} else {
|
||||
invalid = false
|
||||
}
|
||||
if (invalid == true) return
|
||||
if (!tunnels[publicKey]) {
|
||||
console.log("No tunnel found for public key, creating new tunnel...");
|
||||
const port = 1337 + ((mod++) % 1000);
|
||||
const server = net.createServer(function (servsock) {
|
||||
console.log('Incoming Connection, Connecting to:', publicKey.toString('hex'));
|
||||
if (DEBUG === 1) console.log("Public Key Length: ", publicKey.toString('hex').length);
|
||||
const socket = dhtServer.connect(publicKey);
|
||||
|
||||
const local = servsock;
|
||||
let open = { local: true, remote: true };
|
||||
local.on('data', (d) => {
|
||||
if (DEBUG === 1) console.log("Local Data: ", d);
|
||||
socket.write(d);
|
||||
});
|
||||
socket.on('data', (d) => {
|
||||
if (DEBUG === 1) console.log("Socket Data: ", d);
|
||||
local.write(d);
|
||||
});
|
||||
|
||||
const remoteend = (type) => {
|
||||
if (DEBUG === 1) console.log('Local Connection Ended, Ending Remote Connection');
|
||||
if (open.remote) socket.end();
|
||||
open.remote = false;
|
||||
};
|
||||
|
||||
const localend = (type) => {
|
||||
if (DEBUG === 1) console.log('Remote Connection Ended, Ending Local Connection');
|
||||
if (open.local) local.end();
|
||||
open.local = false;
|
||||
};
|
||||
|
||||
local.on('error', remoteend);
|
||||
local.on('finish', remoteend);
|
||||
local.on('end', remoteend);
|
||||
socket.on('finish', localend);
|
||||
socket.on('error', localend);
|
||||
socket.on('end', localend);
|
||||
});
|
||||
|
||||
server.listen(port, "127.0.0.1");
|
||||
tunnels[publicKey] = port;
|
||||
console.log("New tunnel created. Public Key:", publicKey, "Port:", port);
|
||||
proxy.web(req, res, {
|
||||
target: 'http://127.0.0.1:' + port
|
||||
}, function (e) {
|
||||
console.log("Proxy Web Error: ", e);
|
||||
res.writeHead(404, { 'Content-Type': 'text/html' });
|
||||
res.end(content);
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
console.log('Tunnel exists for public key:', publicKey);
|
||||
proxy.web(req, res, {
|
||||
target: 'http://127.0.0.1:' + tunnels[publicKey]
|
||||
}, function (e) {
|
||||
console.log("Proxy Web Error: ", e);
|
||||
res.writeHead(404, { 'Content-Type': 'text/html' });
|
||||
res.end(content);
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Error Occurred: ", e);
|
||||
}
|
||||
});
|
||||
|
||||
server.on('upgrade', function (req, socket, head) {
|
||||
console.log('Upgrade Request');
|
||||
const split = req.headers.host.split('.');
|
||||
const publicKey = Buffer.from(b32.decode.asBytes(split[0].toUpperCase()));
|
||||
proxy.ws(req, socket, {
|
||||
target: 'http://127.0.0.1:' + tunnels[publicKey]
|
||||
}, function (e) {
|
||||
console.error("Proxy WS Error: ", e);
|
||||
socket.end();
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(8081);
|
||||
console.log("HTTP server listening on port 8081");
|
||||
|
||||
process.on('SIGINT', function () {
|
||||
console.log("Shutting down...");
|
||||
server.close();
|
||||
dhtServer.destroy();
|
||||
console.log("Shutdown complete.");
|
||||
process.exit();
|
||||
});
|
||||
};
|
||||
|
||||
startServer().catch(console.error);
|
24
package.json
Normal file
24
package.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "raven",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "proxy.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@hyperswarm/dht": "^6.5.1",
|
||||
"bun": "^1.0.35",
|
||||
"graceful-goodbye": "^1.3.0",
|
||||
"hi-base32": "^0.5.1",
|
||||
"http": "^0.0.1-security",
|
||||
"http-proxy": "^1.18.1",
|
||||
"http2-proxy": "^5.0.53",
|
||||
"hyper-cmd-lib-keys": "^0.1.0",
|
||||
"hyper-cmd-lib-net": "^0.1.0",
|
||||
"hyperdht": "^6.13.1",
|
||||
"pump": "^3.0.0"
|
||||
}
|
||||
}
|
35
relay.js
Normal file
35
relay.js
Normal file
@ -0,0 +1,35 @@
|
||||
const DHT = require("@hyperswarm/dht");
|
||||
const net = require("net");
|
||||
const pump = require("pump");
|
||||
const node = new DHT({});
|
||||
module.exports = () => {
|
||||
return {
|
||||
serve: (keyPair, host, port) => {
|
||||
const server = node.createServer();
|
||||
server.on("connection", function (servsock) {
|
||||
const socket = net.connect(port, host);
|
||||
socket.on('serve error', console.error);
|
||||
let open = { servsock: true, remote: true };
|
||||
servsock.on('data', (d) => { socket.write(d) });
|
||||
socket.on('data', (d) => { servsock.write(d) });
|
||||
|
||||
const remoteend = () => {
|
||||
if (open.remote) socket.end();
|
||||
open.remote = false;
|
||||
}
|
||||
const servsockend = () => {
|
||||
if (open.servsock) servsock.end();
|
||||
open.servsock = false;
|
||||
}
|
||||
servsock.on('error', remoteend)
|
||||
servsock.on('finish', remoteend)
|
||||
servsock.on('end', remoteend)
|
||||
socket.on('finish', servsockend)
|
||||
socket.on('error', servsockend)
|
||||
socket.on('end', servsockend)
|
||||
});
|
||||
server.listen(keyPair);
|
||||
return keyPair.publicKey;
|
||||
}
|
||||
};
|
||||
};
|
34
server.js
Normal file
34
server.js
Normal file
@ -0,0 +1,34 @@
|
||||
const net = require('net');
|
||||
const b32 = require("hi-base32");
|
||||
const DHT = require("@hyperswarm/dht");
|
||||
const node = new DHT({});
|
||||
const pump = require("pump");
|
||||
const { pipeline } = require('stream');
|
||||
const server = net.createServer(clientSocket => {
|
||||
clientSocket.on('end', () => {
|
||||
console.log('Client disconnected');
|
||||
});
|
||||
|
||||
clientSocket.on('error', err => {
|
||||
console.error('Client socket error:', err);
|
||||
});
|
||||
|
||||
clientSocket.once("data",(firstData) => {
|
||||
const firstLine = firstData.toString()
|
||||
if (firstLine !== '') {
|
||||
console.log(firstLine)
|
||||
const [hostname] = firstLine.split("\n").filter(a=>a.toLowerCase().startsWith('host:'));
|
||||
const split = hostname.split(":")[1].trim().split('.');
|
||||
console.log(split);
|
||||
const publicKey = Buffer.from(b32.decode.asBytes(split[0].toUpperCase()), 'hex');
|
||||
console.log(publicKey.toString('hex'))
|
||||
const socket = node.connect(publicKey);
|
||||
socket.on('client error', console.error);
|
||||
pump(socket,clientSocket,socket)
|
||||
socket.write(firstLine);
|
||||
}
|
||||
});
|
||||
});
|
||||
server.listen(8081, () => {
|
||||
console.log('Proxy server listening');
|
||||
});
|
154
worker-server.js
Normal file
154
worker-server.js
Normal file
@ -0,0 +1,154 @@
|
||||
const cluster = require('cluster');
|
||||
const numCPUs = require('os').cpus().length;
|
||||
|
||||
if (cluster.isMaster) {
|
||||
console.log(`Master ${process.pid} is running`);
|
||||
console.log(`Total Workers ${numCPUs*8}`)
|
||||
// Fork workers
|
||||
for (let i = 0; i < numCPUs; i++) {
|
||||
cluster.fork();
|
||||
}
|
||||
|
||||
cluster.on('exit', (worker, code, signal) => {
|
||||
console.log(`Worker ${worker.process.pid} died`);
|
||||
});
|
||||
} else {
|
||||
const fs = require('fs');
|
||||
const http = require('http');
|
||||
const httpProxy = require('http-proxy');
|
||||
const HyperDHTServer = require('hyperdht');
|
||||
const b32 = require("hi-base32");
|
||||
const net = require("net");
|
||||
let invalid = false;
|
||||
|
||||
const tunnels = {};
|
||||
const agent = new http.Agent({ maxSockets: Number.MAX_VALUE });
|
||||
const content = fs.readFileSync('404.txt.new', 'utf8');
|
||||
const DEBUG = 0; // Set DEBUG to 1 to enable debug mode
|
||||
const CONINFO = 0; // Set CONINFO to 1 for a smaller breakdown of connections.
|
||||
const dhtServer = new HyperDHTServer();
|
||||
|
||||
const startServer = async () => {
|
||||
console.log(`Worker ${process.pid} started`);
|
||||
await dhtServer.ready();
|
||||
|
||||
const proxy = httpProxy.createProxyServer({
|
||||
ws: true,
|
||||
agent: agent,
|
||||
timeout: 360000
|
||||
});
|
||||
|
||||
const server = http.createServer(async function (req, res) {
|
||||
try {
|
||||
if (DEBUG === 1 || CONINFO === 1) console.log("Incoming HTTP request...");
|
||||
const split = req.headers.host.split('.');
|
||||
if (DEBUG === 1) console.log("Request Headers Host Split: ", split);
|
||||
const publicKey = Buffer.from(b32.decode.asBytes(split[0].toUpperCase()));
|
||||
if (DEBUG === 1) {
|
||||
console.log("Public Key Buffer: ", publicKey);
|
||||
console.log("Length: " + publicKey.length);
|
||||
}
|
||||
if (!(publicKey.length >= 32)) {
|
||||
console.log("Invalid Connection!")
|
||||
res.writeHead(418, { 'Content-Type': 'text/html' });
|
||||
res.end(content);
|
||||
invalid = true
|
||||
} else {
|
||||
invalid = false
|
||||
}
|
||||
if (invalid == true) return
|
||||
if (!tunnels[publicKey]) {
|
||||
if (DEBUG === 1 || CONINFO === 1) console.log("No tunnel found for public key, creating new tunnel...");
|
||||
const port = await getAvailablePort(); // Get an available port
|
||||
const server = net.createServer(function (servsock) {
|
||||
if (DEBUG === 1 || CONINFO === 1) console.log('Incoming Connection, Connecting to:', publicKey.toString('hex'));
|
||||
if (DEBUG === 1) console.log("Public Key Length: ", publicKey.toString('hex').length);
|
||||
const socket = dhtServer.connect(publicKey);
|
||||
|
||||
const local = servsock;
|
||||
let open = { local: true, remote: true };
|
||||
local.on('data', (d) => {
|
||||
if (DEBUG === 1) console.log("Local Data: ", d);
|
||||
socket.write(d);
|
||||
});
|
||||
socket.on('data', (d) => {
|
||||
if (DEBUG === 1) console.log("Socket Data: ", d);
|
||||
local.write(d);
|
||||
});
|
||||
|
||||
const remoteend = (type) => {
|
||||
if (DEBUG === 1) console.log('Local Connection Ended, Ending Remote Connection');
|
||||
if (open.remote) socket.end();
|
||||
open.remote = false;
|
||||
};
|
||||
|
||||
const localend = (type) => {
|
||||
if (DEBUG === 1) console.log('Remote Connection Ended, Ending Local Connection');
|
||||
if (open.local) local.end();
|
||||
open.local = false;
|
||||
};
|
||||
|
||||
local.on('error', remoteend);
|
||||
local.on('finish', remoteend);
|
||||
local.on('end', remoteend);
|
||||
socket.on('finish', localend);
|
||||
socket.on('error', localend);
|
||||
socket.on('end', localend);
|
||||
});
|
||||
|
||||
// Check if the port is available
|
||||
server.listen(port, "127.0.0.1", () => {
|
||||
if (DEBUG === 1 | CONINFO === 1) console.log(`Tunnel server listening on port ${port}`);
|
||||
tunnels[publicKey] = port;
|
||||
if (DEBUG === 1 || CONINFO === 1) console.log("New tunnel created. Public Key:", publicKey, "Port:", port);
|
||||
proxy.web(req, res, {
|
||||
target: 'http://127.0.0.1:' + port
|
||||
}, function (e) {
|
||||
console.log("Proxy Web Error: ", e);
|
||||
res.writeHead(404, { 'Content-Type': 'text/html' });
|
||||
res.end(content);
|
||||
});
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
if (DEBUG === 1) console.log('Tunnel exists for public key:', publicKey);
|
||||
proxy.web(req, res, {
|
||||
target: 'http://127.0.0.1:' + tunnels[publicKey]
|
||||
}, function (e) {
|
||||
console.log("Proxy Web Error: ", e);
|
||||
res.writeHead(418, { 'Content-Type': 'text/html' });
|
||||
res.end(content);
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Error Occurred: ", e);
|
||||
}
|
||||
});
|
||||
|
||||
server.on('upgrade', function (req, socket, head) {
|
||||
if (DEBUG === 1) console.log('Upgrade Request');
|
||||
const split = req.headers.host.split('.');
|
||||
const publicKey = Buffer.from(b32.decode.asBytes(split[0].toUpperCase()));
|
||||
proxy.ws(req, socket, {
|
||||
target: 'http://127.0.0.1:' + tunnels[publicKey]
|
||||
}, function (e) {
|
||||
console.error("Proxy WS Error: ", e);
|
||||
socket.end();
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(8081, () => {
|
||||
console.log(`Worker ${process.pid} listening on port 8081`);
|
||||
});
|
||||
};
|
||||
|
||||
startServer().catch(console.error);
|
||||
|
||||
async function getAvailablePort() {
|
||||
let port;
|
||||
do {
|
||||
port = 1337 + Math.floor(Math.random() * 1000); // Generate a random port between 1337 and 2336
|
||||
} while (Object.values(tunnels).includes(port)); // Check if the port is already used
|
||||
return port;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user