Refactored code now working
This commit is contained in:
@@ -3,7 +3,7 @@ docker-compose.yml
|
||||
|
||||
**/*.pyc
|
||||
**/__pycache__/
|
||||
/.vscode/
|
||||
**/.vscode/**
|
||||
|
||||
#Node filters
|
||||
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,6 +1,6 @@
|
||||
**/*.pyc
|
||||
**/__pycache__/
|
||||
/.vscode/**
|
||||
**/.vscode/**
|
||||
/.mypy_cache/**
|
||||
|
||||
**/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):
|
||||
init, end = queue_range
|
||||
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 []),
|
||||
* (["-s", str(ip_int)] if ip_int else []),
|
||||
* (["--sport", str(port)] if port else []),
|
||||
@@ -92,8 +92,9 @@ class FiregexTables(IPTables):
|
||||
|
||||
def get(self) -> List[FiregexFilter]:
|
||||
res = []
|
||||
iptables_filters = self.list()
|
||||
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()
|
||||
queue = filter.nfqueue()
|
||||
if queue and port:
|
||||
@@ -133,13 +134,13 @@ class FiregexInterceptor:
|
||||
def func_wrap(ll_data, ll_proto_id, data, ctx, *args):
|
||||
pkt_parsed = ip6.IP6(data) if self.ipv6 else ip.IP(data)
|
||||
try:
|
||||
data = None
|
||||
pkt_data = None
|
||||
if not pkt_parsed[tcp.TCP] is None:
|
||||
data = pkt_parsed[tcp.TCP].body_bytes
|
||||
if not pkt_parsed[tcp.TCP] is None:
|
||||
data = pkt_parsed[udp.UDP].body_bytes
|
||||
if data:
|
||||
if func(data):
|
||||
pkt_data = pkt_parsed[tcp.TCP].body_bytes
|
||||
elif not pkt_parsed[udp.UDP] is None:
|
||||
pkt_data = pkt_parsed[udp.UDP].body_bytes
|
||||
if pkt_data:
|
||||
if func(pkt_data):
|
||||
return data, interceptor.NF_ACCEPT
|
||||
elif pkt_parsed[tcp.TCP]:
|
||||
pkt_parsed[tcp.TCP].flags &= 0x00
|
||||
|
||||
@@ -45,7 +45,7 @@ class FirewallManager:
|
||||
continue
|
||||
|
||||
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):
|
||||
try:
|
||||
@@ -111,7 +111,7 @@ class ServiceManager:
|
||||
def __init__(self, srv: Service, db):
|
||||
self.srv = srv
|
||||
self.db = db
|
||||
self.iptables = FiregexTables(self.srv.ipv6)
|
||||
self.firegextable = FiregexTables(self.srv.ipv6)
|
||||
self.status = STATUS.STOP
|
||||
self.filters: Dict[int, FiregexFilter] = {}
|
||||
self._update_filters_from_db()
|
||||
@@ -137,22 +137,19 @@ class ServiceManager:
|
||||
for f in new_filters:
|
||||
if not f in old_filters:
|
||||
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):
|
||||
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 with self.lock:
|
||||
return self._next(to)
|
||||
|
||||
def _next(self, to):
|
||||
if (self.status, to) == (STATUS.ACTIVE, STATUS.STOP):
|
||||
self.proxy.stop()
|
||||
self._set_status(to)
|
||||
# PAUSE -> ACTIVE
|
||||
elif (self.status, to) == (STATUS.STOP, STATUS.ACTIVE):
|
||||
self.proxy.restart()
|
||||
if (self.status, to) == (STATUS.ACTIVE, STATUS.STOP):
|
||||
self.stop()
|
||||
self._set_status(to)
|
||||
# PAUSE -> ACTIVE
|
||||
elif (self.status, to) == (STATUS.STOP, STATUS.ACTIVE):
|
||||
self.restart()
|
||||
|
||||
def _stats_updater(self,filter:RegexFilter):
|
||||
self.db.query("UPDATE regexes SET blocked_packets = ? WHERE regex_id = ?;", filter.blocked, filter.id)
|
||||
@@ -167,7 +164,7 @@ class ServiceManager:
|
||||
|
||||
def start(self):
|
||||
if not self.interceptor:
|
||||
self.iptables.delete_by_srv(self.srv)
|
||||
self.firegextable.delete_by_srv(self.srv)
|
||||
def regex_filter(pkt, by_client):
|
||||
try:
|
||||
for filter in self.filters.values():
|
||||
@@ -178,11 +175,11 @@ class ServiceManager:
|
||||
return False
|
||||
except IndexError: pass
|
||||
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)
|
||||
|
||||
def stop(self):
|
||||
self.iptables.delete_by_srv(self.srv)
|
||||
self.firegextable.delete_by_srv(self.srv)
|
||||
if self.interceptor:
|
||||
self.interceptor.stop()
|
||||
self.interceptor = None
|
||||
|
||||
@@ -12,6 +12,9 @@ class Rule():
|
||||
self.destination = destination
|
||||
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]:
|
||||
port = re.findall(r"dpt:([0-9]+)", self.details)
|
||||
return int(port[0]) if port else None
|
||||
@@ -49,7 +52,7 @@ class IPTables:
|
||||
if line.startswith("Chain"):
|
||||
chain_name = line.split()[1]
|
||||
res[chain_name] = []
|
||||
elif line.split()[0].isnumeric():
|
||||
elif line and line.split()[0].isnumeric():
|
||||
parsed = re.findall(r"([^ ]*)[ ]{,10}([^ ]*)[ ]{,5}([^ ]*)[ ]{,5}([^ ]*)[ ]{,5}([^ ]*)[ ]+([^ ]*)[ ]+(.*)", line)
|
||||
if len(parsed) > 0:
|
||||
parsed = parsed[0]
|
||||
@@ -60,7 +63,7 @@ class IPTables:
|
||||
opt=parsed[3].strip(),
|
||||
source=parsed[4].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
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from typing import Union
|
||||
import json, sqlite3, os
|
||||
from hashlib import md5
|
||||
import base64
|
||||
|
||||
class SQLite():
|
||||
def __init__(self, db_name: str) -> None:
|
||||
@@ -116,7 +117,7 @@ class Service:
|
||||
|
||||
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):
|
||||
self.regex = regex
|
||||
self.regex = base64.b64decode(regex)
|
||||
self.mode = mode
|
||||
self.service_id = service_id
|
||||
self.is_blacklist = is_blacklist
|
||||
|
||||
@@ -75,10 +75,6 @@ class FiregexAPI:
|
||||
req = self.s.get(f"{self.address}api/service/{service_id}/start")
|
||||
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):
|
||||
req = self.s.get(f"{self.address}api/service/{service_id}/stop")
|
||||
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
|
||||
def exit_test(status_code=0):
|
||||
#if service_created:
|
||||
# if(firegex.delete(service)):
|
||||
# puts(f"Sucessfully delete service with id {service} ✔", color=colors.green)
|
||||
# else:
|
||||
# puts(f"Test Failed: Couldn't delete service ✗", color=colors.red); exit(1)
|
||||
if service_created:
|
||||
if(firegex.delete(service)):
|
||||
puts(f"Sucessfully delete service with id {service} ✔", color=colors.green)
|
||||
else:
|
||||
puts(f"Test Failed: Couldn't delete service ✗", color=colors.red); exit(1)
|
||||
sep()
|
||||
server.terminate()
|
||||
exit(status_code)
|
||||
@@ -120,6 +120,7 @@ def checkRegex(regex):
|
||||
if not sendCheckData(secrets.token_bytes(200) + secret + secrets.token_bytes(200)):
|
||||
puts(f"The malicious request was successfully blocked ✔", color=colors.green)
|
||||
n_blocked += 1
|
||||
sleep(10)
|
||||
if firegex.get_regex(r["id"])["n_packets"] == n_blocked:
|
||||
puts(f"The packed was reported as blocked ✔", color=colors.green)
|
||||
else:
|
||||
@@ -132,7 +133,7 @@ def checkRegex(regex):
|
||||
checkRegex(regex)
|
||||
|
||||
#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)
|
||||
|
||||
#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)
|
||||
else:
|
||||
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
|
||||
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
|
||||
#Start firewall
|
||||
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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user