mirror of
https://github.com/CyberMind-FR/secubox-deb.git
synced 2026-06-30 05:27:24 +00:00
Compare commits
3 Commits
6dba5a08d6
...
da0c5008df
| Author | SHA1 | Date | |
|---|---|---|---|
| da0c5008df | |||
|
|
994b48f39d | ||
| e13cf925f1 |
|
|
@ -3,6 +3,22 @@
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 2026-06-15 — gitea mis-route fix + robust WAF route propagation
|
||||||
|
|
||||||
|
- **gitea (`git.maegia.tv`) 404 → 200.** Pure routing-table error: its WAF
|
||||||
|
route pointed at `192.168.1.200:8000` (unrelated nginx) instead of the gitea
|
||||||
|
LXC `10.100.0.40:3000`. Corrected the route; gitea container was healthy
|
||||||
|
throughout. (`gitea.gk2`→nginx:9080 and `git.gk2`→gitea:3000 were already OK.)
|
||||||
|
- **Robust route propagation (#609/PR #610, mitmproxy 1.0.8 + waf 1.2.6).**
|
||||||
|
Fixing gitea surfaced that the #603 *file* bind-mount binds an inode, so route
|
||||||
|
tools (`jq > tmp && mv` = new inode) didn't reach the addon until a container
|
||||||
|
restart. Now: **directory** bind-mount (host `/srv/mitmproxy` →
|
||||||
|
`/var/lib/secubox-waf-routes`, ro) + symlink, and the addon **live-reloads**
|
||||||
|
`haproxy-routes.json` on mtime change (10 s throttle, in `requestheaders`).
|
||||||
|
Verified live: `jq+mv` add → `[routes] live-reloaded 256 routes`, **0
|
||||||
|
restart**. Ported to source (both synced `secubox_waf.py` copies + wafctl) +
|
||||||
|
rebuilt into apt.secubox.in.
|
||||||
|
|
||||||
## 2026-06-15 — WAF hardening + perf: close open-proxy, behind-WAF media cache
|
## 2026-06-15 — WAF hardening + perf: close open-proxy, behind-WAF media cache
|
||||||
|
|
||||||
Follow-up to the WAF restoration. Three findings investigated; two fixed.
|
Follow-up to the WAF restoration. Three findings investigated; two fixed.
|
||||||
|
|
|
||||||
|
|
@ -688,6 +688,8 @@ ERROR_503_PAGE = b"""<!DOCTYPE html>
|
||||||
class SecuBoxWAF:
|
class SecuBoxWAF:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.routes = {}
|
self.routes = {}
|
||||||
|
self._routes_mtime = 0.0
|
||||||
|
self._last_route_check = 0.0
|
||||||
self.compiled_patterns = {}
|
self.compiled_patterns = {}
|
||||||
self.stats = {"requests": 0, "warnings": 0, "blocked": 0, "errors": 0}
|
self.stats = {"requests": 0, "warnings": 0, "blocked": 0, "errors": 0}
|
||||||
self.threat_counts = defaultdict(list) # IP -> list of timestamps
|
self.threat_counts = defaultdict(list) # IP -> list of timestamps
|
||||||
|
|
@ -925,7 +927,29 @@ class SecuBoxWAF:
|
||||||
except Exception:
|
except Exception:
|
||||||
ctx.log.warn(f"BAN FAILED for {ip} ({reason}) : LAPI off + cscli unavailable")
|
ctx.log.warn(f"BAN FAILED for {ip} ({reason}) : LAPI off + cscli unavailable")
|
||||||
|
|
||||||
|
def _maybe_reload_routes(self):
|
||||||
|
# #609 — live-reload haproxy-routes.json when it changes (throttled
|
||||||
|
# 10 s) so haproxyctl route edits take effect with NO restart. Pairs
|
||||||
|
# with the directory bind-mount that makes mv-replaced files visible.
|
||||||
|
import os as _o, time as _t
|
||||||
|
now = _t.time()
|
||||||
|
if now - getattr(self, "_last_route_check", 0) < 10:
|
||||||
|
return
|
||||||
|
self._last_route_check = now
|
||||||
|
try:
|
||||||
|
m = _o.path.getmtime(str(ROUTES_FILE))
|
||||||
|
except OSError:
|
||||||
|
return
|
||||||
|
if m != getattr(self, "_routes_mtime", 0):
|
||||||
|
self._routes_mtime = m
|
||||||
|
self.load_routes()
|
||||||
|
try:
|
||||||
|
ctx.log.info(f"[routes] live-reloaded {len(self.routes)} routes")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
def requestheaders(self, flow: http.HTTPFlow):
|
def requestheaders(self, flow: http.HTTPFlow):
|
||||||
|
self._maybe_reload_routes()
|
||||||
# #605 — mitmproxy 11 opens the upstream connection before request(),
|
# #605 — mitmproxy 11 opens the upstream connection before request(),
|
||||||
# so routing must happen here. ALSO: in --mode regular mitmproxy is a
|
# so routing must happen here. ALSO: in --mode regular mitmproxy is a
|
||||||
# forward proxy that would relay ANY Host, so internet scanners abused
|
# forward proxy that would relay ANY Host, so internet scanners abused
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,15 @@
|
||||||
|
secubox-mitmproxy (1.0.8-1~bookworm1) bookworm; urgency=medium
|
||||||
|
|
||||||
|
* fix(waf): live-reload haproxy-routes.json on change (#609). The addon now
|
||||||
|
re-reads the routes file when its mtime changes (throttled 10 s, in the
|
||||||
|
requestheaders hook), so haproxyctl route edits take effect with NO
|
||||||
|
restart. Pairs with the directory bind-mount in wafctl that replaced the
|
||||||
|
fragile file bind-mount (a file mount binds one inode → went stale when
|
||||||
|
route tools edit via `jq > tmp && mv`). Verified live: jq+mv add →
|
||||||
|
addon live-reloaded, 0 restart.
|
||||||
|
|
||||||
|
-- Gerald KERMA <devel@cybermind.fr> Mon, 15 Jun 2026 18:00:00 +0200
|
||||||
|
|
||||||
secubox-mitmproxy (1.0.7-1~bookworm1) bookworm; urgency=medium
|
secubox-mitmproxy (1.0.7-1~bookworm1) bookworm; urgency=medium
|
||||||
|
|
||||||
* feat(waf): behind-WAF media cache (#607). New media_cache.py addon caches
|
* feat(waf): behind-WAF media cache (#607). New media_cache.py addon caches
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,14 @@
|
||||||
|
secubox-waf (1.2.6-1~bookworm1) bookworm; urgency=medium
|
||||||
|
|
||||||
|
* fix(waf): robust route propagation (#609). wafctl now uses a DIRECTORY
|
||||||
|
bind-mount (host /srv/mitmproxy → /var/lib/secubox-waf-routes, ro) + a
|
||||||
|
symlink /data/mitmproxy/haproxy-routes.json → it, replacing the #603 file
|
||||||
|
bind-mount (which bound one inode and went stale on `mv`). With the addon
|
||||||
|
live-reload (synced secubox_waf.py copies), haproxyctl route edits apply
|
||||||
|
with no restart. Fixes the class of bug that left git.maegia.tv mis-routed.
|
||||||
|
|
||||||
|
-- Gerald KERMA <devel@cybermind.fr> Mon, 15 Jun 2026 18:00:00 +0200
|
||||||
|
|
||||||
secubox-waf (1.2.5-1~bookworm1) bookworm; urgency=medium
|
secubox-waf (1.2.5-1~bookworm1) bookworm; urgency=medium
|
||||||
|
|
||||||
* feat(waf): behind-WAF media cache (#607) — ship media_cache.py addon copy,
|
* feat(waf): behind-WAF media cache (#607) — ship media_cache.py addon copy,
|
||||||
|
|
|
||||||
|
|
@ -570,6 +570,8 @@ ERROR_503_PAGE = b"""<!DOCTYPE html>
|
||||||
class SecuBoxWAF:
|
class SecuBoxWAF:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.routes = {}
|
self.routes = {}
|
||||||
|
self._routes_mtime = 0.0
|
||||||
|
self._last_route_check = 0.0
|
||||||
self.compiled_patterns = {}
|
self.compiled_patterns = {}
|
||||||
self.stats = {"requests": 0, "warnings": 0, "blocked": 0, "errors": 0}
|
self.stats = {"requests": 0, "warnings": 0, "blocked": 0, "errors": 0}
|
||||||
self.threat_counts = defaultdict(list) # IP -> list of timestamps
|
self.threat_counts = defaultdict(list) # IP -> list of timestamps
|
||||||
|
|
@ -781,7 +783,29 @@ class SecuBoxWAF:
|
||||||
except Exception:
|
except Exception:
|
||||||
ctx.log.warn(f"BAN FAILED for {ip} ({reason})")
|
ctx.log.warn(f"BAN FAILED for {ip} ({reason})")
|
||||||
|
|
||||||
|
def _maybe_reload_routes(self):
|
||||||
|
# #609 — live-reload haproxy-routes.json when it changes (throttled
|
||||||
|
# 10 s) so haproxyctl route edits take effect with NO restart. Pairs
|
||||||
|
# with the directory bind-mount that makes mv-replaced files visible.
|
||||||
|
import os as _o, time as _t
|
||||||
|
now = _t.time()
|
||||||
|
if now - getattr(self, "_last_route_check", 0) < 10:
|
||||||
|
return
|
||||||
|
self._last_route_check = now
|
||||||
|
try:
|
||||||
|
m = _o.path.getmtime(str(ROUTES_FILE))
|
||||||
|
except OSError:
|
||||||
|
return
|
||||||
|
if m != getattr(self, "_routes_mtime", 0):
|
||||||
|
self._routes_mtime = m
|
||||||
|
self.load_routes()
|
||||||
|
try:
|
||||||
|
ctx.log.info(f"[routes] live-reloaded {len(self.routes)} routes")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
def requestheaders(self, flow: http.HTTPFlow):
|
def requestheaders(self, flow: http.HTTPFlow):
|
||||||
|
self._maybe_reload_routes()
|
||||||
# #605 — mitmproxy 11 opens the upstream connection before request(),
|
# #605 — mitmproxy 11 opens the upstream connection before request(),
|
||||||
# so routing must happen here. ALSO: in --mode regular mitmproxy is a
|
# so routing must happen here. ALSO: in --mode regular mitmproxy is a
|
||||||
# forward proxy that would relay ANY Host, so internet scanners abused
|
# forward proxy that would relay ANY Host, so internet scanners abused
|
||||||
|
|
|
||||||
|
|
@ -99,11 +99,13 @@ lxc.net.0.flags = up
|
||||||
lxc.net.0.ipv4.address = $LXC_IP/24
|
lxc.net.0.ipv4.address = $LXC_IP/24
|
||||||
lxc.net.0.ipv4.gateway = 10.100.0.1
|
lxc.net.0.ipv4.gateway = 10.100.0.1
|
||||||
|
|
||||||
# Routes: bind-mount the host-maintained haproxy routes into the path the WAF
|
# Routes: bind-mount the host-maintained haproxy routes DIRECTORY into the
|
||||||
# addon reads. Without this the addon loaded an empty/stale in-LXC copy
|
# container; the addon reads /data/mitmproxy/haproxy-routes.json via a symlink
|
||||||
# (routes_count: 0) so no upstream routing happened and every inspected vhost
|
# into it (created below). A *directory* mount (not a file mount) is required
|
||||||
# went to its public DNS IP. (#603)
|
# so route tools that edit via `jq > tmp && mv` (new inode) stay visible — a
|
||||||
lxc.mount.entry = /srv/mitmproxy/haproxy-routes.json data/mitmproxy/haproxy-routes.json none bind,create=file 0 0
|
# file mount binds one inode and goes stale on mv (#609, was #603). Combined
|
||||||
|
# with the addon's mtime live-reload, route edits apply with no restart.
|
||||||
|
lxc.mount.entry = /srv/mitmproxy var/lib/secubox-waf-routes none bind,ro,create=dir 0 0
|
||||||
|
|
||||||
# Autostart
|
# Autostart
|
||||||
lxc.start.auto = 1
|
lxc.start.auto = 1
|
||||||
|
|
@ -121,6 +123,10 @@ CONF
|
||||||
|
|
||||||
lxc-attach -n "$LXC_NAME" -- mkdir -p /opt/mitmproxy /data/mitmproxy /var/log/mitmproxy \
|
lxc-attach -n "$LXC_NAME" -- mkdir -p /opt/mitmproxy /data/mitmproxy /var/log/mitmproxy \
|
||||||
/data/mitmproxy/cache/media /data/mitmproxy/logs # #607 media cache + stats
|
/data/mitmproxy/cache/media /data/mitmproxy/logs # #607 media cache + stats
|
||||||
|
# #609 — addon reads /data/mitmproxy/haproxy-routes.json; point it at the
|
||||||
|
# routes dir bind-mount so mv-replaced files stay visible + live-reload.
|
||||||
|
lxc-attach -n "$LXC_NAME" -- ln -sfn /var/lib/secubox-waf-routes/haproxy-routes.json \
|
||||||
|
/data/mitmproxy/haproxy-routes.json
|
||||||
lxc-attach -n "$LXC_NAME" -- python3 -m venv /opt/mitmproxy
|
lxc-attach -n "$LXC_NAME" -- python3 -m venv /opt/mitmproxy
|
||||||
lxc-attach -n "$LXC_NAME" -- /opt/mitmproxy/bin/pip install mitmproxy
|
lxc-attach -n "$LXC_NAME" -- /opt/mitmproxy/bin/pip install mitmproxy
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user