Works on http-reverse auth, add cookie-parser module, add simple support of custom modules
This commit is contained in:
parent
0a9355bc9d
commit
ff4d7fdace
@ -8,9 +8,10 @@ const url = require('url');
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const fetch = require('node-fetch');
|
const fetch = require('node-fetch');
|
||||||
|
const cookieParser = require('cookie-parser')
|
||||||
|
|
||||||
function logger (...p) {
|
function logger (...p) {
|
||||||
//return;
|
return;
|
||||||
console.log("[DEBUG.main]:", ...p);
|
console.log("[DEBUG.main]:", ...p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,6 +116,12 @@ module.exports = class HTTPReverse extends Component {
|
|||||||
authPage(this, req, res, next)
|
authPage(this, req, res, next)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.app.use(cookieParser());
|
||||||
|
|
||||||
|
this.syntax.routelist.forEach(route => {
|
||||||
|
this.app.use(route);
|
||||||
|
});
|
||||||
|
|
||||||
this.app.use("*", async (req, res) => {
|
this.app.use("*", async (req, res) => {
|
||||||
logger("REQ HEADERS:>", req.headers);
|
logger("REQ HEADERS:>", req.headers);
|
||||||
logger("originalUrl:>", req.originalUrl);
|
logger("originalUrl:>", req.originalUrl);
|
||||||
|
10
modules/example.js
Normal file
10
modules/example.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
const NetProxierModule = require("./");
|
||||||
|
|
||||||
|
module.exports = class ExampleMdoule extends NetProxierModule {
|
||||||
|
constructor () {
|
||||||
|
super();
|
||||||
|
this.operators.push(new this.statics.Operator("testi", () => true, () => {
|
||||||
|
console.log("BEEP");
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
43
modules/example_custom_auth.js
Normal file
43
modules/example_custom_auth.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
const express = require("express");
|
||||||
|
const NetProxierModule = require("./");
|
||||||
|
|
||||||
|
const HTTPReverse = require("../components/http-reverse");
|
||||||
|
|
||||||
|
module.exports = class CustomAuthPage extends NetProxierModule {
|
||||||
|
constructor () {
|
||||||
|
super();
|
||||||
|
|
||||||
|
const cauth = new this.statics.Operator("cauth", (argv) => {
|
||||||
|
return argv.length === 2;
|
||||||
|
}, (argv, self, syntaxTree) => {
|
||||||
|
if (![HTTPReverse].includes(syntaxTree.Type)) {
|
||||||
|
throw new SyntaxError("Unsupported type of server");
|
||||||
|
}
|
||||||
|
const [ login, password ] = argv;
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.get("/auth/:redirectTo", (req, res, next) => {
|
||||||
|
if (req.cookies.auth === login + ":" + password)
|
||||||
|
return next();
|
||||||
|
const endless = req.query.login + ":" + req.query.password;
|
||||||
|
const redirectTo = Buffer.from(req.params.redirectTo, "hex").toString("utf8");
|
||||||
|
//console.log("redirect to:", redirectTo);
|
||||||
|
if (endless === login + ":" + password) {
|
||||||
|
res.cookie("auth", endless);
|
||||||
|
}
|
||||||
|
res.redirect(redirectTo);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.use((req, res, next) => {
|
||||||
|
//console.log('Cookies: ', req.cookies);
|
||||||
|
if (req.cookies.auth === login + ":" + password)
|
||||||
|
return next();
|
||||||
|
res.send('<form action=\"/auth/'+ Buffer.from(req.originalUrl).toString("hex") +'\"><h4>Needs auth</h4><hr/><p>Логин: <input type="text" size="40" name="login"></p><p>Пароль: <input type="password" size="40" name="password"></p><p><input type="submit"></p></form>');
|
||||||
|
});
|
||||||
|
|
||||||
|
syntaxTree.routelist.push(router);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.operators.push(cauth);
|
||||||
|
}
|
||||||
|
};
|
49
modules/index.js
Normal file
49
modules/index.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Func
|
||||||
|
|
||||||
|
class OperatorsStorage extends Array {
|
||||||
|
constructor (...p) {
|
||||||
|
super(...p);
|
||||||
|
this._indexObject = {};
|
||||||
|
this._indexObjectIndexOf = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
push (item) {
|
||||||
|
if (item instanceof Operator) {
|
||||||
|
if (!this._indexObject[item.operator]) {
|
||||||
|
super.push(item);
|
||||||
|
this._indexObject[item.operator] = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new TypeError("Into OperatorsStorage you can add only Operator's instances");
|
||||||
|
}
|
||||||
|
|
||||||
|
includes (item) {
|
||||||
|
if (item instanceof Operator) {
|
||||||
|
return this._indexObject[item.operator] !== undefined;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new TypeError("Into OperatorsStorage storage only Operator type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
class Operator {
|
||||||
|
constructor (operatorName, argvHandler = () => true, exec = (argv, module) => {}) {
|
||||||
|
this.operator = operatorName;
|
||||||
|
this.handlers = {
|
||||||
|
argv: argvHandler,
|
||||||
|
exec
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = class NetProxierModule {
|
||||||
|
constructor () {
|
||||||
|
this.operators = new OperatorsStorage();
|
||||||
|
|
||||||
|
this.statics = new Object();
|
||||||
|
this.statics.Operator = Operator;
|
||||||
|
}
|
||||||
|
}
|
21
package-lock.json
generated
21
package-lock.json
generated
@ -11,6 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"body": "^5.1.0",
|
"body": "^5.1.0",
|
||||||
"body-parser": "^1.20.3",
|
"body-parser": "^1.20.3",
|
||||||
|
"cookie-parser": "^1.4.7",
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
"node-fetch": "^2.6.7",
|
"node-fetch": "^2.6.7",
|
||||||
"sse": "^0.0.8"
|
"sse": "^0.0.8"
|
||||||
@ -237,6 +238,26 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cookie-parser": {
|
||||||
|
"version": "1.4.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz",
|
||||||
|
"integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==",
|
||||||
|
"dependencies": {
|
||||||
|
"cookie": "0.7.2",
|
||||||
|
"cookie-signature": "1.0.6"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cookie-parser/node_modules/cookie": {
|
||||||
|
"version": "0.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
|
||||||
|
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cookie-signature": {
|
"node_modules/cookie-signature": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"body": "^5.1.0",
|
"body": "^5.1.0",
|
||||||
"body-parser": "^1.20.3",
|
"body-parser": "^1.20.3",
|
||||||
|
"cookie-parser": "^1.4.7",
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
"node-fetch": "^2.6.7",
|
"node-fetch": "^2.6.7",
|
||||||
"sse": "^0.0.8"
|
"sse": "^0.0.8"
|
||||||
|
@ -4,16 +4,17 @@ const components = require("./components");
|
|||||||
|
|
||||||
// General regexps
|
// General regexps
|
||||||
// const FIND_ADDRESS_INSTR_REGEX = /([0-9]{1,3}\.){3}[0-9]{1,3}:[0-9]{1,5}\s{0,}\{[\s\n\r0-9a-z;:\/\."',]{0,}\}/gmi;
|
// const FIND_ADDRESS_INSTR_REGEX = /([0-9]{1,3}\.){3}[0-9]{1,3}:[0-9]{1,5}\s{0,}\{[\s\n\r0-9a-z;:\/\."',]{0,}\}/gmi;
|
||||||
const DOMAINER_REGEX = /domain\s{1,}[a-z0-9\.]{1,}\s{1,}\{[\s\n\r0-9a-z;:\/\."',]{0,}\}/gmi;
|
const DOMAINER_REGEX = /domain\s{1,}[a-z0-9\.]{1,}\s{1,}\{[\s\n\r0-9a-z;:\/\."',_]{0,}\}/gmi;
|
||||||
const DOMAINER_VALUE_FIND_REGEX = /domain\s{1,}[a-z0-9\.]{1,}\s{1,}\{/gmi;
|
const DOMAINER_VALUE_FIND_REGEX = /domain\s{1,}[a-z0-9\.]{1,}\s{1,}\{/gmi;
|
||||||
const ADDRESS_WITH_PORT_REGEX = /([0-9]{1,3}\.){3}[0-9]{1,3}:[0-9]{1,5}/mi;
|
const ADDRESS_WITH_PORT_REGEX = /([0-9]{1,3}\.){3}[0-9]{1,3}:[0-9]{1,5}/mi;
|
||||||
const FIND_ADDRESS_INSTR_REGEX = /([0-9]{1,3}\.){3}[0-9]{1,3}:[0-9]{1,5}\s{0,}\{([\s\n\r0-9a-z;:\/\."',]|domain\s{1,}[a-z0-9\.]{1,}\s{1,}\{[\s\n\r0-9a-z;:\/\."',]{0,}\}){0,}\}/gmi;
|
const FIND_ADDRESS_INSTR_REGEX = /([0-9]{1,3}\.){3}[0-9]{1,3}:[0-9]{1,5}\s{0,}\{([\s\n\r0-9a-z;:\/\."',_]|domain\s{1,}[a-z0-9\._]{1,}\s{1,}\{[\s\n\r0-9a-z;:\/\."',_]{0,}\}){0,}\}/gmi;
|
||||||
const COMMENT_REGEX = /#.{0,}(\n|\r|$)/gmi;
|
const COMMENT_REGEX = /#.{0,}(\n|\r|$)/gmi;
|
||||||
const CONTENT_INTO_CURLY_BRACES = /\{[\s\n\r0-9a-z;:\/\."',]{0,}\}{0,}\}/gmi;
|
const CONTENT_INTO_CURLY_BRACES = /\{[\s\n\r0-9a-z;:\/\."',_]{0,}\}{0,}\}/gmi;
|
||||||
|
|
||||||
// Instruction regexps
|
// Instruction regexps
|
||||||
function readInstructions (instructions, fullCode, forDomains=false) {
|
function readInstructions (instructions, fullCode, forDomains=false) {
|
||||||
const syntaxTree = { firewall: false, encryption: {} };
|
const syntaxTree = { firewall: false, encryption: {}, modules: new Set(), routelist: [] };
|
||||||
|
const moduleOpsQueue = new Array();
|
||||||
|
|
||||||
for (let instruction of instructions) {
|
for (let instruction of instructions) {
|
||||||
if (!instruction) {
|
if (!instruction) {
|
||||||
@ -24,6 +25,7 @@ function readInstructions (instructions, fullCode, forDomains=false) {
|
|||||||
}
|
}
|
||||||
const instructionParts = instruction.split(/\s{1,}/);
|
const instructionParts = instruction.split(/\s{1,}/);
|
||||||
const mainOperator = instructionParts[0];
|
const mainOperator = instructionParts[0];
|
||||||
|
|
||||||
switch (mainOperator) {
|
switch (mainOperator) {
|
||||||
case "type":
|
case "type":
|
||||||
if (instructionParts.length !== 2)
|
if (instructionParts.length !== 2)
|
||||||
@ -58,11 +60,36 @@ function readInstructions (instructions, fullCode, forDomains=false) {
|
|||||||
break;
|
break;
|
||||||
case "firewall":
|
case "firewall":
|
||||||
break;
|
break;
|
||||||
|
case "import":
|
||||||
|
if (instructionParts.length < 2)
|
||||||
|
throw new SyntaxError("Invalid syntax of operator `import`: import <module_name> OR import <module_name1>, <module_name2>, ..., <module_name3>");
|
||||||
|
const modules = instructionParts.slice(1,).join(" ").split(/\s{0,},\s{0,}/gmi);
|
||||||
|
modules.forEach(m => syntaxTree.modules.add(new (require(`./modules/${m}`))()));
|
||||||
|
break;
|
||||||
case "#instuction:domain":
|
case "#instuction:domain":
|
||||||
if (forDomains)
|
if (forDomains)
|
||||||
throw new SyntaxError("Nested use of domains doesn't not supported");
|
throw new SyntaxError("Nested use of domains doesn't not supported");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
let mopFlag = false
|
||||||
|
for (let module of syntaxTree.modules) {
|
||||||
|
for (let op of module.operators) {
|
||||||
|
if (op.operator === mainOperator) {
|
||||||
|
// Нуждается в доработке!
|
||||||
|
if (!op.handlers.argv(instructionParts.slice(1,)))
|
||||||
|
throw new SyntaxError("Custom module's operator error. Invalid argv syntax on operator: " + mainOperator);
|
||||||
|
|
||||||
|
moduleOpsQueue.push(
|
||||||
|
(st) => op.handlers.exec(instructionParts.slice(1,), module, st)
|
||||||
|
);
|
||||||
|
mopFlag = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mopFlag)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (mopFlag) break;
|
||||||
throw new SyntaxError(`Unknown routemap's operator: ${mainOperator}`);
|
throw new SyntaxError(`Unknown routemap's operator: ${mainOperator}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,6 +109,16 @@ function readInstructions (instructions, fullCode, forDomains=false) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
syntaxTree.modules = Array.from(syntaxTree.modules);
|
||||||
|
|
||||||
|
// Object.assign needs replace to object which give only-read access
|
||||||
|
// Except: routelist
|
||||||
|
moduleOpsQueue.forEach(h => {
|
||||||
|
const st = Object.assign({}, syntaxTree);
|
||||||
|
st.routelist = syntaxTree.routelist;
|
||||||
|
return h(st);
|
||||||
|
});
|
||||||
|
|
||||||
return syntaxTree;
|
return syntaxTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,12 +6,18 @@
|
|||||||
type revHTTP;
|
type revHTTP;
|
||||||
target https://github.com;
|
target https://github.com;
|
||||||
};
|
};
|
||||||
|
domain domain.loc {
|
||||||
|
import example;
|
||||||
|
testi;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
127.0.0.1:7889 {
|
127.0.0.1:7889 {
|
||||||
|
import example, example_custom_auth;
|
||||||
type revHTTP;
|
type revHTTP;
|
||||||
target https://google.com;
|
target https://google.com;
|
||||||
auth loopback admin qwerty;
|
#auth loopback admin qwerty;
|
||||||
|
cauth admin 123;
|
||||||
cert public ./tests/pub.crt;
|
cert public ./tests/pub.crt;
|
||||||
cert private ./tests/priv.key;
|
cert private ./tests/priv.key;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user