sysctl managmento for port hijacking

This commit is contained in:
Domingo Dirutigliano
2023-04-12 23:53:43 +02:00
parent 37c51d6c4a
commit 63a3014676
63 changed files with 105 additions and 50 deletions
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
+10 -1
View File
@@ -7,12 +7,18 @@ from jose import jwt
from passlib.context import CryptContext
from fastapi_socketio import SocketManager
from utils.sqlite import SQLite
from utils import API_VERSION, FIREGEX_PORT, JWT_ALGORITHM, get_interfaces, refresh_frontend, DEBUG
from utils import API_VERSION, FIREGEX_PORT, JWT_ALGORITHM, get_interfaces, refresh_frontend, DEBUG, SysctlManager
from utils.loader import frontend_deploy, load_routers
from utils.models import ChangePasswordModel, IpInterface, PasswordChangeForm, PasswordForm, ResetRequest, StatusModel, StatusMessageModel
# DB init
db = SQLite('db/firegex.db')
sysctl = SysctlManager({
"net.ipv4.conf.all.forwarding": True,
"net.ipv6.conf.all.forwarding": True,
"net.ipv4.conf.all.route_localnet": True,
"net.ipv4.ip_forward": True
})
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/login", auto_error=False)
crypto = CryptContext(schemes=["bcrypt"], deprecated="auto")
@@ -114,6 +120,7 @@ async def startup_event():
db.init()
if os.getenv("HEX_SET_PSW"):
set_psw(bytes.fromhex(os.getenv("HEX_SET_PSW")).decode())
sysctl.set()
await startup()
if not JWT_SECRET(): db.put("secret", secrets.token_hex(32))
await refresh_frontend()
@@ -121,6 +128,7 @@ async def startup_event():
@app.on_event("shutdown")
async def shutdown_event():
await shutdown()
sysctl.reset()
db.disconnect()
@api.post('/reset', response_model=StatusMessageModel)
@@ -130,6 +138,7 @@ async def reset_firegex(form: ResetRequest):
db.delete()
db.init()
db.put("secret", secrets.token_hex(32))
sysctl.set()
await reset(form)
await refresh_frontend()
return {'status': 'ok'}
View File
Executable → Regular
View File
Executable → Regular
+28
View File
@@ -29,6 +29,34 @@ def refactor_name(name:str):
while " " in name: name = name.replace(" "," ")
return name
class SysctlManager:
def __init__(self, ctl_table):
self.old_table = {}
self.new_table = {}
if os.path.isdir("/sys_host/"):
self.old_table = dict()
self.new_table = dict(ctl_table)
for name in ctl_table.keys():
self.old_table[name] = read_sysctl(name)
def write_table(self, table):
for name, value in table.items():
write_sysctl(name, value)
def set(self):
self.write_table(self.new_table)
def reset(self):
self.write_table(self.old_table)
def read_sysctl(name:str):
with open(f"/sys_host/{name}", "rt") as f:
return "1" in f.read()
def write_sysctl(name:str, value:bool):
with open(f"/sys_host/{name}", "wt") as f:
f.write("1" if value else "0")
def list_files(mypath):
from os import listdir
from os.path import isfile, join
Executable → Regular
View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Executable → Regular
View File
Vendored Executable → Regular
View File
Generated Executable → Regular
View File
Executable → Regular
View File
View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 90 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 710 B

After

Width:  |  Height:  |  Size: 710 B

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Executable → Regular
View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Executable → Regular
View File

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
View File
View File
View File
View File
View File
Vendored Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
+53 -35
View File
@@ -4,6 +4,7 @@ import argparse, sys, platform, os, multiprocessing, subprocess, getpass
pref = "\033["
reset = f"{pref}0m"
composefile = "firegex-compose.yml"
class colors:
black = "30m"
@@ -72,41 +73,7 @@ args = parser.parse_args()
os.chdir(os.path.dirname(os.path.realpath(__file__)))
run_checks()
start_operation = not (args.stop or args.restart)
if args.build and not os.path.isfile("./Dockerfile"):
puts("This is not a clone of firegex, to build firegex the clone of the repository is needed!", color=colors.red)
exit()
if args.threads < 1:
args.threads = multiprocessing.cpu_count()
if start_operation:
if check_if_exists("docker ps --filter 'name=^firegex$' --no-trunc | grep firegex"):
puts("Firegex is already running! use --help to see options useful to manage firegex execution", color=colors.yellow)
exit()
sep()
puts(f"Firegex", color=colors.yellow, end="")
puts(" will start on port ", end="")
puts(f"{args.port}", color=colors.cyan)
psw_set = None
if start_operation:
if args.psw_no_interactive:
psw_set = args.psw_no_interactive
elif not args.startup_psw:
while True:
puts("Insert the password for firegex: ", end="" , color=colors.yellow, is_bold=True, flush=True)
psw_set = getpass.getpass("")
puts("Confirm the password: ", end="" , color=colors.yellow, is_bold=True, flush=True)
check = getpass.getpass("")
if check != psw_set:
puts("Passwords don't match!" , color=colors.red, is_bold=True, flush=True)
else:
break
composefile = "firegex-compose.yml"
def write_compose(psw_set=None):
with open(composefile,"wt") as compose:
if "linux" in sys.platform and not 'microsoft-standard' in platform.uname().release: #Check if not is a wsl also
@@ -125,6 +92,18 @@ services:
{"- HEX_SET_PSW="+psw_set.encode().hex() if psw_set else ""}
volumes:
- /execute/db
- type: bind
source: /proc/sys/net/ipv4/conf/all/route_localnet
target: /sys_host/net.ipv4.conf.all.route_localnet
- type: bind
source: /proc/sys/net/ipv4/ip_forward
target: /sys_host/net.ipv4.ip_forward
- type: bind
source: /proc/sys/net/ipv4/conf/all/forwarding
target: /sys_host/net.ipv4.conf.all.forwarding
- type: bind
source: /proc/sys/net/ipv6/conf/all/forwarding
target: /sys_host/net.ipv6.conf.all.forwarding
cap_add:
- NET_ADMIN
""")
@@ -152,6 +131,45 @@ services:
cap_add:
- NET_ADMIN
""")
start_operation = not (args.stop or args.restart)
if args.build and not os.path.isfile("./Dockerfile"):
puts("This is not a clone of firegex, to build firegex the clone of the repository is needed!", color=colors.red)
exit()
if args.threads < 1:
args.threads = multiprocessing.cpu_count()
if start_operation and (not args.build or args.keep):
if check_if_exists("docker ps --filter 'name=^firegex$' --no-trunc | grep firegex"):
if args.keep:
write_compose()
else:
puts("Firegex is already running! use --help to see options useful to manage firegex execution", color=colors.yellow)
exit()
sep()
puts(f"Firegex", color=colors.yellow, end="")
puts(" will start on port ", end="")
puts(f"{args.port}", color=colors.cyan)
psw_set = None
if start_operation:
if args.psw_no_interactive:
psw_set = args.psw_no_interactive
elif not args.startup_psw:
while True:
puts("Insert the password for firegex: ", end="" , color=colors.yellow, is_bold=True, flush=True)
psw_set = getpass.getpass("")
puts("Confirm the password: ", end="" , color=colors.yellow, is_bold=True, flush=True)
check = getpass.getpass("")
if check != psw_set:
puts("Passwords don't match!" , color=colors.red, is_bold=True, flush=True)
else:
break
write_compose(psw_set)
sep()
if not args.no_autostart:
try:
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File