pushed edits
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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.
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|
||||||
|
|||||||
@@ -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)]
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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='')
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
Reference in New Issue
Block a user