add TCP and UDP reverse

This commit is contained in:
FullGreaM 2025-12-02 00:54:42 +03:00
parent 3d77282891
commit 4839fb2a12
7 changed files with 226 additions and 8 deletions

View File

@ -18,7 +18,7 @@ function logger (...p) {
console.log("[DEBUG.http]:", ...p); console.log("[DEBUG.http]:", ...p);
} }
function fetchProxy (req, res, reverseTo) { function fetchProxy (server, req, res, reverseTo) {
const params = { method: req.method.toUpperCase(), headers: Object.assign({}, req.headers), redirect: "follow", follow: 20, compress: false }; const params = { method: req.method.toUpperCase(), headers: Object.assign({}, req.headers), redirect: "follow", follow: 20, compress: false };
delete params.headers.host; delete params.headers.host;
delete params.headers.referer; delete params.headers.referer;
@ -26,7 +26,10 @@ function fetchProxy (req, res, reverseTo) {
params.body = req.body; params.body = req.body;
const reqAddress = url.resolve(reverseTo, path.join("/", req.originalUrl)); const reqAddress = url.resolve(reverseTo, path.join("/", req.originalUrl));
fetch(reqAddress, params) server.get("http://expample", res => {
console.log("res:", res);
});
/*fetch(reqAddress, params) // Deprecated
.then(async result => { .then(async result => {
const content = await result.arrayBuffer(); const content = await result.arrayBuffer();
//logger("result:", result); //logger("result:", result);
@ -49,7 +52,7 @@ function fetchProxy (req, res, reverseTo) {
.catch(err => { .catch(err => {
console.error(err); console.error(err);
res.status(500).send(req.st500); res.status(500).send(req.st500);
}); });*/
} }
function authPage (self, req, res, next) { function authPage (self, req, res, next) {
@ -206,7 +209,7 @@ module.exports = class HTTPServer extends Component {
throw new SyntaxError("You can't call revHTTP domain from unsupported type. Supported types: revHTTP, simpleHTTP, redirectHTTP"); throw new SyntaxError("You can't call revHTTP domain from unsupported type. Supported types: revHTTP, simpleHTTP, redirectHTTP");
switch (callCommand) { switch (callCommand) {
case "proxy": case "proxy":
return fetchProxy(req, res, this.syntax.target); return fetchProxy(this.server, req, res, this.syntax.target);
case "auth": case "auth":
const authContext = context.syntax.auth === undefined ? this : context; const authContext = context.syntax.auth === undefined ? this : context;
return authPage(authContext, req, res, next); return authPage(authContext, req, res, next);

View File

@ -30,7 +30,7 @@ module.exports = class HTTPReverse extends HTTPServer {
.callDomain(currentDomain, this.syntax.domains[currentDomain]) .callDomain(currentDomain, this.syntax.domains[currentDomain])
.argv(this.syntax.domains[currentDomain].Type.type(), req, res); .argv(this.syntax.domains[currentDomain].Type.type(), req, res);
} }
return fetchProxy(req, res, reverseTo); return fetchProxy(this.server, req, res, reverseTo);
}); });
this.postinit((err) => { this.postinit((err) => {

View File

@ -2,4 +2,6 @@ module.exports = {
"revHTTP": require("./http-reverse"), "revHTTP": require("./http-reverse"),
"simpleHTTP": require("./http-simple"), "simpleHTTP": require("./http-simple"),
"redirectHTTP": require("./http-redirector"), "redirectHTTP": require("./http-redirector"),
"TCP": require("./tcp"),
"UDP": require("./udp"),
}; };

View File

@ -1,3 +1,118 @@
const Component = require("./_component"); const Component = require("./_component");
const net = require('net');
const fs = require('fs');
class TCPServer extends Component {} function logger (...p) {
return;
console.debug("[TCP reverse]:", ...p);
};
async function isFirewalled () { // TODO: Firewall
return false;
}
module.exports = class TCPServer extends Component {
static type () {
return "tcp-proxy";
}
constructor (adr, syntaxTree) {
super(adr, syntaxTree);
if (syntaxTree.firewall) {
throw new Error("Firewall doesn't supports");
}
}
run () {
this.server = net.createServer(async (srvSocket) => {
const isFrw = await isFirewalled(srvSocket.remoteAddress);
if (isFrw) {
srvSocket.end();
logger(`${srvSocket.remoteAddress} firewalled, reject`);
}
srvSocket.on("error", (err) => {
logger("Caught server socket error: ");
logger(err.stack);
});
});
const connections = {};
this.server.on('connection', async (socket) => {
socket.fullAddress = `${socket.remoteAddress}:${socket.remotePort}`;
//const loggerPromise = loggingIp(`${this.adr.address}:${this.adr.port}`, socket.remoteAddress, new Date());
const isFrw = await isFirewalled(socket.remoteAddress);
if (isFrw) {
socket.end();
logger(`${socket.remoteAddress} firewalled, reject`);
//await loggerPromise;
return;
}
else {
//await loggerPromise;
const remote = {
ip: this.syntax.target.split(/:/)[0],
port: this.syntax.target.split(/:/)[1],
};
connections[socket.fullAddress] = net.createConnection(remote.port, remote.ip);
logger(`${socket.remoteAddress} was been connected, connect to remote created`);
socket.on('data', (data) => {
logger(`from ${socket.remoteAddress} sended: ${data.length} bytes`);
connections[socket.fullAddress].write(data, function(err) {
if (err)
logger(`error: ${socket.remoteAddress} throwed: ${err.name}`);
// connections[socket.fullAddress].end();
});
// connections[socket.fullAddress].end();
});
connections[socket.fullAddress].on('data', (data) => {
logger(`to ${socket.remoteAddress} sended: ${data.length} bytes`);
socket.write(data, function(err) {
if (err)
logger(`error: ${socket.remoteAddress} (remote) throwed: ${err.name}`);
// socket.end();
});
// socket.end();
});
connections[socket.fullAddress].on('end', (data) => {
logger(`remote of ${socket.remoteAddress} disconnected`);
socket.end();
});
connections[socket.fullAddress].on('error', (err) => {
logger(`remote of ${socket.remoteAddress} error:`);
logger(err.stack);
socket.end();
});
socket.on('end', () => {
logger(`${socket.remoteAddress} disconnected`);
connections[socket.fullAddress].end();
connections[socket.fullAddress] = undefined; // Free memory!
});
socket.on("error", (err) => {
logger(
`socket.on(${socket.remoteAddress}) error:`
);
logger(err.stack);
connections[socket.fullAddress].end();
// socket.end();
});
}
});
this.server.on('error', (err) => {
logger("Error of server");
logger(err.stack);
});
this.server.listen(this.adr.port, this.adr.address, (err) => {
if (err) throw err;
console.log("TCP reverse proxy connected!");
});
}
}

92
components/udp.js Normal file
View File

@ -0,0 +1,92 @@
const Component = require("./_component");
const dgram = require('node:dgram');
const fs = require('fs');
function logger (...p) {
return;
console.debug("[UDP reverse]:", ...p);
};
function isFirewalled () { // TODO: Firewall
return false;
}
module.exports = class UDPServer extends Component {
static type () {
return "udp-proxy";
}
constructor (adr, syntaxTree) {
super(adr, syntaxTree);
if (syntaxTree.firewall) {
throw new Error("Firewall doesn't supports");
}
}
run () {
const server = dgram.createSocket('udp4', (srvSocket) => {});
const connections = {};
// const connectionsTimeout = {};
const remote = {
ip: this.syntax.target.split(/:/)[0],
port: this.syntax.target.split(/:/)[1],
};
server.on('error', (err) => {
logger("Caught UDP server socket error: ");
logger(err.stack);
});
server.on('connect', (peer) => {
logger("connect event:", peer);
if (!isFirewalled(peer.address)) {
logger(`${peer.address}:${peer.port} connected!`);
connections[`${peer.address}:${peer.port}`] = dgram.createSocket('udp4');
connections[`${peer.address}:${peer.port}`].on('message', (data, rmt) => {
if (`${rmt.address}:${rmt.port}` === `${remote.ip}:${remote.port}`) {
logger(`to ${peer.address}:${peer.port} sended: ${data.length} bytes`);
server.send(data, peer.port, peer.address, (err) => {
if (err)
logger(`error: ${peer.address}:${peer.port} throwed: ${err.name}`);
});
}
});
}
else {
logger(`${peer.address} firewalled, reject`);
}
});
server.on('message', (data, peer) => {
logger(`from ${peer.address}:${peer.port} attempt send to ${remote.ip}:${remote.port} ${data.length} bytes`);
if (`${peer.address}:${peer.port}` !== `${remote.ip}:${remote.port}`) {
logger(`from ${peer.address}:${peer.port} sended: ${data.length} bytes to ${remote.ip}:${remote.port}`);
if (connections[`${peer.address}:${peer.port}`] === undefined) {
server.emit("connect", peer);
}
if (connections[`${peer.address}:${peer.port}`] !== undefined) {
connections[`${peer.address}:${peer.port}`].send(data, remote.port, remote.ip, (err) => {
if (err)
logger(`error: ${peer.address} (remote) throwed: ${err.name}`);
});
}
}
});
server.on('listening', () => {
const address = server.address();
console.log(`UDP reverse proxy server listening on ${address.address}:${address.port}`);
});
server.bind(this.adr.port, this.adr.address, (err) => {
if (err) throw err;
console.log("UDP reverse proxy connected!");
});
server.on('error', (err) => {
logger("Error of server");
logger(err.stack);
});
}
}

View File

@ -126,7 +126,7 @@ function readInstructions (instructions, fullCode, forDomains=false) {
} }
function logger (...p) { function logger (...p) {
//return; return;
console.debug("[DEBUG.routemap]:", ...p); console.debug("[DEBUG.routemap]:", ...p);
} }

View File

@ -3,7 +3,7 @@
type revHTTP; type revHTTP;
target https://example.org; # RRR target https://example.org; # RRR
querylimit 0; querylimit 5;
domain localhost { domain localhost {
firewall whitelist GLOBAL; firewall whitelist GLOBAL;
type revHTTP; type revHTTP;
@ -35,3 +35,9 @@
target /; target /;
#showdir; #showdir;
} }
127.0.0.1:1111 {
type TCP;
# SSH-Proxy to my device
target 127.0.0.1:22;
}