This commit is contained in:
DomySh
2022-07-22 00:34:57 +02:00
parent 1399d0e22d
commit d8dc5c9f8b
38 changed files with 112 additions and 81 deletions

View File

@@ -15,9 +15,9 @@ Dockerfile
/frontend/coverage
/backend/db/
/backend/db/firegex.db
/backend/db/firegex.db-journal
/backend/db/**
/backend/modules/cppqueue
/backend/modules/proxy
docker-compose.yml
# misc

1
.gitignore vendored
View File

@@ -15,6 +15,7 @@
/backend/db/
/backend/db/**
/backend/modules/cppqueue
/backend/modules/proxy
docker-compose.yml
# misc

View File

@@ -16,11 +16,11 @@ RUN mkdir build; cd build; cmake ../ -DLIBTINS_ENABLE_CXX11=1; make; make instal
RUN mkdir -p /execute/modules
WORKDIR /execute
COPY ./backend/nfqueue /execute/nfqueue
COPY ./backend/binsrc /execute/binsrc
ARG GCC_PARAMS
RUN g++ nfqueue/nfqueue.cpp -o modules/cppqueue -std=c++20 -O3 -march=native -lnetfilter_queue -pthread -lpcre2-8 -ltins -lmnl -lnfnetlink
RUN g++ -O3 -march=native $GCC_PARAMS -o modules/proxy nfqueue/proxy.cpp -pthread -lboost_system -lboost_thread -lpcre2-8
RUN g++ binsrc/nfqueue.cpp -o modules/cppqueue -O3 -march=native -lnetfilter_queue -pthread -lpcre2-8 -ltins -lmnl -lnfnetlink
RUN g++ binsrc/proxy.cpp -o modules/proxy -O3 -march=native $GCC_PARAMS -pthread -lboost_system -lboost_thread -lpcre2-8
ADD ./backend/requirements.txt /execute/requirements.txt
RUN pip3 install --no-cache-dir -r /execute/requirements.txt

View File

@@ -48,12 +48,14 @@ int main(int argc, char *argv[])
cerr << "[fatal] [main] You must be root to run this program" << endl;
exit(EXIT_FAILURE);
}
int n_of_queue = 1;
if (argc >= 2) n_of_queue = atoi(argv[1]);
int n_of_threads = 1;
if (argc >= 2) n_of_threads = atoi(argv[1]);
if(n_of_threads <= 0) n_of_threads = 1;
if (n_of_threads % 2 != 0 ) n_of_threads++;
regex_config.reset(new regex_rules());
NFQueueSequence<filter_callback<true>> input_queues(n_of_queue);
NFQueueSequence<filter_callback<true>> input_queues(n_of_threads/2);
input_queues.start();
NFQueueSequence<filter_callback<false>> output_queues(n_of_queue);
NFQueueSequence<filter_callback<false>> output_queues(n_of_threads/2);
output_queues.start();
cout << "QUEUES INPUT " << input_queues.init() << " " << input_queues.end() << " OUTPUT " << output_queues.init() << " " << output_queues.end() << endl;

Binary file not shown.

View File

@@ -3,6 +3,7 @@ from modules.regexproxy.proxy import Filter, Proxy
import random, socket, asyncio
from base64 import b64decode
from utils.sqlite import SQLite
from utils import refresh_frontend
class STATUS:
WAIT = "wait"
@@ -129,8 +130,10 @@ class ServiceManager:
while True:
if check_port_is_open(self.proxy.public_port):
self._set_status(to)
await refresh_frontend()
await self.proxy.start(in_pause=(to==STATUS.PAUSE))
self._set_status(STATUS.STOP)
await refresh_frontend()
return
else:
await asyncio.sleep(.5)

Binary file not shown.

View File

@@ -6,16 +6,16 @@ from pydantic import BaseModel
from modules.regexproxy.utils import STATUS, ProxyManager, gen_internal_port, gen_service_id
from utils.sqlite import SQLite
from utils.models import ResetRequest, StatusMessageModel
from utils.firegextables import FiregexTables
from utils import refactor_name, refresh_frontend
app = APIRouter()
db = SQLite("regextcpproxy.db",{
db = SQLite("db/regextcpproxy.db",{
'services': {
'status': 'VARCHAR(100) NOT NULL',
'service_id': 'VARCHAR(100) PRIMARY KEY',
'internal_port': 'INT NOT NULL CHECK(internal_port > 0 and internal_port < 65536)',
'public_port': 'INT NOT NULL CHECK(internal_port > 0 and internal_port < 65536) UNIQUE',
'name': 'VARCHAR(100) NOT NULL'
'name': 'VARCHAR(100) NOT NULL UNIQUE'
},
'regexes': {
'regex': 'TEXT NOT NULL',
@@ -31,7 +31,7 @@ db = SQLite("regextcpproxy.db",{
'QUERY':[
"CREATE UNIQUE INDEX IF NOT EXISTS unique_regex_service ON regexes (regex,service_id,is_blacklist,mode,is_case_sensitive);"
]
})
})
firewall = ProxyManager(db)
@@ -39,7 +39,6 @@ async def reset(params: ResetRequest):
if not params.delete:
db.backup()
await firewall.close()
FiregexTables().reset()
if params.delete:
db.delete()
db.init()
@@ -122,18 +121,21 @@ async def get_service_by_id(service_id: str, ):
async def service_stop(service_id: str, ):
"""Request the stop of a specific service"""
await firewall.get(service_id).next(STATUS.STOP)
await refresh_frontend()
return {'status': 'ok'}
@app.get('/service/{service_id}/pause', response_model=StatusMessageModel)
async def service_pause(service_id: str, ):
"""Request the pause of a specific service"""
await firewall.get(service_id).next(STATUS.PAUSE)
await refresh_frontend()
return {'status': 'ok'}
@app.get('/service/{service_id}/start', response_model=StatusMessageModel)
async def service_start(service_id: str, ):
"""Request the start of a specific service"""
await firewall.get(service_id).next(STATUS.ACTIVE)
await refresh_frontend()
return {'status': 'ok'}
@app.get('/service/{service_id}/delete', response_model=StatusMessageModel)
@@ -142,6 +144,7 @@ async def service_delete(service_id: str, ):
db.query('DELETE FROM services WHERE service_id = ?;', service_id)
db.query('DELETE FROM regexes WHERE service_id = ?;', service_id)
await firewall.remove(service_id)
await refresh_frontend()
return {'status': 'ok'}
@@ -150,6 +153,7 @@ async def regen_service_port(service_id: str, ):
"""Request the regeneration of a the internal proxy port of a specific service"""
db.query('UPDATE services SET internal_port = ? WHERE service_id = ?;', gen_internal_port(db), service_id)
await firewall.get(service_id).update_port()
await refresh_frontend()
return {'status': 'ok'}
class ChangePortForm(BaseModel):
@@ -175,8 +179,9 @@ async def change_service_ports(service_id: str, change_port:ChangePortForm ):
query.append(service_id)
db.query(f'UPDATE services SET {sql_inj} WHERE service_id = ?;', *query)
except sqlite3.IntegrityError:
return {'status': 'Name or/and port of the service has been already assigned to another service'}
return {'status': 'Port of the service has been already assigned to another service'}
await firewall.get(service_id).update_port()
await refresh_frontend()
return {'status': 'ok'}
class RegexModel(BaseModel):
@@ -218,7 +223,7 @@ async def regex_delete(regex_id: int, ):
if len(res) != 0:
db.query('DELETE FROM regexes WHERE regex_id = ?;', regex_id)
await firewall.get(res[0]["service_id"]).update_filters()
await refresh_frontend()
return {'status': 'ok'}
@app.get('/regex/{regex_id}/enable', response_model=StatusMessageModel)
@@ -228,6 +233,7 @@ async def regex_enable(regex_id: int, ):
if len(res) != 0:
db.query('UPDATE regexes SET active=1 WHERE regex_id = ?;', regex_id)
await firewall.get(res[0]["service_id"]).update_filters()
await refresh_frontend()
return {'status': 'ok'}
@app.get('/regex/{regex_id}/disable', response_model=StatusMessageModel)
@@ -237,6 +243,7 @@ async def regex_disable(regex_id: int, ):
if len(res) != 0:
db.query('UPDATE regexes SET active=0 WHERE regex_id = ?;', regex_id)
await firewall.get(res[0]["service_id"]).update_filters()
await refresh_frontend()
return {'status': 'ok'}
class RegexAddForm(BaseModel):
@@ -259,8 +266,8 @@ async def add_new_regex(form: RegexAddForm, ):
form.service_id, form.regex, form.is_blacklist, form.mode, form.is_case_sensitive, True if form.active is None else form.active )
except sqlite3.IntegrityError:
return {'status': 'An identical regex already exists'}
await firewall.get(form.service_id).update_filters()
await refresh_frontend()
return {'status': 'ok'}
class ServiceAddForm(BaseModel):
@@ -278,14 +285,20 @@ class RenameForm(BaseModel):
@app.post('/service/{service_id}/rename', response_model=StatusMessageModel)
async def service_rename(service_id: str, form: RenameForm, ):
"""Request to change the name of a specific service"""
form.name = refactor_name(form.name)
if not form.name: return {'status': 'The name cannot be empty!'}
db.query('UPDATE services SET name=? WHERE service_id = ?;', form.name, service_id)
try:
db.query('UPDATE services SET name=? WHERE service_id = ?;', form.name, service_id)
except sqlite3.IntegrityError:
return {'status': 'The name is already used!'}
await refresh_frontend()
return {'status': 'ok'}
@app.post('/services/add', response_model=ServiceAddStatus)
async def add_new_service(form: ServiceAddForm, ):
"""Add a new service"""
serv_id = gen_service_id(db)
form.name = refactor_name(form.name)
try:
internal_port = form.internalPort if form.internalPort else gen_internal_port(db)
db.query("INSERT INTO services (name, service_id, internal_port, public_port, status) VALUES (?, ?, ?, ?, ?)",
@@ -293,5 +306,5 @@ async def add_new_service(form: ServiceAddForm, ):
except sqlite3.IntegrityError:
return {'status': 'Name or/and ports of the service has been already assigned to another service'}
await firewall.reload()
await refresh_frontend()
return {'status': 'ok', "id": serv_id }

BIN
docs/Firegex_Screenshot.jpg Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View File

@@ -1,13 +1,13 @@
{
"files": {
"main.css": "/static/css/main.166875ec.css",
"main.js": "/static/js/main.414c65b7.js",
"main.css": "/static/css/main.96ef8f18.css",
"main.js": "/static/js/main.8840c3f9.js",
"index.html": "/index.html",
"main.166875ec.css.map": "/static/css/main.166875ec.css.map",
"main.414c65b7.js.map": "/static/js/main.414c65b7.js.map"
"main.96ef8f18.css.map": "/static/css/main.96ef8f18.css.map",
"main.8840c3f9.js.map": "/static/js/main.8840c3f9.js.map"
},
"entrypoints": [
"static/css/main.166875ec.css",
"static/js/main.414c65b7.js"
"static/css/main.96ef8f18.css",
"static/js/main.8840c3f9.js"
]
}

View File

@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"><link rel="manifest" href="/site.webmanifest"><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#FFFFFFFF"/><meta name="description" content="Firegex by Pwnzer0tt1"/><title>Firegex</title><script defer="defer" src="/static/js/main.414c65b7.js"></script><link href="/static/css/main.166875ec.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"><link rel="manifest" href="/site.webmanifest"><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#FFFFFFFF"/><meta name="description" content="Firegex by Pwnzer0tt1"/><title>Firegex</title><script defer="defer" src="/static/js/main.8840c3f9.js"></script><link href="/static/css/main.96ef8f18.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>

View File

@@ -1,2 +0,0 @@
@import url(https://fonts.googleapis.com/css2?family=Lato&display=swap);.center-flex,.center-flex-row{align-items:center;display:flex;justify-content:center}.center-flex-row{flex-direction:column}.flex-spacer{flex-grow:1}.Footer_center-flex-row__Iibc4,.Footer_center-flex__mTXcH,.Footer_footer__V8Lu\+{align-items:center;display:flex;justify-content:center}.Footer_center-flex-row__Iibc4{flex-direction:column}.Footer_flex-spacer__6R1Ah{flex-grow:1}.Footer_footer__V8Lu\+{background-color:#242a33;height:150px;margin-top:50px}.Header_header__MY7fH{align-items:center;background-color:#242a33;display:flex;height:140px;justify-content:center;width:100%}.Header_logo__qeTuP{height:70%;margin-left:40px;width:200px}body{font-family:Lato,sans-serif;margin:0}.ServiceRow_center-flex-row__NF59z,.ServiceRow_center-flex__Ffq-d,.ServiceRow_row__HwgWF{align-items:center;display:flex;justify-content:center}.ServiceRow_center-flex-row__NF59z{flex-direction:column}.ServiceRow_flex-spacer__OVA44{flex-grow:1}::-webkit-scrollbar{background:#333;cursor:pointer;margin:3px;width:12px}::-webkit-scrollbar-thumb{background:#757575;border-radius:8px}.ServiceRow_row__HwgWF{border-radius:20px;margin:10px;padding:30px 0;width:95%}.ServiceRow_name__HSrHR{color:#fff;font-size:2.3em;font-weight:bolder;margin-bottom:13px;margin-right:10px}.RegexView_box__Z6\+8g{margin:5px;padding:30px}.RegexView_regex_text__YbrUl{background-color:#25262b;border-radius:8px;margin:6px;padding:6px}
/*# sourceMappingURL=main.166875ec.css.map*/

