feat(mitmproxy): Add headless mode to reduce RAM from 3.4GB to 96MB

- Add headless UCI option to use mitmdump instead of mitmweb
- Enable headless by default for WAF (mitmproxy-in) instance
- Increase default memory limit from 256MB to 2GB
- Fix LXC config generation to always recreate on service start
- Fix rootfs check path (/usr/local/bin not /usr/bin)
- Use exec in startup script for proper foreground execution

Headless mode runs mitmdump (CLI) instead of mitmweb (web UI),
saving ~3.3GB RAM while maintaining full WAF functionality.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
CyberMind-FR 2026-03-17 07:14:05 +01:00
parent 3fcad8e626
commit ece237d194
2 changed files with 70 additions and 38 deletions

View File

@ -6,8 +6,10 @@ config mitmproxy 'main'
option web_port '8081'
option web_host '0.0.0.0'
option data_path '/srv/mitmproxy'
option memory_limit '256M'
option memory_limit '2G'
option mode 'regular'
# Headless mode: use mitmproxy instead of mitmweb (saves ~3GB RAM)
option headless '0'
option ssl_insecure '0'
option anticache '0'
option anticomp '0'
@ -22,11 +24,13 @@ config instance 'out'
option web_port '8089'
option web_host '0.0.0.0'
option data_path '/srv/mitmproxy-out'
option memory_limit '256M'
option memory_limit '2G'
option mode 'transparent'
option ssl_insecure '0'
option anticache '0'
option anticomp '0'
# Headless mode: use mitmproxy instead of mitmweb (saves ~3GB RAM)
option headless '0'
# IN Instance - WAN to Services (WAF/reverse proxy)
config instance 'in'
@ -37,13 +41,16 @@ config instance 'in'
option web_port '8090'
option web_host '0.0.0.0'
option data_path '/srv/mitmproxy-in'
option memory_limit '256M'
option memory_limit '2G'
option mode 'upstream'
option ssl_insecure '0'
option anticache '0'
option anticomp '0'
# HAProxy sends traffic here
option haproxy_backend '1'
# Headless mode: use mitmproxy instead of mitmweb (saves ~3GB RAM)
# Recommended for production WAF to reduce memory usage
option headless '1'
# WAN Protection Mode - protect services exposed to internet
# Acts as WAF/reverse proxy for incoming WAN traffic

View File

