Refactored code now working
This commit is contained in:
@@ -3,7 +3,7 @@ docker-compose.yml
|
|||||||
|
|
||||||
**/*.pyc
|
**/*.pyc
|
||||||
**/__pycache__/
|
**/__pycache__/
|
||||||
/.vscode/
|
**/.vscode/**
|
||||||
|
|
||||||
#Node filters
|
#Node filters
|
||||||
|
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,6 +1,6 @@
|
|||||||
**/*.pyc
|
**/*.pyc
|
||||||
**/__pycache__/
|
**/__pycache__/
|
||||||
/.vscode/**
|
**/.vscode/**
|
||||||
/.mypy_cache/**
|
/.mypy_cache/**
|
||||||
|
|
||||||
**/node_modules
|
**/node_modules
|
||||||
|
|||||||
5
backend/.vscode/settings.json
vendored
5
backend/.vscode/settings.json
vendored
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"python.linting.pylintEnabled": false,
|
|
||||||
"python.linting.mypyEnabled": true,
|
|
||||||
"python.linting.enabled": true
|
|
||||||
}
|
|
||||||
@@ -71,7 +71,7 @@ class FiregexTables(IPTables):
|
|||||||
def add_output(self, queue_range, proto = None, port = None, ip_int = None):
|
def add_output(self, queue_range, proto = None, port = None, ip_int = None):
|
||||||
init, end = queue_range
|
init, end = queue_range
|
||||||
if init > end: init, end = end, init
|
if init > end: init, end = end, init
|
||||||
self.append_rule(FilterTypes.OUTPUT,"NFQUEUE"
|
self.append_rule(FilterTypes.OUTPUT,"NFQUEUE",
|
||||||
* (["-p", str(proto)] if proto else []),
|
* (["-p", str(proto)] if proto else []),
|
||||||
* (["-s", str(ip_int)] if ip_int else []),
|
* (["-s", str(ip_int)] if ip_int else []),
|
||||||
* (["--sport", str(port)] if port else []),
|
* (["--sport", str(port)] if port else []),
|
||||||
@@ -92,8 +92,9 @@ class FiregexTables(IPTables):
|
|||||||
|
|
||||||
def get(self) -> List[FiregexFilter]:
|
def get(self) -> List[FiregexFilter]:
|
||||||
res = []
|
res = []
|
||||||
|
iptables_filters = self.list()
|
||||||
for filter_type in [FilterTypes.INPUT, FilterTypes.OUTPUT]:
|
for filter_type in [FilterTypes.INPUT, FilterTypes.OUTPUT]:
|
||||||
for filter in self.list()[filter_type]:
|
for filter in iptables_filters[filter_type]:
|
||||||
port = filter.sport() if filter_type == FilterTypes.OUTPUT else filter.dport()
|
port = filter.sport() if filter_type == FilterTypes.OUTPUT else filter.dport()
|
||||||
queue = filter.nfqueue()
|
queue = filter.nfqueue()
|
||||||
if queue and port:
|
if queue and port:
|
||||||
@@ -133,13 +134,13 @@ class FiregexInterceptor:
|
|||||||
def func_wrap(ll_data, ll_proto_id, data, ctx, *args):
|
def func_wrap(ll_data, ll_proto_id, data, ctx, *args):
|
||||||
pkt_parsed = ip6.IP6(data) if self.ipv6 else ip.IP(data)
|
pkt_parsed = ip6.IP6(data) if self.ipv6 else ip.IP(data)
|
||||||
try:
|
try:
|
||||||
data = None
|
pkt_data = None
|
||||||
if not pkt_parsed[tcp.TCP] is None:
|
if not pkt_parsed[tcp.TCP] is None:
|
||||||
data = pkt_parsed[tcp.TCP].body_bytes
|
pkt_data = pkt_parsed[tcp.TCP].body_bytes
|
||||||
if not pkt_parsed[tcp.TCP] is None:
|
elif not pkt_parsed[udp.UDP] is None:
|
||||||
data = pkt_parsed[udp.UDP].body_bytes
|
pkt_data = pkt_parsed[udp.UDP].body_bytes
|
||||||
if data:
|
if pkt_data:
|
||||||
if func(data):
|
if func(pkt_data):
|
||||||
return data, interceptor.NF_ACCEPT
|
return data, interceptor.NF_ACCEPT
|
||||||
elif pkt_parsed[tcp.TCP]:
|
elif pkt_parsed[tcp.TCP]:
|
||||||
pkt_parsed[tcp.TCP].flags &= 0x00
|
pkt_parsed[tcp.TCP].flags &= 0x00
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class FirewallManager:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
self.proxy_table[srv.id] = ServiceManager(srv, self.db)
|
self.proxy_table[srv.id] = ServiceManager(srv, self.db)
|
||||||
await self.proxy_table[srv.id].next(srv["status"])
|
await self.proxy_table[srv.id].next(srv.status)
|
||||||
|
|
||||||
async def _stats_updater(self, callback):
|
async def _stats_updater(self, callback):
|
||||||
try:
|
try:
|
||||||
@@ -111,7 +111,7 @@ class ServiceManager:
|
|||||||
def __init__(self, srv: Service, db):
|
def __init__(self, srv: Service, db):
|
||||||
self.srv = srv
|
self.srv = srv
|
||||||
self.db = db
|
self.db = db
|
||||||
self.iptables = FiregexTables(self.srv.ipv6)
|
self.firegextable = FiregexTables(self.srv.ipv6)
|
||||||
self.status = STATUS.STOP
|
self.status = STATUS.STOP
|
||||||
self.filters: Dict[int, FiregexFilter] = {}
|
self.filters: Dict[int, FiregexFilter] = {}
|
||||||
self._update_filters_from_db()
|
self._update_filters_from_db()
|
||||||
@@ -137,22 +137,19 @@ class ServiceManager:
|
|||||||
for f in new_filters:
|
for f in new_filters:
|
||||||
if not f in old_filters:
|
if not f in old_filters:
|
||||||
filter = [ele for ele in regexes if ele.id == f][0]
|
filter = [ele for ele in regexes if ele.id == f][0]
|
||||||
self.filters[f] = FiregexFilter.from_regex(filter)
|
self.filters[f] = RegexFilter.from_regex(filter)
|
||||||
|
|
||||||
def __update_status_db(self, status):
|
def __update_status_db(self, status):
|
||||||
self.db.query("UPDATE services SET status = ? WHERE service_id = ?;", status, self.srv["service_id"])
|
self.db.query("UPDATE services SET status = ? WHERE service_id = ?;", status, self.srv.id)
|
||||||
|
|
||||||
async def next(self,to):
|
async def next(self,to):
|
||||||
async with self.lock:
|
async with self.lock:
|
||||||
return self._next(to)
|
if (self.status, to) == (STATUS.ACTIVE, STATUS.STOP):
|
||||||
|
self.stop()
|
||||||
def _next(self, to):
|
self._set_status(to)
|
||||||
if (self.status, to) == (STATUS.ACTIVE, STATUS.STOP):
|
# PAUSE -> ACTIVE
|
||||||
self.proxy.stop()
|
elif (self.status, to) == (STATUS.STOP, STATUS.ACTIVE):
|
||||||
self._set_status(to)
|
self.restart()
|
||||||
# PAUSE -> ACTIVE
|
|
||||||
elif (self.status, to) == (STATUS.STOP, STATUS.ACTIVE):
|
|
||||||
self.proxy.restart()
|
|
||||||
|
|
||||||
def _stats_updater(self,filter:RegexFilter):
|
def _stats_updater(self,filter:RegexFilter):
|
||||||
self.db.query("UPDATE regexes SET blocked_packets = ? WHERE regex_id = ?;", filter.blocked, filter.id)
|
self.db.query("UPDATE regexes SET blocked_packets = ? WHERE regex_id = ?;", filter.blocked, filter.id)
|
||||||
@@ -167,7 +164,7 @@ class ServiceManager:
|
|||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
if not self.interceptor:
|
if not self.interceptor:
|
||||||
self.iptables.delete_by_srv(self.srv)
|
self.firegextable.delete_by_srv(self.srv)
|
||||||
def regex_filter(pkt, by_client):
|
def regex_filter(pkt, by_client):
|
||||||
try:
|
try:
|
||||||
for filter in self.filters.values():
|
for filter in self.filters.values():
|
||||||
@@ -178,11 +175,11 @@ class ServiceManager:
|
|||||||
return False
|
return False
|
||||||
except IndexError: pass
|
except IndexError: pass
|
||||||
return True
|
return True
|
||||||
self.interceptor = self.iptables.add(self.srv["proto"], self.srv["port"], self.srv["ip_int"], regex_filter)
|
self.interceptor = self.firegextable.add(FiregexFilter(self.srv.proto,self.srv.port, self.srv.ip_int, func=regex_filter))
|
||||||
self._set_status(STATUS.ACTIVE)
|
self._set_status(STATUS.ACTIVE)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.iptables.delete_by_srv(self.srv)
|
self.firegextable.delete_by_srv(self.srv)
|
||||||
if self.interceptor:
|
if self.interceptor:
|
||||||
self.interceptor.stop()
|
self.interceptor.stop()
|
||||||
self.interceptor = None
|
self.interceptor = None
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ class Rule():
|
|||||||
self.destination = destination
|
self.destination = destination
|
||||||
self.details = details
|
self.details = details
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return f"Rule {self.id} : {self.target}, {self.prot}, {self.opt}, {self.source}, {self.destination}, {self.details}"
|
||||||
|
|
||||||
def dport(self) -> Union[int, None]:
|
def dport(self) -> Union[int, None]:
|
||||||
port = re.findall(r"dpt:([0-9]+)", self.details)
|
port = re.findall(r"dpt:([0-9]+)", self.details)
|
||||||
return int(port[0]) if port else None
|
return int(port[0]) if port else None
|
||||||
@@ -49,7 +52,7 @@ class IPTables:
|
|||||||
if line.startswith("Chain"):
|
if line.startswith("Chain"):
|
||||||
chain_name = line.split()[1]
|
chain_name = line.split()[1]
|
||||||
res[chain_name] = []
|
res[chain_name] = []
|
||||||
elif line.split()[0].isnumeric():
|
elif line and line.split()[0].isnumeric():
|
||||||
parsed = re.findall(r"([^ ]*)[ ]{,10}([^ ]*)[ ]{,5}([^ ]*)[ ]{,5}([^ ]*)[ ]{,5}([^ ]*)[ ]+([^ ]*)[ ]+(.*)", line)
|
parsed = re.findall(r"([^ ]*)[ ]{,10}([^ ]*)[ ]{,5}([^ ]*)[ ]{,5}([^ ]*)[ ]{,5}([^ ]*)[ ]+([^ ]*)[ ]+(.*)", line)
|
||||||
if len(parsed) > 0:
|
if len(parsed) > 0:
|
||||||
parsed = parsed[0]
|
parsed = parsed[0]
|
||||||
@@ -60,7 +63,7 @@ class IPTables:
|
|||||||
opt=parsed[3].strip(),
|
opt=parsed[3].strip(),
|
||||||
source=parsed[4].strip(),
|
source=parsed[4].strip(),
|
||||||
destination=parsed[5].strip(),
|
destination=parsed[5].strip(),
|
||||||
details=" ".join(parsed[6:]).strip() if len(parsed[0]) >= 7 else ""
|
details=" ".join(parsed[6:]).strip() if len(parsed) >= 7 else ""
|
||||||
))
|
))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from typing import Union
|
from typing import Union
|
||||||
import json, sqlite3, os
|
import json, sqlite3, os
|
||||||
from hashlib import md5
|
from hashlib import md5
|
||||||
|
import base64
|
||||||
|
|
||||||
class SQLite():
|
class SQLite():
|
||||||
def __init__(self, db_name: str) -> None:
|
def __init__(self, db_name: str) -> None:
|
||||||
@@ -116,7 +117,7 @@ class Service:
|
|||||||
|
|
||||||
class Regex:
|
class Regex:
|
||||||
def __init__(self, id: int, regex: str, mode: str, service_id: str, is_blacklist: bool, blocked_packets: int, is_case_sensitive: bool, active: bool):
|
def __init__(self, id: int, regex: str, mode: str, service_id: str, is_blacklist: bool, blocked_packets: int, is_case_sensitive: bool, active: bool):
|
||||||
self.regex = regex
|
self.regex = base64.b64decode(regex)
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.service_id = service_id
|
self.service_id = service_id
|
||||||
self.is_blacklist = is_blacklist
|
self.is_blacklist = is_blacklist
|
||||||
|
|||||||
@@ -75,10 +75,6 @@ class FiregexAPI:
|
|||||||
req = self.s.get(f"{self.address}api/service/{service_id}/start")
|
req = self.s.get(f"{self.address}api/service/{service_id}/start")
|
||||||
return req.json()["status"] == "ok"
|
return req.json()["status"] == "ok"
|
||||||
|
|
||||||
def pause(self,service_id):
|
|
||||||
req = self.s.get(f"{self.address}api/service/{service_id}/pause")
|
|
||||||
return req.json()["status"] == "ok"
|
|
||||||
|
|
||||||
def stop(self,service_id):
|
def stop(self,service_id):
|
||||||
req = self.s.get(f"{self.address}api/service/{service_id}/stop")
|
req = self.s.get(f"{self.address}api/service/{service_id}/stop")
|
||||||
return req.json()["status"] == "ok"
|
return req.json()["status"] == "ok"
|
||||||
|
|||||||
@@ -58,11 +58,11 @@ else: puts(f"Test Failed: Couldn't create service ✗", color=colors.red); exit(
|
|||||||
|
|
||||||
#Delete the Service and exit
|
#Delete the Service and exit
|
||||||
def exit_test(status_code=0):
|
def exit_test(status_code=0):
|
||||||
#if service_created:
|
if service_created:
|
||||||
# if(firegex.delete(service)):
|
if(firegex.delete(service)):
|
||||||
# puts(f"Sucessfully delete service with id {service} ✔", color=colors.green)
|
puts(f"Sucessfully delete service with id {service} ✔", color=colors.green)
|
||||||
# else:
|
else:
|
||||||
# puts(f"Test Failed: Couldn't delete service ✗", color=colors.red); exit(1)
|
puts(f"Test Failed: Couldn't delete service ✗", color=colors.red); exit(1)
|
||||||
sep()
|
sep()
|
||||||
server.terminate()
|
server.terminate()
|
||||||
exit(status_code)
|
exit(status_code)
|
||||||
@@ -120,6 +120,7 @@ def checkRegex(regex):
|
|||||||
if not sendCheckData(secrets.token_bytes(200) + secret + secrets.token_bytes(200)):
|
if not sendCheckData(secrets.token_bytes(200) + secret + secrets.token_bytes(200)):
|
||||||
puts(f"The malicious request was successfully blocked ✔", color=colors.green)
|
puts(f"The malicious request was successfully blocked ✔", color=colors.green)
|
||||||
n_blocked += 1
|
n_blocked += 1
|
||||||
|
sleep(10)
|
||||||
if firegex.get_regex(r["id"])["n_packets"] == n_blocked:
|
if firegex.get_regex(r["id"])["n_packets"] == n_blocked:
|
||||||
puts(f"The packed was reported as blocked ✔", color=colors.green)
|
puts(f"The packed was reported as blocked ✔", color=colors.green)
|
||||||
else:
|
else:
|
||||||
@@ -132,7 +133,7 @@ def checkRegex(regex):
|
|||||||
checkRegex(regex)
|
checkRegex(regex)
|
||||||
|
|
||||||
#Pause the proxy
|
#Pause the proxy
|
||||||
if(firegex.pause(service)): puts(f"Sucessfully paused service with id {service} ✔", color=colors.green)
|
if(firegex.stop(service)): puts(f"Sucessfully paused service with id {service} ✔", color=colors.green)
|
||||||
else: puts(f"Test Failed: Coulnd't pause the service ✗", color=colors.red); exit_test(1)
|
else: puts(f"Test Failed: Coulnd't pause the service ✗", color=colors.red); exit_test(1)
|
||||||
|
|
||||||
#Check if it's actually paused
|
#Check if it's actually paused
|
||||||
@@ -140,49 +141,8 @@ if sendCheckData(secrets.token_bytes(200) + secret + secrets.token_bytes(200)):
|
|||||||
puts(f"The request wasn't blocked ✔", color=colors.green)
|
puts(f"The request wasn't blocked ✔", color=colors.green)
|
||||||
else:
|
else:
|
||||||
puts(f"Test Failed: The request was blocked when it shouldn't have", color=colors.red)
|
puts(f"Test Failed: The request was blocked when it shouldn't have", color=colors.red)
|
||||||
#Stop the proxy
|
|
||||||
if(firegex.stop(service)): puts(f"Sucessfully stopped service with id {service} ✔", color=colors.green)
|
|
||||||
else: puts(f"Test Failed: Coulnd't stop the service ✗", color=colors.red); exit_test(1)
|
|
||||||
|
|
||||||
#Check if proxy is stopped and check if WAIT works
|
#Start firewall
|
||||||
def bindForSeconds(port,delay=4):
|
|
||||||
try:
|
|
||||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
||||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
||||||
sock.bind(('127.0.0.1', port))
|
|
||||||
sock.listen()
|
|
||||||
puts(f"The test could bind to port {port} ✔", color=colors.green)
|
|
||||||
sleep(delay)
|
|
||||||
sock.close()
|
|
||||||
except Exception as e:
|
|
||||||
puts(f"The test couldn't bind to port {port} ✗", color=colors.red)
|
|
||||||
|
|
||||||
bindingTest = Process(target=bindForSeconds, args=[args.service_port])
|
|
||||||
bindingTest.start()
|
|
||||||
sleep(1)
|
|
||||||
|
|
||||||
#Restart it
|
|
||||||
if(firegex.pause(service)): puts(f"Sucessfully started in pause mode ✔", color=colors.green)
|
|
||||||
else: puts(f"Test Failed: Coulnd't start the service ✗", color=colors.red); exit_test(1)
|
|
||||||
if firegex.get_service(service)["status"] == "wait":
|
|
||||||
puts(f"Service started in WAIT mode ✔", color=colors.green)
|
|
||||||
else:
|
|
||||||
puts(f"Service started but it's not WAIT mode ✗", color=colors.red); exit_test(1)
|
|
||||||
|
|
||||||
bindingTest.join()
|
|
||||||
sleep(1)
|
|
||||||
#Check if service started in pause mode successfully
|
|
||||||
if firegex.get_service(service)["status"] == "pause":
|
|
||||||
puts(f"Service started in PAUSE mode ✔", color=colors.green)
|
|
||||||
else:
|
|
||||||
puts(f"Service is not in PAUSE mode ✗", color=colors.red); exit_test(1)
|
|
||||||
|
|
||||||
if sendCheckData(secrets.token_bytes(200) + secret + secrets.token_bytes(200)):
|
|
||||||
puts(f"The request wasn't blocked ✔", color=colors.green)
|
|
||||||
else:
|
|
||||||
puts(f"Test Failed: The request was blocked when it shouldn't have", color=colors.red)
|
|
||||||
|
|
||||||
#Restart it and check
|
|
||||||
if(firegex.start(service)): puts(f"Sucessfully started service with id {service} ✔", color=colors.green)
|
if(firegex.start(service)): puts(f"Sucessfully started service with id {service} ✔", color=colors.green)
|
||||||
else: puts(f"Test Failed: Coulnd't start the service ✗", color=colors.red); exit_test(1)
|
else: puts(f"Test Failed: Coulnd't start the service ✗", color=colors.red); exit_test(1)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user