diff --git a/.gitignore b/.gitignore index d643585..f3dfd31 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ /backend/modules/proxy docker-compose.yml firegex-compose.yml +firegex-compose-tmp-file.yml # misc **/.DS_Store diff --git a/frontend/src/js/utils.tsx b/frontend/src/js/utils.tsx index 7e148cc..85f3d5a 100644 --- a/frontend/src/js/utils.tsx +++ b/frontend/src/js/utils.tsx @@ -85,7 +85,7 @@ export async function postapi(path:string,data:any,is_form:boolean=false):Promis 'Content-Type': is_form ? 'application/x-www-form-urlencoded' : 'application/json', "Authorization" : "Bearer " + window.localStorage.getItem("access_token") }, - body: is_form ? data : JSON.stringify(data) + body: is_form ? (new URLSearchParams(data)).toString() : JSON.stringify(data) }).then(res => { if(res.status === 401) window.location.reload() if(res.status === 406) resolve({status:"Wrong Password"}) @@ -157,7 +157,7 @@ export async function changepassword(data:ChangePassword) { } export async function login(data:PasswordSend) { - const from = "username=login&password=" + encodeURI(data.password); + const from = {username: "login", password: data.password}; const { status, access_token } = await postapi("login",from,true) as LoginResponse; window.localStorage.setItem("access_token", access_token); return status; diff --git a/start.py b/start.py index e9aeaa2..e676526 100755 --- a/start.py +++ b/start.py @@ -4,7 +4,8 @@ import argparse, sys, platform, os, multiprocessing, subprocess, getpass pref = "\033[" reset = f"{pref}0m" -composefile = "firegex-compose.yml" +composefile = "firegex-compose-tmp-file.yml" +os.chdir(os.path.dirname(os.path.realpath(__file__))) class colors: black = "30m" @@ -44,40 +45,46 @@ def dockercmd(cmd): else: puts("Docker not found! please install docker!", color=colors.red) -def run_checks(): - if not check_if_exists("docker"): - puts("Docker not found! please install docker and docker compose!", color=colors.red) - exit() - elif not check_if_exists("docker-compose") and not check_if_exists("docker compose"): - print(check_if_exists("docker-compose"), check_if_exists("docker compose")) - puts("Docker compose not found! please install docker compose!", color=colors.red) - exit() - if not check_if_exists("docker ps"): - puts("Cannot use docker, the user hasn't the permission or docker isn't running", color=colors.red) - exit() +def gen_args(): + parser = argparse.ArgumentParser() -parser = argparse.ArgumentParser() -parser.add_argument('--port', "-p", type=int, required=False, help='Port where open the web service of the firewall', default=4444) -parser.add_argument('--clear', required=False, action="store_true", help='Delete docker volume associated to firegex resetting all the settings', default=False) -parser.add_argument('--logs', required=False, action="store_true", help='Show firegex logs', default=False) -parser.add_argument('--threads', "-t", type=int, required=False, help='Number of threads started for each service/utility', default=-1) -parser.add_argument('--no-autostart', "-n", required=False, action="store_true", help='Save docker-compose file and not start the container', default=False) -parser.add_argument('--build', "-b", required=False, action="store_true", help='Build the container locally', default=False) -parser.add_argument('--keep','-k', required=False, action="store_true", help='Keep the firegex-compose.yml file generated', default=False) -parser.add_argument('--stop', '-s', required=False, action="store_true", help='Stop firegex execution', default=False) -parser.add_argument('--restart', '-r', required=False, action="store_true", help='Restart firegex', default=False) -parser.add_argument('--psw-no-interactive',type=str, required=False, help='Password for no-interactive mode', default=None) -parser.add_argument('--startup-psw','-P', required=False, action="store_true", help='Insert password in the startup screen of firegex', default=False) + subcommands = parser.add_subparsers(dest="command", help="Command to execute [Default start if not running]") + + #Compose Command + parser_compose = subcommands.add_parser('compose', help='Run docker compose command') + parser_compose.add_argument('compose_args', nargs=argparse.REMAINDER, help='Arguments to pass to docker compose', default=[]) + + #Start Command + parser_start = subcommands.add_parser('start', help='Start the firewall') + parser_start.add_argument('--threads', "-t", type=int, required=False, help='Number of threads started for each service/utility', default=-1) + parser_start.add_argument('--build', "-b", required=False, action="store_true", help='Build the container locally', default=False) + parser_start.add_argument('--psw-no-interactive',type=str, required=False, help='Password for no-interactive mode', default=None) + parser_start.add_argument('--startup-psw','-P', required=False, action="store_true", help='Insert password in the startup screen of firegex', default=False) + parser_start.add_argument('--port', "-p", type=int, required=False, help='Port where open the web service of the firewall', default=4444) + parser_start.add_argument('--logs', required=False, action="store_true", help='Show firegex logs', default=False) + + #Stop Command + parser_stop = subcommands.add_parser('stop', help='Stop the firewall') + parser_stop.add_argument('--clear', required=False, action="store_true", help='Delete docker volume associated to firegex resetting all the settings', default=False) + + parser_restart = subcommands.add_parser('restart', help='Restart the firewall') + parser_restart.add_argument('--logs', required=False, action="store_true", help='Show firegex logs', default=False) + + #General args + if os.path.isfile("./Dockerfile"): + parser.add_argument('--build', "-b", required=False, action="store_true", help='Build the container from source', default=False) + return parser.parse_args() +args = gen_args() -args = parser.parse_args() -os.chdir(os.path.dirname(os.path.realpath(__file__))) -run_checks() +def is_linux(): + return "linux" in sys.platform and not 'microsoft-standard' in platform.uname().release -def write_compose(psw_set=None): +def write_compose(skip_password = True): + psw_set = get_password() if not skip_password else 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 + if is_linux(): #Check if not is a wsl also compose.write(f""" services: firewall: @@ -110,9 +117,6 @@ volumes: """) else: - sep() - puts("--- WARNING ---", color=colors.yellow) - puts("You are not in a linux machine, the firewall will not work in this machine.", color=colors.red) compose.write(f""" services: firewall: @@ -127,83 +131,135 @@ services: {"- HEX_SET_PSW="+psw_set.encode().hex() if psw_set else ""} volumes: - firegex_data:/execute/db - - /execute/db cap_add: - NET_ADMIN volumes: firegex_data: """) -def main(): - start_operation = not (args.stop or args.restart) - volume_exists = check_if_exists('docker volume ls --filter="name=^firegex_firegex_data$" --quiet | grep firegex_firegex_data') - if args.clear: - dockercmd("volume rm firegex_firegex_data") - exit() - - if args.logs: - composecmd("logs -f") - exit() - - 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 +def check_already_running(): + return check_if_exists("docker ps --filter 'name=^firegex$' --no-trunc | grep firegex") + +def get_password(): + if volume_exists() or args.startup_psw: + return None if args.psw_no_interactive: - psw_set = args.psw_no_interactive - elif start_operation and not volume_exists and not args.startup_psw: + return args.psw_no_interactive + psw_set = None + while True: while True: - puts("Insert the password for firegex: ", end="" , color=colors.yellow, is_bold=True, flush=True) + puts("Insert a 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) + if (len(psw_set) < 8): + puts("The password has to be at least 8 char long", color=colors.red, is_bold=True, flush=True) else: break + 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 + return psw_set - write_compose(psw_set) +def volume_exists(): + return check_if_exists('docker volume ls --filter="name=^firegex_firegex_data$" --quiet | grep firegex_firegex_data') - sep() - if not args.no_autostart: - try: - if args.restart: - puts("Running 'docker-compose restart'\n", color=colors.green) - composecmd("restart", composefile) - elif args.stop: - puts("Running 'docker-compose down'\n", color=colors.green) - composecmd("down", composefile) - else: - if not args.build: - puts("Downloading docker image from github packages 'docker pull ghcr.io/pwnzer0tt1/firegex'", color=colors.green) - dockercmd("pull ghcr.io/pwnzer0tt1/firegex") - puts("Running 'docker-compose up -d --build'\n", color=colors.green) - composecmd("up -d --build", composefile) - finally: - if not args.keep: - os.remove(composefile) - else: - puts("Done! You can start/stop firegex with docker-compose up -d --build", color=colors.yellow) +def nfqueue_exists(): + return check_if_exists('ls /lib/modules/$(uname -r)/kernel/net/netfilter/nfnetlink_queue.*') + +def delete_volume(): + return dockercmd("volume rm firegex_firegex_data") + +def main(): + + print(args) + + if not check_if_exists("docker"): + puts("Docker not found! please install docker and docker compose!", color=colors.red) + exit() + elif not check_if_exists("docker-compose") and not check_if_exists("docker compose"): + print(check_if_exists("docker-compose"), check_if_exists("docker compose")) + puts("Docker compose not found! please install docker compose!", color=colors.red) + exit() + if not check_if_exists("docker ps"): + puts("Cannot use docker, the user hasn't the permission or docker isn't running", color=colors.red) + exit() + + if args.command is None: + if not check_already_running() and not args.clear: + args.command = "start" + + if not is_linux(): sep() + puts("--- WARNING ---", color=colors.yellow) + puts("You are not in a linux machine, the firewall will not work in this machine.", color=colors.red) + sep() + elif not nfqueue_exists(): + sep() + puts("--- WARNING ---", color=colors.yellow) + puts("The nfqueue kernel module seems not loaded, some features of firegex may not work.", color=colors.red) + sep() + + if not "threads" in args or args.threads < 1: + args.threads = multiprocessing.cpu_count() + + if not "port" in args or args.port < 1: + args.port = 4444 + + if args.command: + match args.command: + case "start": + if check_already_running(): + puts("Firegex is already running! use --help to see options useful to manage firegex execution", color=colors.yellow) + else: + puts(f"Firegex", color=colors.yellow, end="") + puts(" will start on port ", end="") + puts(f"{args.port}", color=colors.cyan) + write_compose(skip_password=False) + if not args.build: + puts("Downloading docker image from github packages 'docker pull ghcr.io/pwnzer0tt1/firegex'", color=colors.green) + dockercmd("pull ghcr.io/pwnzer0tt1/firegex") + puts("Running 'docker compose up -d --build'\n", color=colors.green) + composecmd("up -d --build", composefile) + case "compose": + write_compose() + compose_cmd = " ".join(args.compose_args) + puts(f"Running 'docker compose {compose_cmd}'\n", color=colors.green) + composecmd(compose_cmd, composefile) + case "restart": + if check_already_running(): + write_compose() + puts("Running 'docker compose restart'\n", color=colors.green) + composecmd("restart", composefile) + else: + puts("Firegex is not running!" , color=colors.red, is_bold=True, flush=True) + case "stop": + if check_already_running(): + write_compose() + puts("Running 'docker compose down'\n", color=colors.green) + composecmd("down", composefile) + else: + puts("Firegex is not running!" , color=colors.red, is_bold=True, flush=True) + + write_compose() + + if "clear" in args and args.clear: + if volume_exists(): + delete_volume() + else: + puts("Firegex volume not found!", color=colors.red) + + if "logs" in args and args.logs: + composecmd("logs -f") + if __name__ == "__main__": try: - main() + try: + main() + finally: + if os.path.isfile(composefile): + os.remove(composefile) except KeyboardInterrupt: print()