Merge pull request #28 from Minei3oat/socket

Allow binding to UNIX domain sockets
This commit is contained in:
Domingo Dirutigliano
2025-10-01 15:39:40 +02:00
committed by GitHub
3 changed files with 37 additions and 8 deletions

View File

@@ -8,7 +8,7 @@ from fastapi import FastAPI, HTTPException, Depends, APIRouter
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import jwt from jose import jwt
from utils.sqlite import SQLite from utils.sqlite import SQLite
from utils import API_VERSION, FIREGEX_PORT, FIREGEX_HOST, JWT_ALGORITHM, get_interfaces, socketio_emit, DEBUG, SysctlManager, NORELOAD from utils import API_VERSION, FIREGEX_PORT, FIREGEX_HOST, FIREGEX_SOCKET, JWT_ALGORITHM, get_interfaces, socketio_emit, DEBUG, SysctlManager, NORELOAD
from utils.loader import frontend_deploy, load_routers from utils.loader import frontend_deploy, load_routers
from utils.models import ChangePasswordModel, IpInterface, PasswordChangeForm, PasswordForm, ResetRequest, StatusModel, StatusMessageModel from utils.models import ChangePasswordModel, IpInterface, PasswordChangeForm, PasswordForm, ResetRequest, StatusModel, StatusMessageModel
from contextlib import asynccontextmanager from contextlib import asynccontextmanager
@@ -229,6 +229,7 @@ if __name__ == '__main__':
# None allows to bind also on ipv6, and is selected if FIREGEX_HOST is any # None allows to bind also on ipv6, and is selected if FIREGEX_HOST is any
host="" if FIREGEX_HOST == "any" else FIREGEX_HOST, host="" if FIREGEX_HOST == "any" else FIREGEX_HOST,
port=FIREGEX_PORT, port=FIREGEX_PORT,
uds=FIREGEX_SOCKET,
reload=DEBUG and not NORELOAD, reload=DEBUG and not NORELOAD,
access_log=True, access_log=True,
workers=1, # Firewall module can't be replicated in multiple workers workers=1, # Firewall module can't be replicated in multiple workers

View File

@@ -26,6 +26,8 @@ DEBUG = "DEBUG" in sys.argv
NORELOAD = "NORELOAD" in sys.argv NORELOAD = "NORELOAD" in sys.argv
FIREGEX_PORT = int(os.getenv("PORT","4444")) FIREGEX_PORT = int(os.getenv("PORT","4444"))
FIREGEX_HOST = os.getenv("HOST","0.0.0.0") FIREGEX_HOST = os.getenv("HOST","0.0.0.0")
FIREGEX_SOCKET_DIR = os.getenv("SOCKET_DIR", None)
FIREGEX_SOCKET = os.path.join(FIREGEX_SOCKET_DIR, "firegex.sock") if FIREGEX_SOCKET_DIR else None
JWT_ALGORITHM: str = "HS256" JWT_ALGORITHM: str = "HS256"
API_VERSION = "{{VERSION_PLACEHOLDER}}" if "{" not in "{{VERSION_PLACEHOLDER}}" else "0.0.0" API_VERSION = "{{VERSION_PLACEHOLDER}}" if "{" not in "{{VERSION_PLACEHOLDER}}" else "0.0.0"

40
run.py
View File

