fix(haproxy,mitmproxy): Fix config reload and preserve Host header

haproxyctl:
- Copy generated config to /etc/haproxy/ inside container before reload
- HAProxy reads from /etc/haproxy/haproxy.cfg, not /opt/haproxy/config/

mitmproxy haproxy_router.py:
- Save original Host header before setting backend destination
- Restore Host header after routing to preserve it for backend validation
- Fixes PeerTube OAuth and other apps that validate Host header

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
CyberMind-FR 2026-02-15 07:40:20 +01:00
parent 1a8beb45e0
commit f3f6eb4e4b
4 changed files with 56 additions and 4 deletions

View File

@ -1749,3 +1749,27 @@ git checkout HEAD -- index.html
- HAProxy configuration status with configure button - HAProxy configuration status with configure button
- Emancipate form for public exposure - Emancipate form for public exposure
- Logs viewer with refresh button - Logs viewer with refresh button
### 2026-02-15: Generative LuCI Navigation Tree
- **Created luci.secubox-portal RPCD backend** for dynamic component discovery
- `get_tree`: Auto-discovers all `luci-app-*` packages, groups by category
- `get_containers`: Lists LXC containers from `/srv/lxc/` with running state
- `get_vhosts`: Lists HAProxy vhosts from UCI with domain/backend/ssl info
- Categories: SecuBox Core, Security, Media & Streaming, Network & Proxy, Development & CMS, IoT & Home, AI & Communication, System & Management, Other SecuBox Apps
- **Updated luci-tree.js** with dynamic RPC-based interface
- Three tabs: LuCI Apps, Containers, Vhosts
- Refresh button for live updates without page reload
- Stats row showing categories, links, packages, containers, vhosts counts
- Search functionality for filtering modules
- Cyberpunk dark theme with green/cyan accents
- **ACL permissions** for unauthenticated portal access to tree methods
### 2026-02-15: PeerTube Configuration Fixes
- **Redis ARM64-COW-BUG**: Added `ignore-warnings ARM64-COW-BUG` to redis.conf
- **Redis sentinel**: Disabled (using standalone Redis, not sentinel cluster)
- **RTMPS**: Disabled (no SSL key file needed for live streaming)
- **HAProxy WAF bypass**: Added `waf_bypass=1` to tube.gk2.secubox.in vhost
- Without bypass, mitmproxy WAF stripped Host header causing OAuth errors
- PeerTube validates requests against configured webserver.hostname
- **Listen hostname**: Set to `0.0.0.0` (not domain name) for proper binding
- **Webserver hostname**: Set to `tube.gk2.secubox.in` for OAuth validation

View File

@ -1,6 +1,6 @@
# Work In Progress (Claude) # Work In Progress (Claude)
_Last updated: 2026-02-14 (WAF architecture configured)_ _Last updated: 2026-02-15 (PeerTube + Generative LuCI Tree)_
> **Architecture Reference**: SecuBox Fanzine v3 — Les 4 Couches > **Architecture Reference**: SecuBox Fanzine v3 — Les 4 Couches
@ -74,16 +74,35 @@ _Last updated: 2026-02-14 (WAF architecture configured)_
- User management: create-user, reset-password, list-users - User management: create-user, reset-password, list-users
- Backup/restore PostgreSQL database - Backup/restore PostgreSQL database
- UCI config: main, server, live, transcoding, storage, network, admin sections - UCI config: main, server, live, transcoding, storage, network, admin sections
- Fixed: Redis ARM64-COW-BUG via `ignore-warnings` config
- Fixed: Redis sentinel disabled (using standalone Redis)
- Fixed: RTMPS disabled (no SSL keys needed)
- Fixed: HAProxy waf_bypass=1 for proper OAuth routing
- **PeerTube LuCI Dashboard** — DONE (2026-02-15) - **PeerTube LuCI Dashboard** — DONE (2026-02-15)
- Created `luci-app-peertube` package - Created `luci-app-peertube` package
- RPCD handler with 11 methods: status, start, stop, install, uninstall, update, logs, emancipate, live_enable, live_disable, configure_haproxy - RPRD handler with 11 methods: status, start, stop, install, uninstall, update, logs, emancipate, live_enable, live_disable, configure_haproxy
- Dashboard with install wizard, status display, service controls - Dashboard with install wizard, status display, service controls
- Live streaming toggle with firewall integration - Live streaming toggle with firewall integration
- HAProxy configuration button - HAProxy configuration button
- Emancipate form for public exposure - Emancipate form for public exposure
- Logs viewer with refresh - Logs viewer with refresh
- **Generative LuCI Tree** — DONE (2026-02-15)
- Created `luci.secubox-portal` RPCD backend for dynamic component discovery
- Three RPC methods: get_tree, get_containers, get_vhosts
- Auto-discovers all installed `luci-app-*` packages and groups by category:
- SecuBox Core, Security, Media & Streaming, Network & Proxy
- Development & CMS, IoT & Home, AI & Communication, System & Management
- Discovers LXC containers from `/srv/lxc/` with running state
- Discovers HAProxy vhosts from UCI with domain/backend/ssl info
- Updated `luci-tree.js` with:
- Three tabs: LuCI Apps, Containers, Vhosts
- Refresh button for live updates
- Stats showing packages, containers, vhosts counts
- Search functionality for filtering
- ACL permissions for unauthenticated portal access
### Just Completed (2026-02-14) ### Just Completed (2026-02-14)
- **mitmproxy WAF Wildcard Route Priority Fix** — DONE (2026-02-14) - **mitmproxy WAF Wildcard Route Priority Fix** — DONE (2026-02-14)

View File

@ -1821,6 +1821,8 @@ cmd_reload() {
generate_config generate_config
log_info "Reloading HAProxy configuration..." log_info "Reloading HAProxy configuration..."
# Copy generated config to container's /etc/haproxy/ (HAProxy reads from there)
lxc_exec cp /opt/haproxy/config/haproxy.cfg /etc/haproxy/haproxy.cfg
# HAProxy in master-worker mode (-W) reloads gracefully on SIGUSR2 # HAProxy in master-worker mode (-W) reloads gracefully on SIGUSR2
# Fallback to SIGHUP if USR2 fails # Fallback to SIGHUP if USR2 fails
lxc_exec killall -USR2 haproxy 2>/dev/null || \ lxc_exec killall -USR2 haproxy 2>/dev/null || \

View File

@ -116,12 +116,19 @@ class HaproxyRouter:
host = flow.request.host_header or flow.request.host host = flow.request.host_header or flow.request.host
backend = self._get_backend(host) backend = self._get_backend(host)
# Set the upstream server # Save original Host header before routing
original_host_header = flow.request.headers.get("Host", host)
# Set the upstream server (changes internal routing destination)
flow.request.host = backend[0] flow.request.host = backend[0]
flow.request.port = backend[1] flow.request.port = backend[1]
# CRITICAL: Restore original Host header for backend validation
# Many backends (PeerTube OAuth, etc.) validate Host header against config
flow.request.headers["Host"] = original_host_header
# Log routing decision # Log routing decision
ctx.log.debug(f"ROUTE: {host} -> {backend[0]}:{backend[1]}") ctx.log.debug(f"ROUTE: {host} -> {backend[0]}:{backend[1]} (Host: {original_host_header})")
# Store original host for analytics # Store original host for analytics
flow.metadata['original_host'] = host flow.metadata['original_host'] = host