Refactored code now working

This commit is contained in:
nik012003
2022-07-12 23:14:32 +02:00
parent 1e94c26fd6
commit e331a31530
9 changed files with 39 additions and 86 deletions

View File

@@ -3,7 +3,7 @@ docker-compose.yml
**/*.pyc **/*.pyc
**/__pycache__/ **/__pycache__/
/.vscode/ **/.vscode/**
#Node filters #Node filters

2
.gitignore vendored
View File

@@ -1,6 +1,6 @@
**/*.pyc **/*.pyc
**/__pycache__/ **/__pycache__/
/.vscode/** **/.vscode/**
/.mypy_cache/** /.mypy_cache/**
**/node_modules **/node_modules

View File

@@ -1,5 +0,0 @@
{
"python.linting.pylintEnabled": false,
"python.linting.mypyEnabled": true,
"python.linting.enabled": true
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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)