pushed edits

This commit is contained in:
Domingo Dirutigliano
2025-02-02 22:27:12 +01:00
parent 732b68ba82
commit ec279a4fc5
13 changed files with 32 additions and 30 deletions

1
.gitignore vendored
View File

@@ -19,6 +19,7 @@
/frontend/dist/ /frontend/dist/
/frontend/dist/** /frontend/dist/**
/backend/modules/cppqueue /backend/modules/cppqueue
/backend/binsrc/cppqueue
/backend/modules/proxy /backend/modules/proxy
docker-compose.yml docker-compose.yml
firegex-compose.yml firegex-compose.yml

View File

@@ -34,7 +34,14 @@ async def lifespan(app):
yield yield
await shutdown_main() await shutdown_main()
app = FastAPI(debug=DEBUG, redoc_url=None, lifespan=lifespan) app = FastAPI(
debug=DEBUG,
redoc_url=None,
lifespan=lifespan,
docs_url="/api/docs",
title="Firegex API",
version=API_VERSION,
)
utils.socketio = SocketManager(app, "/sock", socketio_path="") utils.socketio = SocketManager(app, "/sock", socketio_path="")
if DEBUG: if DEBUG:
@@ -183,9 +190,9 @@ if __name__ == '__main__':
os.chdir(os.path.dirname(os.path.realpath(__file__))) os.chdir(os.path.dirname(os.path.realpath(__file__)))
uvicorn.run( uvicorn.run(
"app:app", "app:app",
host="::" if DEBUG else None, host=None, #"::" if DEBUG else None,
port=FIREGEX_PORT, port=FIREGEX_PORT,
reload=DEBUG, reload=False,#DEBUG,
access_log=True, access_log=True,
workers=1, # Multiple workers will cause a crash due to the creation workers=1, # Multiple workers will cause a crash due to the creation
# of multiple processes with separated memory # of multiple processes with separated memory

View File

@@ -7,7 +7,6 @@
using namespace std; using namespace std;
#ifndef REGEX_FILTER_HPP #ifndef REGEX_FILTER_HPP
#define REGEX_FILTER_HPP #define REGEX_FILTER_HPP
@@ -20,8 +19,8 @@ struct decoded_regex {
}; };
struct regex_ruleset { struct regex_ruleset {
hs_database_t* hs_db; hs_database_t* hs_db = nullptr;
char** regexes; char** regexes = nullptr;
}; };
decoded_regex decode_regex(string regex){ decoded_regex decode_regex(string regex){
@@ -46,7 +45,7 @@ decoded_regex decode_regex(string regex){
} }
decoded_regex ruleset{ decoded_regex ruleset{
regex: expr, regex: expr,
direction: regex[1] == 'C'? CTOS : STOC, direction: regex[1] == 'C' ? CTOS : STOC,
is_case_sensitive: regex[0] == '1' is_case_sensitive: regex[0] == '1'
}; };
return ruleset; return ruleset;
@@ -66,9 +65,11 @@ class RegexRules{
void free_dbs(){ void free_dbs(){
if (output_ruleset.hs_db != nullptr){ if (output_ruleset.hs_db != nullptr){
hs_free_database(output_ruleset.hs_db); hs_free_database(output_ruleset.hs_db);
output_ruleset.hs_db = nullptr;
} }
if (input_ruleset.hs_db != nullptr){ if (input_ruleset.hs_db != nullptr){
hs_free_database(input_ruleset.hs_db); hs_free_database(input_ruleset.hs_db);
input_ruleset.hs_db = nullptr;
} }
} }

Binary file not shown.

View File

@@ -12,7 +12,6 @@ class RegexFilter:
def __init__( def __init__(
self, regex, self, regex,
is_case_sensitive=True, is_case_sensitive=True,
is_blacklist=True,
input_mode=False, input_mode=False,
output_mode=False, output_mode=False,
blocked_packets=0, blocked_packets=0,
@@ -21,7 +20,6 @@ class RegexFilter:
): ):
self.regex = regex self.regex = regex
self.is_case_sensitive = is_case_sensitive self.is_case_sensitive = is_case_sensitive
self.is_blacklist = is_blacklist
if input_mode == output_mode: if input_mode == output_mode:
input_mode = output_mode = True # (False, False) == (True, True) input_mode = output_mode = True # (False, False) == (True, True)
self.input_mode = input_mode self.input_mode = input_mode
@@ -35,7 +33,7 @@ class RegexFilter:
def from_regex(cls, regex:Regex, update_func = None): def from_regex(cls, regex:Regex, update_func = None):
return cls( return cls(
id=regex.id, regex=regex.regex, is_case_sensitive=regex.is_case_sensitive, id=regex.id, regex=regex.regex, is_case_sensitive=regex.is_case_sensitive,
is_blacklist=regex.is_blacklist, blocked_packets=regex.blocked_packets, blocked_packets=regex.blocked_packets,
input_mode = regex.mode in ["C","B"], output_mode=regex.mode in ["S","B"], input_mode = regex.mode in ["C","B"], output_mode=regex.mode in ["S","B"],
update_func = update_func update_func = update_func
) )
@@ -47,9 +45,9 @@ class RegexFilter:
re.compile(self.regex) # raise re.error if it's invalid! re.compile(self.regex) # raise re.error if it's invalid!
case_sensitive = "1" if self.is_case_sensitive else "0" case_sensitive = "1" if self.is_case_sensitive else "0"
if self.input_mode: if self.input_mode:
yield case_sensitive + "C" + self.regex.hex() if self.is_blacklist else case_sensitive + "c"+ self.regex.hex() yield case_sensitive + "C" + self.regex.hex()
if self.output_mode: if self.output_mode:
yield case_sensitive + "S" + self.regex.hex() if self.is_blacklist else case_sensitive + "s"+ self.regex.hex() yield case_sensitive + "S" + self.regex.hex()
async def update(self): async def update(self):
if self.update_func: if self.update_func:

View File

@@ -15,11 +15,10 @@ class Service:
class Regex: class Regex:
def __init__(self, regex_id: int, regex: bytes, mode: str, service_id: str, is_blacklist: bool, blocked_packets: int, is_case_sensitive: bool, active: bool, **other): def __init__(self, regex_id: int, regex: bytes, mode: str, service_id: str, blocked_packets: int, is_case_sensitive: bool, active: bool, **other):
self.regex = regex self.regex = regex
self.mode = mode self.mode = mode
self.service_id = service_id self.service_id = service_id
self.is_blacklist = is_blacklist
self.blocked_packets = blocked_packets self.blocked_packets = blocked_packets
self.id = regex_id self.id = regex_id
self.is_case_sensitive = is_case_sensitive self.is_case_sensitive = is_case_sensitive

View File

@@ -28,7 +28,6 @@ class RegexModel(BaseModel):
mode:str mode:str
id:int id:int
service_id:str service_id:str
is_blacklist: bool
n_packets:int n_packets:int
is_case_sensitive:bool is_case_sensitive:bool
active:bool active:bool
@@ -38,7 +37,6 @@ class RegexAddForm(BaseModel):
regex: str regex: str
mode: str mode: str
active: bool|None = None active: bool|None = None
is_blacklist: bool
is_case_sensitive: bool is_case_sensitive: bool
class ServiceAddForm(BaseModel): class ServiceAddForm(BaseModel):
@@ -66,7 +64,6 @@ db = SQLite('db/nft-regex.db', {
'regex': 'TEXT NOT NULL', 'regex': 'TEXT NOT NULL',
'mode': 'VARCHAR(1) NOT NULL CHECK (mode IN ("C", "S", "B"))', # C = to the client, S = to the server, B = both 'mode': 'VARCHAR(1) NOT NULL CHECK (mode IN ("C", "S", "B"))', # C = to the client, S = to the server, B = both
'service_id': 'VARCHAR(100) NOT NULL', 'service_id': 'VARCHAR(100) NOT NULL',
'is_blacklist': 'BOOLEAN NOT NULL CHECK (is_blacklist IN (0, 1))',
'blocked_packets': 'INTEGER UNSIGNED NOT NULL DEFAULT 0', 'blocked_packets': 'INTEGER UNSIGNED NOT NULL DEFAULT 0',
'regex_id': 'INTEGER PRIMARY KEY', 'regex_id': 'INTEGER PRIMARY KEY',
'is_case_sensitive' : 'BOOLEAN NOT NULL CHECK (is_case_sensitive IN (0, 1))', 'is_case_sensitive' : 'BOOLEAN NOT NULL CHECK (is_case_sensitive IN (0, 1))',
@@ -75,7 +72,7 @@ db = SQLite('db/nft-regex.db', {
}, },
'QUERY':[ 'QUERY':[
"CREATE UNIQUE INDEX IF NOT EXISTS unique_services ON services (port, ip_int, proto);", "CREATE UNIQUE INDEX IF NOT EXISTS unique_services ON services (port, ip_int, proto);",
"CREATE UNIQUE INDEX IF NOT EXISTS unique_regex_service ON regexes (regex,service_id,is_blacklist,mode,is_case_sensitive);" "CREATE UNIQUE INDEX IF NOT EXISTS unique_regex_service ON regexes (regex,service_id,mode,is_case_sensitive);"
] ]
}) })
@@ -194,7 +191,7 @@ async def get_service_regexe_list(service_id: str):
raise HTTPException(status_code=400, detail="This service does not exists!") raise HTTPException(status_code=400, detail="This service does not exists!")
return db.query(""" return db.query("""
SELECT SELECT
regex, mode, regex_id `id`, service_id, is_blacklist, regex, mode, regex_id `id`, service_id,
blocked_packets n_packets, is_case_sensitive, active blocked_packets n_packets, is_case_sensitive, active
FROM regexes WHERE service_id = ?; FROM regexes WHERE service_id = ?;
""", service_id) """, service_id)
@@ -204,7 +201,7 @@ async def get_regex_by_id(regex_id: int):
"""Get regex info using his id""" """Get regex info using his id"""
res = db.query(""" res = db.query("""
SELECT SELECT
regex, mode, regex_id `id`, service_id, is_blacklist, regex, mode, regex_id `id`, service_id,
blocked_packets n_packets, is_case_sensitive, active blocked_packets n_packets, is_case_sensitive, active
FROM regexes WHERE `id` = ?; FROM regexes WHERE `id` = ?;
""", regex_id) """, regex_id)
@@ -251,8 +248,8 @@ async def add_new_regex(form: RegexAddForm):
except Exception: except Exception:
raise HTTPException(status_code=400, detail="Invalid regex") raise HTTPException(status_code=400, detail="Invalid regex")
try: try:
db.query("INSERT INTO regexes (service_id, regex, is_blacklist, mode, is_case_sensitive, active ) VALUES (?, ?, ?, ?, ?, ?);", db.query("INSERT INTO regexes (service_id, regex, mode, is_case_sensitive, active ) VALUES (?, ?, ?, ?, ?);",
form.service_id, form.regex, form.is_blacklist, form.mode, form.is_case_sensitive, True if form.active is None else form.active ) form.service_id, form.regex, form.mode, form.is_case_sensitive, True if form.active is None else form.active )
except sqlite3.IntegrityError: except sqlite3.IntegrityError:
raise HTTPException(status_code=400, detail="An identical regex already exists") raise HTTPException(status_code=400, detail="An identical regex already exists")

View File

@@ -19,7 +19,7 @@ ON_DOCKER = "DOCKER" in sys.argv
DEBUG = "DEBUG" in sys.argv DEBUG = "DEBUG" in sys.argv
FIREGEX_PORT = int(os.getenv("PORT","4444")) FIREGEX_PORT = int(os.getenv("PORT","4444"))
JWT_ALGORITHM: str = "HS256" JWT_ALGORITHM: str = "HS256"
API_VERSION = "2.2.0" API_VERSION = "3.0.0"
PortType = Annotated[int, Path(gt=0, lt=65536)] PortType = Annotated[int, Path(gt=0, lt=65536)]

View File

@@ -36,7 +36,6 @@ export type RegexFilter = {
id:number, id:number,
service_id:string, service_id:string,
regex:string regex:string
is_blacklist:boolean,
is_case_sensitive:boolean, is_case_sensitive:boolean,
mode:string //C S B => C->S S->C BOTH mode:string //C S B => C->S S->C BOTH
n_packets:number, n_packets:number,

View File

@@ -16,7 +16,7 @@ export const regex_ipv4 = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.
export const regex_ipv4_no_cidr = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" export const regex_ipv4_no_cidr = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"
export const regex_port = "^([1-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])?$" export const regex_port = "^([1-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])?$"
export const regex_range_port = "^(([1-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])(-([1-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])?)?)?$" export const regex_range_port = "^(([1-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])(-([1-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])?)?)?$"
export const DEV_IP_BACKEND = "198.19.249.69:4444" export const DEV_IP_BACKEND = "127.0.0.1:4444"
export const queryClient = new QueryClient({ defaultOptions: { queries: { export const queryClient = new QueryClient({ defaultOptions: { queries: {
staleTime: Infinity staleTime: Infinity

View File

@@ -98,7 +98,7 @@ print(f"{results[0]} MB/s")
#Add all the regexs #Add all the regexs
for i in range(1,args.num_of_regexes+1): for i in range(1,args.num_of_regexes+1):
regex = base64.b64encode(bytes(secrets.token_hex(16).encode())).decode() regex = base64.b64encode(bytes(secrets.token_hex(16).encode())).decode()
if not firegex.nf_add_regex(service_id,regex,"B",active=True,is_blacklist=True,is_case_sensitive=False): if not firegex.nf_add_regex(service_id,regex,"B",active=True,is_case_sensitive=False):
puts("Benchmark Failed: Coulnd't add the regex ✗", color=colors.red) puts("Benchmark Failed: Coulnd't add the regex ✗", color=colors.red)
exit_test(1) exit_test(1)
puts(f"Performance with {i} regex(s): ", color=colors.red, end='') puts(f"Performance with {i} regex(s): ", color=colors.red, end='')

View File

@@ -67,7 +67,7 @@ else:
#Add new regex #Add new regex
secret = bytes(secrets.token_hex(16).encode()) secret = bytes(secrets.token_hex(16).encode())
regex = base64.b64encode(secret).decode() regex = base64.b64encode(secret).decode()
if firegex.nf_add_regex(service_id,regex,"B",active=True,is_blacklist=True,is_case_sensitive=True): if firegex.nf_add_regex(service_id,regex,"B",active=True,is_case_sensitive=True):
puts(f"Sucessfully added regex {str(secret)}", color=colors.green) puts(f"Sucessfully added regex {str(secret)}", color=colors.green)
else: else:
puts("Test Failed: Coulnd't add the regex {str(secret)} ✗", color=colors.red) puts("Test Failed: Coulnd't add the regex {str(secret)} ✗", color=colors.red)
@@ -166,7 +166,7 @@ for r in firegex.nf_get_service_regexes(service_id):
checkRegex(regex,should_work=False) checkRegex(regex,should_work=False)
#Add case insensitive regex #Add case insensitive regex
if(firegex.nf_add_regex(service_id,regex,"B",active=True,is_blacklist=True,is_case_sensitive=False)): if(firegex.nf_add_regex(service_id,regex,"B",active=True, is_case_sensitive=False)):
puts(f"Sucessfully added case insensitive regex {str(secret)}", color=colors.green) puts(f"Sucessfully added case insensitive regex {str(secret)}", color=colors.green)
else: else:
puts(f"Test Failed: Coulnd't add the case insensitive regex {str(secret)}", color=colors.red) puts(f"Test Failed: Coulnd't add the case insensitive regex {str(secret)}", color=colors.red)

View File

@@ -121,9 +121,9 @@ class FiregexAPI:
req = self.s.get(f"{self.address}api/nfregex/regex/{regex_id}/disable") req = self.s.get(f"{self.address}api/nfregex/regex/{regex_id}/disable")
return verify(req) return verify(req)
def nf_add_regex(self, service_id: str, regex: str, mode: str, active: bool, is_blacklist: bool, is_case_sensitive: bool): def nf_add_regex(self, service_id: str, regex: str, mode: str, active: bool, is_case_sensitive: bool):
req = self.s.post(f"{self.address}api/nfregex/regexes/add", req = self.s.post(f"{self.address}api/nfregex/regexes/add",
json={"service_id": service_id, "regex": regex, "mode": mode, "active": active, "is_blacklist": is_blacklist, "is_case_sensitive": is_case_sensitive}) json={"service_id": service_id, "regex": regex, "mode": mode, "active": active, "is_case_sensitive": is_case_sensitive})
return verify(req) return verify(req)
def nf_add_service(self, name: str, port: int, proto: str, ip_int: str): def nf_add_service(self, name: str, port: int, proto: str, ip_int: str):