mirror of
https://github.com/Av0idD4rk/firegex.git
synced 2026-10-25 11:39:25 +00:00
minor adjustments + network address based access control
This commit is contained in:
parent
4f62a7c7c9
commit
4125eff93f
@ -16,7 +16,7 @@ from fastapi.middleware.cors import CORSMiddleware
|
|||||||
import socketio
|
import socketio
|
||||||
from socketio.exceptions import ConnectionRefusedError
|
from socketio.exceptions import ConnectionRefusedError
|
||||||
import hashlib
|
import hashlib
|
||||||
|
from ipaddress import ip_network, ip_address
|
||||||
# DB init
|
# DB init
|
||||||
db = SQLite('db/firegex.db')
|
db = SQLite('db/firegex.db')
|
||||||
sysctl = SysctlManager({
|
sysctl = SysctlManager({
|
||||||
@ -34,6 +34,51 @@ async def lifespan(app):
|
|||||||
yield
|
yield
|
||||||
await shutdown_main()
|
await shutdown_main()
|
||||||
|
|
||||||
|
ALLOWED_NETWORKS = [ip_network(ip.strip(), strict=False) for ip in os.getenv("ALLOWED_IPS", "").split(",") if ip.strip()]
|
||||||
|
PROXY_IP_HEADER = os.getenv("PROXY_IP_HEADER", "")
|
||||||
|
|
||||||
|
class IPFilterMiddleware:
|
||||||
|
def __init__(self, app):
|
||||||
|
self.app = app
|
||||||
|
|
||||||
|
async def __call__(self, scope, receive, send):
|
||||||
|
if scope["type"] in ["http", "websocket"]:
|
||||||
|
if ALLOWED_NETWORKS:
|
||||||
|
client_ip = None
|
||||||
|
if PROXY_IP_HEADER:
|
||||||
|
headers = dict(scope.get("headers", []))
|
||||||
|
header_val = headers.get(PROXY_IP_HEADER.lower().encode())
|
||||||
|
if header_val:
|
||||||
|
client_ip = header_val.decode().split(",")[0].strip()
|
||||||
|
|
||||||
|
if not client_ip and scope.get("client"):
|
||||||
|
client_ip = scope["client"][0]
|
||||||
|
|
||||||
|
if client_ip:
|
||||||
|
try:
|
||||||
|
ip_obj = ip_address(client_ip)
|
||||||
|
if not any(ip_obj in net for net in ALLOWED_NETWORKS):
|
||||||
|
if scope["type"] == "http":
|
||||||
|
await send({
|
||||||
|
"type": "http.response.start",
|
||||||
|
"status": 403,
|
||||||
|
"headers": [(b"content-type", b"text/plain")],
|
||||||
|
})
|
||||||
|
await send({
|
||||||
|
"type": "http.response.body",
|
||||||
|
"body": b"Forbidden",
|
||||||
|
})
|
||||||
|
elif scope["type"] == "websocket":
|
||||||
|
await send({
|
||||||
|
"type": "websocket.close",
|
||||||
|
"code": 1008
|
||||||
|
})
|
||||||
|
return
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
await self.app(scope, receive, send)
|
||||||
|
|
||||||
app = FastAPI(
|
app = FastAPI(
|
||||||
debug=DEBUG,
|
debug=DEBUG,
|
||||||
redoc_url=None,
|
redoc_url=None,
|
||||||
@ -42,6 +87,7 @@ app = FastAPI(
|
|||||||
title="Firegex API",
|
title="Firegex API",
|
||||||
version=API_VERSION,
|
version=API_VERSION,
|
||||||
)
|
)
|
||||||
|
app.add_middleware(IPFilterMiddleware)
|
||||||
|
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
app.add_middleware(
|
app.add_middleware(
|
||||||
@ -64,17 +110,23 @@ app.mount("/sock", sio_app)
|
|||||||
def APP_STATUS(): return "init" if db.get("password") is None else "run"
|
def APP_STATUS(): return "init" if db.get("password") is None else "run"
|
||||||
def JWT_SECRET(): return db.get("secret")
|
def JWT_SECRET(): return db.get("secret")
|
||||||
|
|
||||||
def hash_psw(psw: str):
|
def _hash_psw_sync(psw: str) -> str:
|
||||||
salt = secrets.token_hex(32)
|
salt = secrets.token_hex(32)
|
||||||
return hashlib.pbkdf2_hmac("sha256", psw.encode(), salt.encode(), 500_000).hex()+"-"+salt
|
return hashlib.pbkdf2_hmac("sha256", psw.encode(), salt.encode(), 500_000).hex()+"-"+salt
|
||||||
|
|
||||||
def verify_psw(psw: str, hashed: str) -> bool:
|
async def hash_psw(psw: str) -> str:
|
||||||
|
return await asyncio.to_thread(_hash_psw_sync, psw)
|
||||||
|
|
||||||
|
def _verify_psw_sync(psw: str, hashed: str) -> bool:
|
||||||
psw_hash, salt = hashed.split("-")
|
psw_hash, salt = hashed.split("-")
|
||||||
new_hashed = hashlib.pbkdf2_hmac("sha256", psw.encode(), salt.encode(), 500_000).hex()
|
new_hashed = hashlib.pbkdf2_hmac("sha256", psw.encode(), salt.encode(), 500_000).hex()
|
||||||
return new_hashed == psw_hash
|
return new_hashed == psw_hash
|
||||||
|
|
||||||
def set_psw(psw: str):
|
async def verify_psw(psw: str, hashed: str) -> bool:
|
||||||
db.put("password", hash_psw(psw))
|
return await asyncio.to_thread(_verify_psw_sync, psw, hashed)
|
||||||
|
|
||||||
|
async def set_psw(psw: str):
|
||||||
|
db.put("password", await hash_psw(psw))
|
||||||
|
|
||||||
def create_access_token(data: dict):
|
def create_access_token(data: dict):
|
||||||
to_encode = data.copy()
|
to_encode = data.copy()
|
||||||
@ -144,7 +196,7 @@ async def login_api(form: OAuth2PasswordRequestForm = Depends()):
|
|||||||
if form.password == "":
|
if form.password == "":
|
||||||
return {"status":"Cannot insert an empty password!"}
|
return {"status":"Cannot insert an empty password!"}
|
||||||
await asyncio.sleep(0.3) # No bruteforce :)
|
await asyncio.sleep(0.3) # No bruteforce :)
|
||||||
if verify_psw(form.password, db.get("password")):
|
if await verify_psw(form.password, db.get("password")):
|
||||||
return {"access_token": create_access_token({"logged_in": True}), "token_type": "bearer"}
|
return {"access_token": create_access_token({"logged_in": True}), "token_type": "bearer"}
|
||||||
raise HTTPException(406,"Wrong password!")
|
raise HTTPException(406,"Wrong password!")
|
||||||
|
|
||||||
@ -156,7 +208,7 @@ async def set_password(form: PasswordForm):
|
|||||||
raise HTTPException(status_code=400)
|
raise HTTPException(status_code=400)
|
||||||
if form.password == "":
|
if form.password == "":
|
||||||
return {"status":"Cannot insert an empty password!"}
|
return {"status":"Cannot insert an empty password!"}
|
||||||
set_psw(form.password)
|
await set_psw(form.password)
|
||||||
await refresh_frontend()
|
await refresh_frontend()
|
||||||
return {"status":"ok", "access_token": create_access_token({"logged_in": True})}
|
return {"status":"ok", "access_token": create_access_token({"logged_in": True})}
|
||||||
|
|
||||||
@ -172,7 +224,7 @@ async def change_password(form: PasswordChangeForm):
|
|||||||
db.put("secret", secrets.token_hex(32))
|
db.put("secret", secrets.token_hex(32))
|
||||||
await disconnect_all()
|
await disconnect_all()
|
||||||
|
|
||||||
set_psw(form.password)
|
await set_psw(form.password)
|
||||||
await refresh_frontend()
|
await refresh_frontend()
|
||||||
return {"status":"ok", "access_token": create_access_token({"logged_in": True})}
|
return {"status":"ok", "access_token": create_access_token({"logged_in": True})}
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,23 @@ public:
|
|||||||
PktRequest<Derived>* pkt;
|
PktRequest<Derived>* pkt;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
queue.take(pkt);
|
queue.take(pkt);
|
||||||
static_cast<Derived*>(this)->handle_next_packet(pkt);
|
try {
|
||||||
|
static_cast<Derived*>(this)->handle_next_packet(pkt);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
std::cerr << "[error] Exception handling packet: " << e.what() << std::endl;
|
||||||
|
if (pkt->get_action() == FilterAction::NOACTION) {
|
||||||
|
try {
|
||||||
|
pkt->accept();
|
||||||
|
} catch (...) {}
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
std::cerr << "[error] Unknown exception handling packet" << std::endl;
|
||||||
|
if (pkt->get_action() == FilterAction::NOACTION) {
|
||||||
|
try {
|
||||||
|
pkt->accept();
|
||||||
|
} catch (...) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
delete pkt;
|
delete pkt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -530,14 +530,22 @@ class NfQueue {
|
|||||||
return MNL_CB_ERROR;
|
return MNL_CB_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct nfqnl_msg_packet_hdr *ph = (nfqnl_msg_packet_hdr*) mnl_attr_get_payload(attr[NFQA_PACKET_HDR]);
|
||||||
|
struct nfgenmsg *nfg = (nfgenmsg *)mnl_nlmsg_get_payload(nlh);
|
||||||
|
|
||||||
|
if (attr[NFQA_PAYLOAD] == nullptr) {
|
||||||
|
cerr << "[error] [NfQueue._real_queue_cb] payload not set" << endl;
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
struct nlmsghdr *nlh_verdict = nfq_nlmsg_put(buf, NFQNL_MSG_VERDICT, ntohs(nfg->res_id));
|
||||||
|
nfq_nlmsg_verdict_put(nlh_verdict, ntohl(ph->packet_id), NF_ACCEPT);
|
||||||
|
mnl_socket_sendto(info->nl, nlh_verdict, nlh_verdict->nlmsg_len);
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
//Get Payload
|
//Get Payload
|
||||||
uint16_t plen = mnl_attr_get_payload_len(attr[NFQA_PAYLOAD]);
|
uint16_t plen = mnl_attr_get_payload_len(attr[NFQA_PAYLOAD]);
|
||||||
char *payload = (char *)mnl_attr_get_payload(attr[NFQA_PAYLOAD]);
|
char *payload = (char *)mnl_attr_get_payload(attr[NFQA_PAYLOAD]);
|
||||||
|
|
||||||
//Return result to the kernel
|
|
||||||
struct nfqnl_msg_packet_hdr *ph = (nfqnl_msg_packet_hdr*) mnl_attr_get_payload(attr[NFQA_PACKET_HDR]);
|
|
||||||
struct nfgenmsg *nfg = (nfgenmsg *)mnl_nlmsg_get_payload(nlh);
|
|
||||||
|
|
||||||
bool is_input = ntohl(mnl_attr_get_u32(attr[NFQA_MARK])) & 0x1; // == 0x1337 that is odd
|
bool is_input = ntohl(mnl_attr_get_u32(attr[NFQA_MARK])) & 0x1; // == 0x1337 that is odd
|
||||||
handle_func(new PktRequest<D>(
|
handle_func(new PktRequest<D>(
|
||||||
payload, plen, (D*)info->data, info->nl, nfg, ph, is_input
|
payload, plen, (D*)info->data, info->nl, nfg, ph, is_input
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import sqlite3
|
|||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from modules.nfproxy.nftables import FiregexTables
|
from modules.nfproxy.nftables import FiregexTables
|
||||||
from modules.nfproxy.firewall import STATUS, FirewallManager
|
from modules.nfproxy.firewall import STATUS, FirewallManager, ServiceNotFoundException
|
||||||
from utils.sqlite import SQLite
|
from utils.sqlite import SQLite
|
||||||
from utils import ip_parse, refactor_name, socketio_emit, PortType
|
from utils import ip_parse, refactor_name, socketio_emit, PortType
|
||||||
from utils.models import ResetRequest, StatusMessageModel
|
from utils.models import ResetRequest, StatusMessageModel
|
||||||
@ -373,9 +373,13 @@ async def join_outstream(sid, data):
|
|||||||
"""Client joins a room."""
|
"""Client joins a room."""
|
||||||
srv = data.get("service")
|
srv = data.get("service")
|
||||||
if srv:
|
if srv:
|
||||||
room = f"nfproxy-outstream-{srv}"
|
try:
|
||||||
await utils.socketio.enter_room(sid, room)
|
srv_manager = firewall.get(srv)
|
||||||
await utils.socketio.emit(room, firewall.get(srv).read_outstrem_buffer(), room=sid)
|
room = f"nfproxy-outstream-{srv}"
|
||||||
|
await utils.socketio.enter_room(sid, room)
|
||||||
|
await utils.socketio.emit(room, srv_manager.read_outstrem_buffer(), room=sid)
|
||||||
|
except ServiceNotFoundException:
|
||||||
|
pass
|
||||||
|
|
||||||
async def leave_outstream(sid, data):
|
async def leave_outstream(sid, data):
|
||||||
"""Client leaves a room."""
|
"""Client leaves a room."""
|
||||||
@ -387,9 +391,13 @@ async def join_exception(sid, data):
|
|||||||
"""Client joins a room."""
|
"""Client joins a room."""
|
||||||
srv = data.get("service")
|
srv = data.get("service")
|
||||||
if srv:
|
if srv:
|
||||||
room = f"nfproxy-exception-{srv}"
|
try:
|
||||||
await utils.socketio.enter_room(sid, room)
|
srv_manager = firewall.get(srv)
|
||||||
await utils.socketio.emit(room, firewall.get(srv).last_exception_time, room=sid)
|
room = f"nfproxy-exception-{srv}"
|
||||||
|
await utils.socketio.enter_room(sid, room)
|
||||||
|
await utils.socketio.emit(room, srv_manager.last_exception_time, room=sid)
|
||||||
|
except ServiceNotFoundException:
|
||||||
|
pass
|
||||||
|
|
||||||
async def leave_exception(sid, data):
|
async def leave_exception(sid, data):
|
||||||
"""Client leaves a room."""
|
"""Client leaves a room."""
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import { Firewall } from './pages/Firewall';
|
|||||||
import { useQueryClient } from '@tanstack/react-query';
|
import { useQueryClient } from '@tanstack/react-query';
|
||||||
import NFProxy from './pages/NFProxy';
|
import NFProxy from './pages/NFProxy';
|
||||||
import ServiceDetailsNFProxy from './pages/NFProxy/ServiceDetails';
|
import ServiceDetailsNFProxy from './pages/NFProxy/ServiceDetails';
|
||||||
import { useAuthStore } from './js/store';
|
import { useAuthStore, useSystemStore } from './js/store';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
|
||||||
@ -24,6 +24,7 @@ function App() {
|
|||||||
const [loadinBtn, setLoadingBtn] = useState(false);
|
const [loadinBtn, setLoadingBtn] = useState(false);
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const { access_token } = useAuthStore()
|
const { access_token } = useAuthStore()
|
||||||
|
const { setVersion } = useSystemStore()
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
socketio.auth = { token: access_token || "" }
|
socketio.auth = { token: access_token || "" }
|
||||||
@ -48,6 +49,7 @@ function App() {
|
|||||||
const getStatus = () =>{
|
const getStatus = () =>{
|
||||||
getstatus().then( res =>{
|
getstatus().then( res =>{
|
||||||
setSystemStatus(res)
|
setSystemStatus(res)
|
||||||
|
setVersion(res.version || "unknown")
|
||||||
setReqError(undefined)
|
setReqError(undefined)
|
||||||
}).catch(err=>{
|
}).catch(err=>{
|
||||||
setReqError(err.toString())
|
setReqError(err.toString())
|
||||||
|
|||||||
@ -9,13 +9,14 @@ import { ImExit } from 'react-icons/im';
|
|||||||
import ResetPasswordModal from './ResetPasswordModal';
|
import ResetPasswordModal from './ResetPasswordModal';
|
||||||
import ResetModal from './ResetModal';
|
import ResetModal from './ResetModal';
|
||||||
import { MenuDropDownWithButton } from '../MainLayout';
|
import { MenuDropDownWithButton } from '../MainLayout';
|
||||||
import { useNavbarStore } from '../../js/store';
|
import { useNavbarStore, useSystemStore } from '../../js/store';
|
||||||
|
|
||||||
|
|
||||||
function HeaderPage(props: any) {
|
function HeaderPage(props: any) {
|
||||||
|
|
||||||
const navigator = useNavigate()
|
const navigator = useNavigate()
|
||||||
const { navOpened, toggleNav } = useNavbarStore()
|
const { navOpened, toggleNav } = useNavbarStore()
|
||||||
|
const { version } = useSystemStore()
|
||||||
|
|
||||||
const logout_action = () => {
|
const logout_action = () => {
|
||||||
logout().then(r => {
|
logout().then(r => {
|
||||||
@ -48,7 +49,7 @@ function HeaderPage(props: any) {
|
|||||||
</Box>
|
</Box>
|
||||||
<Box display="flex" style={{ flexDirection: "column" }} visibleFrom='xs'>
|
<Box display="flex" style={{ flexDirection: "column" }} visibleFrom='xs'>
|
||||||
<Title order={2} >[Fi]*regex</Title>
|
<Title order={2} >[Fi]*regex</Title>
|
||||||
<p style={{margin: 0, fontSize: "70%"}}>By <a href="https://pwnzer0tt1.it">Pwnzer0tt1</a></p>
|
<p style={{margin: 0, fontSize: "70%"}}>By <a href="https://pwnzer0tt1.it">Pwnzer0tt1</a> {version && <span style={{marginLeft: "5px", color: "gray"}}>{version}</span>}</p>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
|||||||
@ -5,16 +5,17 @@ import NavBar from './NavBar';
|
|||||||
import HeaderPage from './Header';
|
import HeaderPage from './Header';
|
||||||
import { getMainPath } from '../js/utils';
|
import { getMainPath } from '../js/utils';
|
||||||
import { useLocation } from 'react-router';
|
import { useLocation } from 'react-router';
|
||||||
import { useNavbarStore } from '../js/store';
|
import { useNavbarStore, useSessionStore } from '../js/store';
|
||||||
import { HiMenu } from "react-icons/hi";
|
import { HiMenu } from "react-icons/hi";
|
||||||
|
|
||||||
|
|
||||||
function MainLayout({ children }:{ children:any }) {
|
function MainLayout({ children }:{ children:any }) {
|
||||||
const { navOpened } = useNavbarStore()
|
const { navOpened } = useNavbarStore()
|
||||||
|
const { setHomeSection } = useSessionStore()
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
if (location.pathname !== "/"){
|
if (location.pathname !== "/"){
|
||||||
sessionStorage.setItem('home_section', getMainPath())
|
setHomeSection(getMainPath())
|
||||||
}
|
}
|
||||||
},[location.pathname])
|
},[location.pathname])
|
||||||
return <AppShell
|
return <AppShell
|
||||||
|
|||||||
@ -15,7 +15,8 @@ export type LoginResponse = {
|
|||||||
|
|
||||||
export type ServerStatusResponse = {
|
export type ServerStatusResponse = {
|
||||||
status:string,
|
status:string,
|
||||||
loggined:boolean
|
loggined:boolean,
|
||||||
|
version?:string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PasswordSend = {
|
export type PasswordSend = {
|
||||||
|
|||||||
@ -73,3 +73,13 @@ export const useSession = () => {
|
|||||||
getHomeSection,
|
getHomeSection,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface SystemState {
|
||||||
|
version: string | null;
|
||||||
|
setVersion: (version: string | null) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSystemStore = create<SystemState>()((set) => ({
|
||||||
|
version: null,
|
||||||
|
setVersion: (version) => set({ version }),
|
||||||
|
}));
|
||||||
|
|||||||
29
run.py
29
run.py
@ -103,7 +103,9 @@ def load_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
|
"socket_dir": None,
|
||||||
|
"allowed_ips": None,
|
||||||
|
"proxy_ip_header": None
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.path.isfile(g.configfile):
|
if os.path.isfile(g.configfile):
|
||||||
@ -156,6 +158,8 @@ def gen_args(args_to_parse: list[str]|None = None):
|
|||||||
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('--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('--allowed-ips', required=False, type=str, help=f'Comma-separated list of CIDR addresses allowed to contact firegex (default from config: {config.get("allowed_ips")})', default=config.get("allowed_ips"))
|
||||||
|
parser_start.add_argument('--proxy-ip-header', required=False, type=str, help=f'Header name to read the client IP from (default from config: {config.get("proxy_ip_header")})', default=config.get("proxy_ip_header"))
|
||||||
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)
|
||||||
@ -170,6 +174,8 @@ def gen_args(args_to_parse: list[str]|None = None):
|
|||||||
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('--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('--allowed-ips', required=False, type=str, help=f'Comma-separated list of CIDR addresses allowed to contact firegex (default from config: {config.get("allowed_ips")})', default=config.get("allowed_ips"))
|
||||||
|
parser_restart.add_argument('--proxy-ip-header', required=False, type=str, help=f'Header name to read the client IP from (default from config: {config.get("proxy_ip_header")})', default=config.get("proxy_ip_header"))
|
||||||
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)
|
||||||
|
|
||||||
@ -185,6 +191,8 @@ def gen_args(args_to_parse: list[str]|None = None):
|
|||||||
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('--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('--allowed-ips', required=False, type=str, help=f'Comma-separated list of CIDR addresses allowed to contact firegex (default from config: {config.get("allowed_ips")})', default=config.get("allowed_ips"))
|
||||||
|
parser_config.add_argument('--proxy-ip-header', required=False, type=str, help=f'Header name to read the client IP from (default from config: {config.get("proxy_ip_header")})', default=config.get("proxy_ip_header"))
|
||||||
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)
|
||||||
|
|
||||||
@ -234,6 +242,12 @@ def gen_args(args_to_parse: list[str]|None = None):
|
|||||||
if hasattr(args, 'socket_dir') and args.socket_dir != config["socket_dir"]:
|
if hasattr(args, 'socket_dir') and args.socket_dir != config["socket_dir"]:
|
||||||
config["socket_dir"] = args.socket_dir
|
config["socket_dir"] = args.socket_dir
|
||||||
config_changed = True
|
config_changed = True
|
||||||
|
if hasattr(args, 'allowed_ips') and args.allowed_ips != config.get("allowed_ips"):
|
||||||
|
config["allowed_ips"] = args.allowed_ips
|
||||||
|
config_changed = True
|
||||||
|
if hasattr(args, 'proxy_ip_header') and args.proxy_ip_header != config.get("proxy_ip_header"):
|
||||||
|
config["proxy_ip_header"] = args.proxy_ip_header
|
||||||
|
config_changed = True
|
||||||
|
|
||||||
if config_changed:
|
if config_changed:
|
||||||
save_config(config)
|
save_config(config)
|
||||||
@ -335,7 +349,9 @@ def write_compose(skip_password = True):
|
|||||||
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 []),
|
||||||
*(["SOCKET_DIR=/run/firegex"] if args.socket_dir else []),
|
*(["SOCKET_DIR=/run/firegex"] if args.socket_dir else []),
|
||||||
*([f"FIREGEX_VERSION={get_git_version()}"] if get_git_version() else [])
|
*([f"FIREGEX_VERSION={get_git_version()}"] if get_git_version() else []),
|
||||||
|
*([f"ALLOWED_IPS={args.allowed_ips}"] if getattr(args, 'allowed_ips', None) else []),
|
||||||
|
*([f"PROXY_IP_HEADER={args.proxy_ip_header}"] if getattr(args, 'proxy_ip_header', None) else [])
|
||||||
],
|
],
|
||||||
"volumes": [
|
"volumes": [
|
||||||
"firegex_data:/execute/db",
|
"firegex_data:/execute/db",
|
||||||
@ -389,7 +405,9 @@ def write_compose(skip_password = True):
|
|||||||
f"PORT={args.port}",
|
f"PORT={args.port}",
|
||||||
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"FIREGEX_VERSION={get_git_version()}"] if get_git_version() else [])
|
*([f"FIREGEX_VERSION={get_git_version()}"] if get_git_version() else []),
|
||||||
|
*([f"ALLOWED_IPS={args.allowed_ips}"] if getattr(args, 'allowed_ips', None) else []),
|
||||||
|
*([f"PROXY_IP_HEADER={args.proxy_ip_header}"] if getattr(args, 'proxy_ip_header', None) else [])
|
||||||
],
|
],
|
||||||
"volumes": [
|
"volumes": [
|
||||||
"firegex_data:/execute/db"
|
"firegex_data:/execute/db"
|
||||||
@ -854,6 +872,11 @@ def run_standalone():
|
|||||||
f"NTHREADS={args.threads}",
|
f"NTHREADS={args.threads}",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if getattr(args, 'allowed_ips', None):
|
||||||
|
env_vars.append(f"ALLOWED_IPS={args.allowed_ips}")
|
||||||
|
if getattr(args, 'proxy_ip_header', None):
|
||||||
|
env_vars.append(f"PROXY_IP_HEADER={args.proxy_ip_header}")
|
||||||
|
|
||||||
# Add password if set
|
# Add password if set
|
||||||
psw_set = get_password()
|
psw_set = get_password()
|
||||||
if psw_set:
|
if psw_set:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user