View File

@@ -1 +0,0 @@
{"version":3,"file":"static/css/main.166875ec.css","mappings":"wEAUA,8BAGE,mBAFA,aACA,sBACA,CAGF,iBAEE,sBAGF,aACE,YAZF,iFAGE,mBAFA,aACA,sBACA,CAGF,+BAEE,sBAGF,2BACE,YCnBF,uBAGI,yBAFA,aACA,eCJY,CCEhB,sBAKI,mBAFA,wBDLY,CCMZ,aAFA,aAIA,uBALA,UAKA,CAGJ,oBAGI,WADA,iBADA,WAEA,CHVJ,KAEE,4BADA,QACA,CAGF,yFAGE,mBAFA,aACA,sBACA,CAGF,mCAEE,sBAGF,+BACE,YAGF,oBAGE,gBACA,eAFA,UAAU,CADV,UAGA,CAEF,0BACE,mBACA,kBI9BF,uBAGI,mBACA,YAFA,eADA,SAGA,CAIJ,wBAKI,WAJA,gBACA,mBAEA,mBADA,iBAEA,CCbJ,uBAEI,UAAS,CADT,YACU,CAGd,6BAEI,wBHPS,CGQT,kBACA,WAHA,WAGA","sources":["index.scss","components/Footer/index.module.scss","_vars.scss","components/Header/index.module.scss","components/NFRegex/ServiceRow/index.module.scss","components/NFRegex/RegexView/index.module.scss"],"sourcesContent":["\n@use \"vars\" as *;\n\n@import url('https://fonts.googleapis.com/css2?family=Lato&display=swap');\n\nbody {\n margin: 0;\n font-family: 'Lato', sans-serif;\n}\n\n.center-flex{\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n.center-flex-row{\n @extend .center-flex;\n flex-direction: column;\n}\n\n.flex-spacer{\n flex-grow: 1;\n}\n\n::-webkit-scrollbar {\n width: 12px;\n margin:3px;\n background: #333;\n cursor: pointer;\n}\n::-webkit-scrollbar-thumb {\n background: #757575;\n border-radius: 8px;\n}","@use \"../../vars\" as *;\r\n@use \"../../index.scss\" as *;\r\n\r\n.footer{\r\n height: 150px;\r\n margin-top: 50px;\r\n background-color: $primary_color;\r\n @extend .center-flex;\r\n}","\r\n$primary_color: #242a33;\r\n$second_color: #1A1B1E;\r\n$third_color:#25262b;\r\n","\r\n@use \"../../vars\" as *;\r\n\r\n.header{\r\n width: 100%;\r\n height: 140px;\r\n background-color: $primary_color;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.logo{\r\n width: 200px;\r\n margin-left: 40px;\r\n height: 70%;\r\n}","\r\n@use \"../../../index.scss\" as *;\r\n\r\n.row{\r\n width: 95%;\r\n padding: 30px 0px;\r\n border-radius: 20px;\r\n margin: 10px;\r\n @extend .center-flex;\r\n}\r\n\r\n.name{\r\n font-size: 2.3em;\r\n font-weight: bolder;\r\n margin-right: 10px;\r\n margin-bottom: 13px;\r\n color:#FFF;\r\n}","\r\n@use \"../../../vars\" as *;\r\n\r\n.box{\r\n padding:30px;\r\n margin:5px;\r\n}\r\n\r\n.regex_text{\r\n padding: 6px;\r\n background-color: $third_color;\r\n border-radius: 8px;\r\n margin: 6px;\r\n}"],"names":[],"sourceRoot":""}