@@ -102,7 +102,8 @@ def load_config():
default_config = { default_config = {
"port": 4444, "port": 4444,
# any allow to bind service also on ipv6 (see the main of backend to understand why) # any allow to bind service also on ipv6 (see the main of backend to understand why)
"host": "any" "host": "any",
"socket_dir": None
} }
if os.path.isfile(g.configfile): if os.path.isfile(g.configfile):
@@ -154,6 +155,7 @@ def gen_args(args_to_parse: list[str]|None = None):
parser_start.add_argument('--psw-on-web', required=False, help='Setup firegex password on the web interface', action="store_true", default=False) parser_start.add_argument('--psw-on-web', required=False, help='Setup firegex password on the web interface', action="store_true", default=False)
parser_start.add_argument('--port', "-p", type=int, required=False, help=f'Port where open the web service of the firewall (default from config: {config["port"]})', default=config["port"]) parser_start.add_argument('--port', "-p", type=int, required=False, help=f'Port where open the web service of the firewall (default from config: {config["port"]})', default=config["port"])
parser_start.add_argument('--host', required=False, help=f'Host IP address to bind the service to (default from config: {config["host"]})', default=config["host"]) parser_start.add_argument('--host', required=False, help=f'Host IP address to bind the service to (default from config: {config["host"]})', default=config["host"])
parser_start.add_argument('--socket-dir', required=False, type=str, help=f'Listen on socket_dir/firegex.sock instead of TCP (default from config: {config["socket_dir"]})', default=config["socket_dir"])
parser_start.add_argument('--logs', required=False, action="store_true", help='Show firegex logs', default=False) parser_start.add_argument('--logs', required=False, action="store_true", help='Show firegex logs', default=False)
parser_start.add_argument('--version', '-v', required=False, type=str , help='Version of the firegex image to use', default=None) parser_start.add_argument('--version', '-v', required=False, type=str , help='Version of the firegex image to use', default=None)
parser_start.add_argument('--prebuilt', required=False, action="store_true", help='Use prebuilt docker image', default=False) parser_start.add_argument('--prebuilt', required=False, action="store_true", help='Use prebuilt docker image', default=False)
@@ -167,6 +169,7 @@ def gen_args(args_to_parse: list[str]|None = None):
parser_restart = subcommands.add_parser('restart', help='Restart the firewall') parser_restart = subcommands.add_parser('restart', help='Restart the firewall')
parser_restart.add_argument('--port', "-p", type=int, required=False, help=f'Port where open the web service of the firewall (default from config: {config["port"]})', default=config["port"]) parser_restart.add_argument('--port', "-p", type=int, required=False, help=f'Port where open the web service of the firewall (default from config: {config["port"]})', default=config["port"])
parser_restart.add_argument('--host', required=False, help=f'Host IP address to bind the service to (default from config: {config["host"]})', default=config["host"]) parser_restart.add_argument('--host', required=False, help=f'Host IP address to bind the service to (default from config: {config["host"]})', default=config["host"])
parser_restart.add_argument('--socket-dir', required=False, type=str, help=f'Listen on socket_dir/firegex.sock instead of TCP (default from config: {config["socket_dir"]})', default=config["socket_dir"])
parser_restart.add_argument('--logs', required=False, action="store_true", help='Show firegex logs', default=False) parser_restart.add_argument('--logs', required=False, action="store_true", help='Show firegex logs', default=False)
parser_restart.add_argument('--standalone', required=False, action="store_true", help='Force standalone mode', default=False) parser_restart.add_argument('--standalone', required=False, action="store_true", help='Force standalone mode', default=False)
@@ -174,12 +177,14 @@ def gen_args(args_to_parse: list[str]|None = None):
parser_status = subcommands.add_parser('status', help='Show firewall status') parser_status = subcommands.add_parser('status', help='Show firewall status')
parser_status.add_argument('--port', "-p", type=int, required=False, help=f'Port where open the web service of the firewall (default from config: {config["port"]})', default=config["port"]) parser_status.add_argument('--port', "-p", type=int, required=False, help=f'Port where open the web service of the firewall (default from config: {config["port"]})', default=config["port"])
parser_status.add_argument('--host', required=False, help=f'Host IP address to bind the service to (default from config: {config["host"]})', default=config["host"]) parser_status.add_argument('--host', required=False, help=f'Host IP address to bind the service to (default from config: {config["host"]})', default=config["host"])
parser_status.add_argument('--socket-dir', required=False, type=str, help=f'Listen on socket_dir/firegex.sock instead of TCP (default from config: {config["socket_dir"]})', default=config["socket_dir"])
parser_status.add_argument('--standalone', required=False, action="store_true", help='Force standalone mode', default=False) parser_status.add_argument('--standalone', required=False, action="store_true", help='Force standalone mode', default=False)
#Config Command #Config Command
parser_config = subcommands.add_parser('config', help='Manage configuration settings') parser_config = subcommands.add_parser('config', help='Manage configuration settings')
parser_config.add_argument('--port', "-p", type=int, required=False, help='Set default port for web service') parser_config.add_argument('--port', "-p", type=int, required=False, help='Set default port for web service')
parser_config.add_argument('--host', required=False, help='Set default host IP address to bind the service to') parser_config.add_argument('--host', required=False, help='Set default host IP address to bind the service to')
parser_config.add_argument('--socket-dir', required=False, type=str, help=f'Listen on socket_dir/firegex.sock instead of TCP (default from config: {config["socket_dir"]})', default=config["socket_dir"])
parser_config.add_argument('--show', required=False, action="store_true", help='Show current configuration', default=False) parser_config.add_argument('--show', required=False, action="store_true", help='Show current configuration', default=False)
args = parser.parse_args(args=args_to_parse) args = parser.parse_args(args=args_to_parse)
@@ -215,6 +220,9 @@ def gen_args(args_to_parse: list[str]|None = None):
if "host" not in args: if "host" not in args:
args.host = config["host"] args.host = config["host"]
if "socket_dir" not in args:
args.socket_dir = config["socket_dir"]
# Save configuration if values were specified via command line and differ from config # Save configuration if values were specified via command line and differ from config
config_changed = False config_changed = False
if hasattr(args, 'port') and args.port != config["port"]: if hasattr(args, 'port') and args.port != config["port"]:
@@ -223,6 +231,9 @@ def gen_args(args_to_parse: list[str]|None = None):
if hasattr(args, 'host') and args.host != config["host"]: if hasattr(args, 'host') and args.host != config["host"]:
config["host"] = args.host config["host"] = args.host
config_changed = True config_changed = True
if hasattr(args, 'socket_dir') and args.socket_dir != config["socket_dir"]:
config["socket_dir"] = args.socket_dir
config_changed = True
if config_changed: if config_changed:
save_config(config) save_config(config)
@@ -241,10 +252,9 @@ def is_linux():
return "linux" in sys.platform and 'microsoft-standard' not in platform.uname().release return "linux" in sys.platform and 'microsoft-standard' not in platform.uname().release
def get_web_interface_url(): def get_web_interface_url():
# In modalità host network (Linux), l'host configurato non è applicabile if args.socket_dir:
# quindi usiamo sempre localhost return os.path.join(args.socket_dir, "firegex.sock")
if is_linux():
return f"http://localhost:{args.port}"
# Per altre piattaforme, usiamo l'host configurato se non è 0.0.0.0 # Per altre piattaforme, usiamo l'host configurato se non è 0.0.0.0
# altrimenti usiamo localhost per evitare confusione # altrimenti usiamo localhost per evitare confusione
display_host = "localhost" if args.host == "0.0.0.0" else args.host display_host = "localhost" if args.host == "0.0.0.0" else args.host
@@ -266,7 +276,8 @@ def write_compose(skip_password = True):
f"PORT={args.port}", f"PORT={args.port}",
f"HOST={args.host}", f"HOST={args.host}",
f"NTHREADS={args.threads}", f"NTHREADS={args.threads}",
*([f"PSW_HASH_SET={hash_psw(psw_set)}"] if psw_set else []) *([f"PSW_HASH_SET={hash_psw(psw_set)}"] if psw_set else []),
*([f"SOCKET_DIR=/run/firegex"] if args.socket_dir else [])
], ],
"volumes": [ "volumes": [
"firegex_data:/execute/db", "firegex_data:/execute/db",
@@ -289,7 +300,12 @@ def write_compose(skip_password = True):
"type": "bind", "type": "bind",
"source": "/proc/sys/net/ipv6/conf/all/forwarding", "source": "/proc/sys/net/ipv6/conf/all/forwarding",
"target": "/sys_host/net.ipv6.conf.all.forwarding" "target": "/sys_host/net.ipv6.conf.all.forwarding"
} },
*([{
"type": "bind",
"source": args.socket_dir,
"target": "/run/firegex"
}] if args.socket_dir else [])
], ],
"cap_add": [ "cap_add": [
"NET_ADMIN", "NET_ADMIN",
@@ -768,6 +784,10 @@ def run_standalone():
if psw_set: if psw_set:
env_vars.append(f"PSW_HASH_SET={hash_psw(psw_set)}") env_vars.append(f"PSW_HASH_SET={hash_psw(psw_set)}")
# Add socket dir if set
if args.socket_dir:
env_vars.append(f"SOCKET_DIR={args.socket_dir}")
# Prepare environment string for chroot # Prepare environment string for chroot
env_string = " ".join([f"{var}" for var in env_vars]) env_string = " ".join([f"{var}" for var in env_vars])
@@ -846,6 +866,7 @@ def handle_config_command(args):
puts("Current configuration:", color=colors.cyan, is_bold=True) puts("Current configuration:", color=colors.cyan, is_bold=True)
puts(f"Port: {config['port']}", color=colors.white) puts(f"Port: {config['port']}", color=colors.white)
puts(f"Host: {config['host']}", color=colors.white) puts(f"Host: {config['host']}", color=colors.white)
puts(f"Socket dir: {config['socket_dir']}", color=colors.white)
puts(f"Config file: {g.configfile}", color=colors.white) puts(f"Config file: {g.configfile}", color=colors.white)
return return
@@ -862,6 +883,11 @@ def handle_config_command(args):
config_changed = True config_changed = True
puts(f"Host set to: {args.host}", color=colors.green) puts(f"Host set to: {args.host}", color=colors.green)
if hasattr(args, 'socket_dir') and args.socket_dir is not None:
config["socket_dir"] = args.socket_dir
config_changed = True
puts(f"Socket dir set to: {args.socket_dir}", color=colors.green)
if config_changed: if config_changed:
if save_config(config): if save_config(config):
puts(f"Configuration saved to {g.configfile}", color=colors.green) puts(f"Configuration saved to {g.configfile}", color=colors.green)