@ -170,6 +170,7 @@ load_instance_config() {
anticomp="$(uci_get ${inst}.anticomp || echo 0)"
flow_detail="$(uci_get ${inst}.flow_detail || echo 1)"
haproxy_backend="$(uci_get ${inst}.haproxy_backend || echo 0)"
headless="$(uci_get ${inst}.headless || echo 0)"
else
# Legacy single-instance mode
INSTANCE=""
@ -178,7 +179,7 @@ load_instance_config() {
web_port="$(uci_get main.web_port || echo 8081)"
web_host="$(uci_get main.web_host || echo 0.0.0.0)"
data_path="$(uci_get main.data_path || echo /srv/mitmproxy)"
memory_limit="$(uci_get main.memory_limit || echo 256M)"
memory_limit="$(uci_get main.memory_limit || echo 2G)"
mode="$(uci_get main.mode || echo regular)"
upstream_proxy="$(uci_get main.upstream_proxy || echo '')"
reverse_target="$(uci_get main.reverse_target || echo '')"
@ -187,6 +188,7 @@ load_instance_config() {
anticomp="$(uci_get main.anticomp || echo 0)"
flow_detail="$(uci_get main.flow_detail || echo 1)"
haproxy_backend="0"
headless="$(uci_get main.headless || echo 0)"
fi
# Set derived paths
@ -555,7 +557,7 @@ lxc_check_prereqs() {
lxc_create_rootfs() {
load_config
if [ -d "$LXC_ROOTFS" ] && [ -x "$LXC_ROOTFS/usr/bin/mitmproxy" ]; then
if [ -d "$LXC_ROOTFS" ] && [ -x "$LXC_ROOTFS/usr/local/bin/mitmproxy" ]; then
log_info "LXC rootfs already exists with mitmproxy"
return 0
fi
@ -672,6 +674,9 @@ HAPROXY_ROUTER_ENABLED="${MITMPROXY_HAPROXY_ROUTER_ENABLED:-0}"
HAPROXY_LISTEN_PORT="${MITMPROXY_HAPROXY_LISTEN_PORT:-8890}"
HAPROXY_ROUTES_FILE="${MITMPROXY_HAPROXY_ROUTES_FILE:-/data/haproxy-routes.json}"
# Headless mode (use mitmproxy instead of mitmweb to save ~3GB RAM)
HEADLESS="${MITMPROXY_HEADLESS:-0}"
# Build args
ARGS="--listen-host 0.0.0.0 --listen-port $PROXY_PORT --set confdir=/data"
ARGS="$ARGS --web-host $WEB_HOST --web-port $WEB_PORT --no-web-open-browser"
@ -705,44 +710,60 @@ if [ "$FILTERING_ENABLED" = "1" ] && [ -n "$ADDON_SCRIPT" ] && [ -f "$ADDON_SCRI
echo "Loading addon: $ADDON_SCRIPT"
fi
rm -f /data/.mitmproxy_token /tmp/mitmweb.log
rm -f /data/.mitmproxy_token /tmp/mitmweb.log /tmp/mitmproxy.log
echo "Starting mitmweb..."
echo "Command: mitmweb $ARGS"
# Choose between headless mitmproxy and mitmweb
if [ "$HEADLESS" = "1" ]; then
echo "Starting mitmproxy (headless mode - no web UI, ~3GB RAM saved)..."
echo "Command: mitmdump $ARGS"
# Start mitmweb in background, output to log file
/usr/local/bin/mitmweb $ARGS 2>&1 | tee /tmp/mitmweb.log &
MITMWEB_PID=$!
# mitmdump is the headless CLI version
/usr/local/bin/mitmdump $ARGS 2>&1 | tee /tmp/mitmproxy.log &
MITMPROXY_PID=$!
# Wait for token to appear in log (with timeout)
echo "Waiting for authentication token..."
ATTEMPTS=0
MAX_ATTEMPTS=30
while [ $ATTEMPTS -lt $MAX_ATTEMPTS ]; do
sleep 1
ATTEMPTS=$((ATTEMPTS + 1))
echo "mitmproxy running in headless mode (PID: $MITMPROXY_PID)"
echo "No web UI available - use /tmp/mitmproxy.log for logs"
if [ -f /tmp/mitmweb.log ]; then
# Extract token from log - mitmweb outputs: "Web server listening at http://x.x.x.x:8081/?token=XXXXX"
# Token can be alphanumeric, not just hex
TOKEN=$(grep -o 'token=[a-zA-Z0-9_-]*' /tmp/mitmweb.log 2>/dev/null | head -1 | cut -d= -f2)
if [ -n "$TOKEN" ]; then
echo "$TOKEN" > /data/.mitmproxy_token
chmod 644 /data/.mitmproxy_token
echo "Token captured: $(echo "$TOKEN" | cut -c1-8)..."
echo "Web UI: http://$WEB_HOST:$WEB_PORT/?token=$TOKEN"
break
# Wait for process to keep container running
wait $MITMPROXY_PID
else
echo "Starting mitmweb (web UI mode)..."
echo "Command: mitmweb $ARGS"
# Start mitmweb in background, output to log file
/usr/local/bin/mitmweb $ARGS 2>&1 | tee /tmp/mitmweb.log &
MITMWEB_PID=$!
# Wait for token to appear in log (with timeout)
echo "Waiting for authentication token..."
ATTEMPTS=0
MAX_ATTEMPTS=30
while [ $ATTEMPTS -lt $MAX_ATTEMPTS ]; do
sleep 1
ATTEMPTS=$((ATTEMPTS + 1))
if [ -f /tmp/mitmweb.log ]; then
# Extract token from log - mitmweb outputs: "Web server listening at http://x.x.x.x:8081/?token=XXXXX"
# Token can be alphanumeric, not just hex
TOKEN=$(grep -o 'token=[a-zA-Z0-9_-]*' /tmp/mitmweb.log 2>/dev/null | head -1 | cut -d= -f2)
if [ -n "$TOKEN" ]; then
echo "$TOKEN" > /data/.mitmproxy_token
chmod 644 /data/.mitmproxy_token
echo "Token captured: $(echo "$TOKEN" | cut -c1-8)..."
echo "Web UI: http://$WEB_HOST:$WEB_PORT/?token=$TOKEN"
break
fi
fi
done
if [ ! -f /data/.mitmproxy_token ]; then
echo "Warning: Could not capture authentication token after ${MAX_ATTEMPTS}s"
echo "Check /tmp/mitmweb.log for details"
fi
done
if [ ! -f /data/.mitmproxy_token ]; then
echo "Warning: Could not capture authentication token after ${MAX_ATTEMPTS}s"
echo "Check /tmp/mitmweb.log for details"
# Wait for mitmweb process to keep container running
wait $MITMWEB_PID
fi
# Wait for mitmweb process to keep container running
wait $MITMWEB_PID
START
chmod +x "$rootfs/opt/start-mitmproxy.sh"
@ -954,6 +975,9 @@ lxc.environment = MITMPROXY_HAPROXY_ROUTER_ENABLED=$haproxy_router_enabled
lxc.environment = MITMPROXY_HAPROXY_LISTEN_PORT=$haproxy_listen_port
lxc.environment = MITMPROXY_HAPROXY_ROUTES_FILE=/data/haproxy-routes.json
# Headless mode (use mitmproxy instead of mitmweb to save ~3GB RAM)
lxc.environment = MITMPROXY_HEADLESS=$headless
# Capabilities - drop dangerous ones (sys_admin needed for some ops)
lxc.cap.drop = sys_module mac_admin mac_override sys_time
@ -984,12 +1008,13 @@ lxc_run() {
load_config
lxc_stop
if [ ! -f "$LXC_CONFIG" ]; then
log_error "LXC not configured. Run 'mitmproxyctl install' first."
# Check rootfs exists (mitmproxy is at /usr/local/bin in the container)
if [ ! -d "$LXC_ROOTFS" ] || [ ! -x "$LXC_ROOTFS/usr/local/bin/mitmproxy" ]; then
log_error "LXC rootfs not installed. Run 'mitmproxyctl install' first."
return 1
fi
# Regenerate config to pick up any UCI changes
# Create/regenerate config (always do this to pick up any UCI changes)
lxc_create_config
# Ensure mount points exist