View File

@@ -0,0 +1,2 @@
@import url(https://fonts.googleapis.com/css2?family=Lato&display=swap);.center-flex,.center-flex-row{align-items:center;display:flex;justify-content:center}.center-flex-row{flex-direction:column}.flex-spacer{flex-grow:1}.Footer_center-flex-row__Iibc4,.Footer_center-flex__mTXcH,.Footer_footer__V8Lu\+{align-items:center;display:flex;justify-content:center}.Footer_center-flex-row__Iibc4{flex-direction:column}.Footer_flex-spacer__6R1Ah{flex-grow:1}.Footer_footer__V8Lu\+{background-color:#242a33;margin-top:50px}.Header_center-flex-row__IvRvv,.Header_center-flex__DB4BQ,.Header_divlogo__5tqvT,.Header_navbtn__0vn69{align-items:center;display:flex;justify-content:center}.Header_center-flex-row__IvRvv{flex-direction:column}.Header_flex-spacer__lqMXa{flex-grow:1}.Header_header__MY7fH{align-items:center;background-color:#242a33;display:flex;justify-content:center;width:100%}.Header_divlogo__5tqvT{cursor:pointer;height:100%;width:110px}.Header_navbtn__0vn69{margin:0;width:30px}.ServiceRow_center-flex-row__NF59z,.ServiceRow_center-flex__Ffq-d,.ServiceRow_row__HwgWF{align-items:center;display:flex;justify-content:center}.ServiceRow_center-flex-row__NF59z{flex-direction:column}.ServiceRow_flex-spacer__OVA44{flex-grow:1}.ServiceRow_row__HwgWF{border-radius:20px;margin:10px;padding:30px 0;width:95%}.ServiceRow_name__HSrHR{color:#fff;font-size:2.3em;font-weight:bolder;margin-bottom:13px;margin-right:10px}body{font-family:Lato,sans-serif;margin:0}.ServiceRow_center-flex-row__KpTZC,.ServiceRow_center-flex__OM87P,.ServiceRow_row__q7RbE{align-items:center;display:flex;justify-content:center}.ServiceRow_center-flex-row__KpTZC{flex-direction:column}.ServiceRow_flex-spacer__5N54i{flex-grow:1}::-webkit-scrollbar{background:#333;cursor:pointer;margin:3px;width:12px}::-webkit-scrollbar-thumb{background:#757575;border-radius:8px}.ServiceRow_row__q7RbE{border-radius:20px;margin:10px;padding:30px 0;width:95%}.ServiceRow_name__Qefq\+{color:#fff;font-size:2.3em;font-weight:bolder;margin-bottom:13px;margin-right:10px}.RegexView_box__IDvxB{margin:5px;padding:30px}.RegexView_regex_text__pFvPS{background-color:#25262b;border-radius:8px;margin:6px;padding:6px}
/*# sourceMappingURL=main.96ef8f18.css.map*/

View File

@@ -0,0 +1 @@
{"version":3,"file":"static/css/main.96ef8f18.css","mappings":"wEAUA,8BAGE,mBAFA,aACA,sBACA,CAGF,iBAEE,sBAGF,aACE,YAZF,iFAGE,mBAFA,aACA,sBACA,CAGF,+BAEE,sBAGF,2BACE,YCnBF,uBAEI,yBADA,eCHY,CFShB,uGAGE,mBAFA,aACA,sBACA,CAGF,+BAEE,sBAGF,2BACE,YGlBF,sBAII,mBAFA,wBDLY,CCMZ,aAEA,uBAJA,UAIA,CAGJ,uBAGI,eADA,YADA,WAEA,CAIJ,sBAGI,QAAO,CADP,UACQ,CHZZ,yFAGE,mBAFA,aACA,sBACA,CAGF,mCAEE,sBAGF,+BACE,YInBF,uBAGI,mBACA,YAFA,eADA,SAGA,CAIJ,wBAKI,WAJA,gBACA,mBAEA,mBADA,iBAEA,CJXJ,KAEE,4BADA,QACA,CAGF,yFAGE,mBAFA,aACA,sBACA,CAGF,mCAEE,sBAGF,+BACE,YAGF,oBAGE,gBACA,eAFA,UAAU,CADV,UAGA,CAEF,0BACE,mBACA,kBK9BF,uBAGI,mBACA,YAFA,eADA,SAGA,CAIJ,yBAKI,WAJA,gBACA,mBAEA,mBADA,iBAEA,CCbJ,sBAEI,UAAS,CADT,YACU,CAGd,6BAEI,wBJPS,CIQT,kBACA,WAHA,WAGA","sources":["index.scss","components/Footer/index.module.scss","_vars.scss","components/Header/index.module.scss","components/NFRegex/ServiceRow/index.module.scss","components/RegexProxy/ServiceRow/ServiceRow.module.scss","components/RegexView/index.module.scss"],"sourcesContent":["\n@use \"vars\" as *;\n\n@import url('https://fonts.googleapis.com/css2?family=Lato&display=swap');\n\nbody {\n margin: 0;\n font-family: 'Lato', sans-serif;\n}\n\n.center-flex{\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n.center-flex-row{\n @extend .center-flex;\n flex-direction: column;\n}\n\n.flex-spacer{\n flex-grow: 1;\n}\n\n::-webkit-scrollbar {\n width: 12px;\n margin:3px;\n background: #333;\n cursor: pointer;\n}\n::-webkit-scrollbar-thumb {\n background: #757575;\n border-radius: 8px;\n}","@use \"../../vars\" as *;\r\n@use \"../../index.scss\" as *;\r\n\r\n.footer{\r\n margin-top: 50px;\r\n background-color: $primary_color;\r\n @extend .center-flex;\r\n}","\r\n$primary_color: #242a33;\r\n$second_color: #1A1B1E;\r\n$third_color:#25262b;\r\n","\r\n@use \"../../vars\" as *;\r\n@use \"../../index.scss\" as *;\r\n\r\n.header{\r\n width: 100%;\r\n background-color: $primary_color;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.divlogo{\r\n width: 110px;\r\n height: 100%;\r\n cursor: pointer;\r\n @extend .center-flex;\r\n}\r\n\r\n.navbtn{\r\n @extend .center-flex;\r\n width: 30px;\r\n margin:0;\r\n}","\r\n@use \"../../../index.scss\" as *;\r\n\r\n.row{\r\n width: 95%;\r\n padding: 30px 0px;\r\n border-radius: 20px;\r\n margin: 10px;\r\n @extend .center-flex;\r\n}\r\n\r\n.name{\r\n font-size: 2.3em;\r\n font-weight: bolder;\r\n margin-right: 10px;\r\n margin-bottom: 13px;\r\n color:#FFF;\r\n}","\r\n@use \"../../../index.scss\" as *;\r\n\r\n.row{\r\n width: 95%;\r\n padding: 30px 0px;\r\n border-radius: 20px;\r\n margin: 10px;\r\n @extend .center-flex;\r\n}\r\n\r\n.name{\r\n font-size: 2.3em;\r\n font-weight: bolder;\r\n margin-right: 10px;\r\n margin-bottom: 13px;\r\n color:#FFF;\r\n}","\r\n@use \"../../vars\" as *;\r\n\r\n.box{\r\n padding:30px;\r\n margin:5px;\r\n}\r\n\r\n.regex_text{\r\n padding: 6px;\r\n background-color: $third_color;\r\n border-radius: 8px;\r\n margin: 6px;\r\n}"],"names":[],"sourceRoot":""}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -2,13 +2,15 @@ import { Button, Group, Loader, LoadingOverlay, Notification, Space, PasswordInp
import { useForm } from '@mantine/hooks';
import React, { useEffect, useState } from 'react';
import { ImCross } from 'react-icons/im';
import { Navigate, Outlet, Route, Routes } from 'react-router-dom';
import { Outlet, Route, Routes } from 'react-router-dom';
import MainLayout from './components/MainLayout';
import { PasswordSend, ServerStatusResponse } from './js/models';
import { errorNotify, fireUpdateRequest, getstatus, login, setpassword } from './js/utils';
import { errorNotify, fireUpdateRequest, getstatus, HomeRedirector, login, setpassword } from './js/utils';
import NFRegex from './pages/NFRegex.tsx';
import ServiceDetails from './pages/NFRegex.tsx/ServiceDetails';
import io from 'socket.io-client';
import RegexProxy from './pages/RegexProxy';
import ServiceDetailsNFRegex from './pages/NFRegex.tsx/ServiceDetails';
import ServiceDetailsProxyRegex from './pages/RegexProxy/ServiceDetails';
const socket = io({transports: ["websocket", "polling"], path:"/sock" });
@@ -146,9 +148,12 @@ function App() {
return <Routes>
<Route element={<MainLayout><Outlet /></MainLayout>}>
<Route path="nfregex" element={<NFRegex><Outlet /></NFRegex>} >
<Route path=":srv" element={<ServiceDetails />} />
<Route path=":srv" element={<ServiceDetailsNFRegex />} />
</Route>
<Route path="*" element={<Navigate to="/nfregex" />} />
<Route path="regexproxy" element={<RegexProxy><Outlet /></RegexProxy>} >
<Route path=":srv" element={<ServiceDetailsProxyRegex />} />
</Route>
<Route path="*" element={<HomeRedirector />} />
</Route>
</Routes>
}else{

View File

@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import { ActionIcon, Divider, Image, Menu, Tooltip, FloatingTooltip, MediaQuery, Burger, Space, Header } from '@mantine/core';
import style from "./index.module.scss";
import { errorNotify, gatmainpath, logout } from '../../js/utils';
import { errorNotify, getmainpath, logout } from '../../js/utils';
import { AiFillHome } from "react-icons/ai"
import { useNavigate } from 'react-router-dom';
import { FaLock } from 'react-icons/fa';
@@ -24,7 +24,7 @@ function HeaderPage({navOpen, setNav, ...other}: { navOpen: boolean, setNav:Reac
}
const go_to_home = () => {
navigator(`/${gatmainpath()}`)
navigator(`/${getmainpath()}`)
}
const [changePasswordModal, setChangePasswordModal] = useState(false);

View File

@@ -1,15 +1,24 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { Container, Space } from '@mantine/core';
import { AppShell } from '@mantine/core';
import NavBar from './NavBar';
import FooterPage from './Footer';
import HeaderPage from './Header';
import { getmainpath } from '../js/utils';
import { useLocation } from 'react-router-dom';
function MainLayout({ children }:{ children:any }) {
const [opened, setOpened] = useState(false);
const location = useLocation()
useEffect(()=>{
if (location.pathname !== "/"){
sessionStorage.setItem('home_section', getmainpath())
}
},[location.pathname])
return <>
<AppShell

View File

@@ -3,7 +3,7 @@ import React from "react";
import { IoMdGitNetwork } from "react-icons/io";
import { MdTransform } from "react-icons/md";
import { useNavigate } from "react-router-dom";
import { gatmainpath } from "../../js/utils";
import { getmainpath } from "../../js/utils";
import { GrDirections } from "react-icons/gr";
function NavBarButton({ navigate, closeNav, name, icon, color, disabled }:
@@ -17,7 +17,7 @@ function NavBarButton({ navigate, closeNav, name, icon, color, disabled }:
borderRadius: theme.radius.sm,
opacity: disabled ? 0.4 : 1,
color: theme.colorScheme === 'dark' ? theme.colors.dark[0] : theme.black,
backgroundColor:(navigate===gatmainpath()?(theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[0]):"transparent"),
backgroundColor:(navigate===getmainpath()?(theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[0]):"transparent"),
'&:hover': {
backgroundColor:
theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[0],

View File

@@ -1,7 +1,7 @@
import { Button, Group, NumberInput, Space, TextInput, Notification, Modal, Switch } from '@mantine/core';
import { useForm } from '@mantine/hooks';
import React, { useState } from 'react';
import { fireUpdateRequest, okNotify } from '../../js/utils';
import { okNotify } from '../../js/utils';
import { ImCross } from "react-icons/im"
import { regexproxy } from './utils';
@@ -45,7 +45,6 @@ function AddNewService({ opened, onClose }:{ opened:boolean, onClose:()=>void })
if (res.status === "ok"){
setSubmitLoading(false)
close();
fireUpdateRequest();
if (autostart) regexproxy.servicestart(res.id)
okNotify(`Service ${name} has been added`, `Successfully added ${res.id} with port ${port}`)
}else{

View File

@@ -4,7 +4,7 @@ import React, { useEffect, useState } from 'react';
import { ImCross } from "react-icons/im"
import { FaLongArrowAltDown } from 'react-icons/fa';
import { regexproxy, Service } from '../utils';
import { fireUpdateRequest, okNotify } from '../../../js/utils';
import { okNotify } from '../../../js/utils';
type InputForm = {
internalPort:number,
@@ -43,7 +43,6 @@ function ChangePortModal({ service, opened, onClose }:{ service:Service, opened:
if (!res){
setSubmitLoading(false)
close();
fireUpdateRequest();
okNotify(`Internal port on ${service.name} service has changed in ${data.internalPort}`, `Successfully changed internal port of service with id ${service.id}`)
}else{
setSubmitLoading(false)

View File

@@ -1,7 +1,7 @@
import { Button, Group, Space, TextInput, Notification, Modal } from '@mantine/core';
import { useForm } from '@mantine/hooks';
import React, { useEffect, useState } from 'react';
import { fireUpdateRequest, okNotify } from '../../../js/utils';
import { okNotify } from '../../../js/utils';
import { ImCross } from "react-icons/im"
import { regexproxy, Service } from '../utils';
@@ -29,7 +29,6 @@ function RenameForm({ opened, onClose, service }:{ opened:boolean, onClose:()=>v
if (!res){
setSubmitLoading(false)
close();
fireUpdateRequest();
okNotify(`Service ${service.name} has been renamed in ${ name }`, `Successfully renamed service on port ${service.public_port}`)
}else{
setSubmitLoading(false)

View File

@@ -1,5 +1,5 @@
@use "../../index.scss" as *;
@use "../../../index.scss" as *;
.row{
width: 95%;

View File

@@ -4,7 +4,7 @@ import { FaPause, FaPlay, FaStop } from 'react-icons/fa';
import { MdOutlineArrowForwardIos } from "react-icons/md"
import style from "./ServiceRow.module.scss";
import YesNoModal from '../../YesNoModal';
import { errorNotify, fireUpdateRequest, okNotify } from '../../../js/utils';
import { errorNotify, okNotify } from '../../../js/utils';
import { BsArrowRepeat, BsTrashFill } from 'react-icons/bs';
import { TbNumbers } from 'react-icons/tb';
import { BiRename } from 'react-icons/bi'
@@ -36,7 +36,6 @@ function ServiceRow({ service, onClick }:{ service:Service, onClick?:()=>void })
await regexproxy.servicestop(service.id).then(res => {
if(!res){
okNotify(`Service ${service.id} stopped successfully!`,`The service ${service.name} has been stopped!`)
fireUpdateRequest();
}else{
errorNotify(`An error as occurred during the stopping of the service ${service.id}`,`Error: ${res}`)
}
@@ -51,7 +50,6 @@ function ServiceRow({ service, onClick }:{ service:Service, onClick?:()=>void })
await regexproxy.servicestart(service.id).then(res => {
if(!res){
okNotify(`Service ${service.id} started successfully!`,`The service ${service.name} has been started!`)
fireUpdateRequest();
}else{
errorNotify(`An error as occurred during the starting of the service ${service.id}`,`Error: ${res}`)
}
@@ -66,7 +64,6 @@ function ServiceRow({ service, onClick }:{ service:Service, onClick?:()=>void })
await regexproxy.servicepause(service.id).then(res => {
if(!res){
okNotify(`Service ${service.id} paused successfully!`,`The service ${service.name} has been paused (Transparent mode)!`)
fireUpdateRequest();
}else{
errorNotify(`An error as occurred during the pausing of the service ${service.id}`,`Error: ${res}`)
}
@@ -81,7 +78,6 @@ function ServiceRow({ service, onClick }:{ service:Service, onClick?:()=>void })
regexproxy.servicedelete(service.id).then(res => {
if (!res){
okNotify("Service delete complete!",`The service ${service.id} has been deleted!`)
fireUpdateRequest();
}else
errorNotify("An error occurred while deleting a service",`Error: ${res}`)
}).catch(err => {
@@ -94,7 +90,6 @@ function ServiceRow({ service, onClick }:{ service:Service, onClick?:()=>void })
regexproxy.serviceregenport(service.id).then(res => {
if (!res){
okNotify("Service port regeneration completed!",`The service ${service.id} has changed the internal port!`)
fireUpdateRequest();
}else
errorNotify("An error occurred while changing the internal service port",`Error: ${res}`)
}).catch(err => {
@@ -108,14 +103,14 @@ function ServiceRow({ service, onClick }:{ service:Service, onClick?:()=>void })
<MediaQuery smallerThan="md" styles={{ display: 'none' }}><div>
<div className="center-flex-row">
<div className="center-flex"><Title className={style.name}>{service.name}</Title> <Badge size="xl" gradient={{ from: 'indigo', to: 'cyan' }} variant="gradient">:{service.public_port}</Badge></div>
<Badge color={status_color} size="xl" radius="md">{service.internal_port} {"->"} {service.public_port}</Badge>
<Badge color={status_color} size="lg" radius="md">{service.internal_port} {"->"} {service.public_port}</Badge>
</div>
</div></MediaQuery>
<MediaQuery largerThan="md" styles={{ display: 'none' }}><div>
<div className="center-flex">
<div className="center-flex"><Title className={style.name}>{service.name}</Title> <Badge size="xl" gradient={{ from: 'indigo', to: 'cyan' }} variant="gradient">:{service.public_port}</Badge></div>
<Space w="xl" />
<Badge color={status_color} size="xl" radius="md">{service.internal_port} {"->"} {service.public_port}</Badge>
<Badge color={status_color} size="lg" radius="md">{service.internal_port} {"->"} {service.public_port}</Badge>
</div>
</div></MediaQuery>
@@ -133,9 +128,9 @@ function ServiceRow({ service, onClick }:{ service:Service, onClick?:()=>void })
</MediaQuery>
<div className="center-flex-row">
<Badge style={{marginBottom:"20px"}} color={status_color} radius="sm" size="xl" variant="filled">Status: <u>{service.status}</u></Badge>
<Badge style={{marginBottom:"8px"}}color="violet" radius="sm" size="lg" variant="filled">Regex: {service.n_regex}</Badge>
<Badge color="yellow" radius="sm" size="lg" variant="filled">Connections Blocked: {service.n_packets}</Badge>
<Badge style={{marginBottom:"20px"}} color={status_color} radius="sm" size="lg" variant="filled">Status: <u>{service.status}</u></Badge>
<Badge style={{marginBottom:"8px"}}color="violet" radius="sm" size="md" variant="filled">Regex: {service.n_regex}</Badge>
<Badge color="yellow" radius="sm" size="md" variant="filled">Connections Blocked: {service.n_packets}</Badge>
</div>
<MediaQuery largerThan="md" styles={{ display: 'none' }}>
<div className='flex-spacer' />
@@ -170,8 +165,7 @@ function ServiceRow({ service, onClick }:{ service:Service, onClick?:()=>void })
</Tooltip>:
<Tooltip label={service.status === "stop"?"Start in pause mode":"Pause service"} zIndex={0} transition="pop" transitionDuration={200} /*openDelay={500}*/ transitionTimingFunction="ease" color={service.status === "stop"?"cyan":"red"}>
<ActionIcon color={service.status === "stop"?"cyan":"red"} loading={buttonLoading}
onClick={pauseService} size="xl" radius="md" variant="filled"
/*disabled={service.status === "stop"}*/>
onClick={pauseService} size="xl" radius="md" variant="filled">
<FaPause size="20px" />
</ActionIcon>
</Tooltip>

View File

@@ -1,6 +1,7 @@
import { showNotification } from "@mantine/notifications";
import { ImCross } from "react-icons/im";
import { TiTick } from "react-icons/ti"
import { Navigate } from "react-router-dom";
import { nfregex } from "../components/NFRegex/utils";
import { regexproxy } from "../components/RegexProxy/utils";
import { ChangePassword, IpInterface, LoginResponse, PasswordSend, ServerResponse, ServerResponseToken, ServerStatusResponse } from "./models";
@@ -52,20 +53,26 @@ export async function postapi(path:string,data:any,is_form:boolean=false):Promis
});
}
export function gatmainpath(){
export function getmainpath(){
const paths = window.location.pathname.split("/")
if (paths.length > 1) return paths[1]
return ""
}
export function getapiobject(){
switch(gatmainpath()){
switch(getmainpath()){
case "nfregex":
return nfregex
case "regexproxy":
return regexproxy
}
throw 'No api for this tool!';
throw new Error('No api for this tool!');
}
export function HomeRedirector(){
const section = sessionStorage.getItem("home_section")
const path = section?`/${section}`:`/nfqueue`
return <Navigate to={path} />
}
export function fireUpdateRequest(){

View File

@@ -10,7 +10,7 @@ import { errorNotify, eventUpdateName, fireUpdateRequest } from '../../js/utils'
import { useWindowEvent } from '@mantine/hooks';
import { RegexFilter } from '../../js/models';
function ServiceDetails() {
function ServiceDetailsNFRegex() {
const {srv} = useParams()
const [serviceInfo, setServiceInfo] = useState<Service>({
service_id: "",
@@ -81,4 +81,4 @@ function ServiceDetails() {
</>
}
export default ServiceDetails;
export default ServiceDetailsNFRegex;

View File

@@ -10,15 +10,15 @@ import ServiceRow from '../../components/RegexProxy/ServiceRow';
import AddNewRegex from '../../components/AddNewRegex';
import RegexView from '../../components/RegexView';
function ServiceDetails() {
const {srv_id} = useParams()
function ServiceDetailsProxyRegex() {
const {srv} = useParams()
const [serviceInfo, setServiceInfo] = useState<Service>({
id:srv_id?srv_id:"",
id:srv?srv:"",
internal_port:0,
n_packets:0,
n_regex:0,
name:srv_id?srv_id:"",
name:srv?srv:"",
public_port:0,
status:"🤔"
})
@@ -29,9 +29,9 @@ function ServiceDetails() {
const closeModal = () => {setOpen(false);updateInfo();}
const updateInfo = async () => {
if (!srv_id) return
if (!srv) return
let error = false;
await regexproxy.serviceinfo(srv_id).then(res => {
await regexproxy.serviceinfo(srv).then(res => {
setServiceInfo(res)
}).catch(
err =>{
@@ -39,10 +39,10 @@ function ServiceDetails() {
navigator("/")
})
if (error) return
await regexproxy.serviceregexes(srv_id).then(res => {
await regexproxy.serviceregexes(srv).then(res => {
setRegexesList(res)
}).catch(
err => errorNotify(`Updater for ${srv_id} service failed [Regex list]!`, err.toString())
err => errorNotify(`Updater for ${srv} service failed [Regex list]!`, err.toString())
)
setLoader(false)
}
@@ -76,10 +76,10 @@ function ServiceDetails() {
</Grid>
}
{srv_id?<AddNewRegex opened={open} onClose={closeModal} service={srv_id} />:null}
{srv?<AddNewRegex opened={open} onClose={closeModal} service={srv} />:null}
</div>
}
export default ServiceDetails;
export default ServiceDetailsProxyRegex;

View File

@@ -47,7 +47,7 @@ function RegexProxy({ children }: { children: any }) {
return <>
<Space h="sm" />
<div className='center-flex'>
<Title order={4}>Netfilter Regex</Title>
<Title order={4}>TCP Proxy Regex Filter (IPv4 Only)</Title>
<div className='flex-spacer' />
<Badge size="sm" color="green" variant="filled">Services: {generalStats.services}</Badge>
<Space w="xs" />

View File

@@ -54,7 +54,7 @@ services:
network_mode: "host"
environment:
- PORT={args.port}
- NTHREADS={args.thread_per_queue}
- NTHREADS={args.threads}
volumes:
- /execute/db
cap_add:
@@ -79,7 +79,7 @@ services:
- {args.port}:{args.port}
environment:
- PORT={args.port}
- NTHREADS={args.thread_per_queue}
- NTHREADS={args.threads}
volumes:
- /execute/db
cap_add: