- WEBHOOK_SECURITY_MODE=permissive → n8n-API-Anbindung (http://n8n:5678) wieder verbunden (n8n_health_check success:true); Blocker war der app-eigene SSRF-Guard, nicht Netz/Bearer. - Waisen-Container aus homelab-cline/n8n-mcp-deploy in Portainer-Stack 174 (n8n) gefaltet; n8n/redis ohne Downtime, Bearer/Port/Volume erhalten. Orphan-Ordner entfernt. - SSoT-Mirror docs/macmini-vlan20/stacks/ (gitignored) + Rollback-Backup. - TP30 Posten #8: N8N_SMTP_PASS beim Stack-Read geleakt (5. Maskierungs-Panne) → Rotation fällig. - INVENTORY + Handoff aktualisiert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
4.7 KiB
4.7 KiB
Handoff 2026-09-01 — n8n-mcp SSRF-Block ✅ GEFIXT + in Portainer-Stack 174 gefaltet
Kontext
Aus TP10 (Terpenfinder Auto-Refresh, Repo blaueblueten-n8n) ausgelagerter bf-infra-Task:
der n8n-MCP war einsatzfähig, aber seine Anbindung an die n8n-API war blockiert. Diese
Session hat den Blocker behoben und die Container-Definition sauber verortet.
Befund (Ausgangslage)
- Netz war nie das Problem: aus dem
n8n-mcp-Container erreichten beide Wege n8n — internhttp://n8n:5678→ HTTP 200, öffentlichhttps://n8n.emsenhuber.net/healthz→ HTTP 200. - Einziger Blocker = App-eigener SSRF-Guard von n8n-mcp (v2.57.1 → nach Redeploy 2.77.0):
N8N_API_URL=http://n8n:5678löst auf die private Docker-Bridge-IP172.19.0.3auf, und der Guard lehnte private IPs im Default-Modusstrictab (SSRF protection: Private IP addresses not allowed,connected:false). Der API-Client validiertN8N_API_URLüber genau diesen Guard (/app/dist/services/n8n-api-client.js:104→SSRFProtection.validateWebhookUrl). - SSoT-Drift (mit-gefixt): der laufende Container war ein Waise aus
~/dev/homelab-cline/n8n-mcp-deploy/docker-compose.yml(kein Git-Repo), und dieses File stimmte mit dem laufenden Container nicht überein (File:https://n8n.emsenhuber.net+ Netzweb; Container:http://n8n:5678+ Netzn8n_default).n8n+n8n-redisliefen dagegen im Portainer-Stack 174 (n8n, Endpoint 20 = macmini).
Fix (durchgeführt 2026-09-01)
Entscheidung (User): intern + permissive, und n8n-mcp in Portainer-Stack 174 falten.
- SSRF entschärft:
WEBHOOK_SECURITY_MODE=permissivegesetzt → private/LAN-IP fürN8N_API_URL=http://n8n:5678erlaubt. Bleibt auf der Docker-Bridge, kein CF/Tunnel/Caddy- Umweg, keine 10-s-DNS-Falle, unabhängig von der Edge. Vertretbar, weil dieser Container ausschließlich mit dem trusted LAN-n8n redet. - Waise beseitigt: orphan-Container entfernt (
docker rm -f n8n-mcp), n8n-mcp als dritter Service in Stack 174 aufgenommen (nebenn8n+redis, gemeinsames Default-Netzn8n_default,depends_on: n8n). Stack via Portainer-API redeployt (PUT /api/stacks/174?endpointId=20,prune:false). - Erhalten geblieben: Bearer (
AUTH_TOKEN==MCP_AUTH_TOKEN, len 64) unverändert → bestehende Clients (opencodehttp://10.40.20.167:3001/mcp) laufen weiter; Host-Port-Bind10.40.20.167:3001:3000→ Caddy-Routen8n-mcp.emsenhuber.net(Caddyfile Z. 75) intakt; Daten-Volume alsexternalwiederverwendet (n8n-mcp-deploy_n8n-mcp-data,nodes.dbbleibt) — eigenerN8N_API_KEYvon n8n-mcp (≠ n8n) unverändert.
Verifikation (nicht behauptet — gemessen)
SSRFProtection.validateWebhookUrl("http://n8n:5678")im Container →valid:true,resolved:172.19.0.3,mode:permissive.- MCP-Tool
n8n_health_check(voller Handshake) →{"success":true,"status":"ok", "apiUrl":"http://n8n:5678","mcpVersion":"2.77.0","upToDate":true}. n8n+n8n-redisbehielten Container-ID undStartedAt(2026-07-29) → kein n8n-Downtime beim Redeploy (nur der neue Service wurde erstellt).
SSoT / Ablage
- Master der Stack-Definition = Portainer-Stack 174 (
n8n, Endpoint 20, macmini). - Gitignored Repo-Mirror + Rollback:
docs/macmini-vlan20/stacks/174-n8n.yml(neuer Stand) und…/174-n8n.orig-pre-mcp-fold-20260901.yml(Vorzustand). Neu gitignored:docs/macmini-vlan20/stacks. - INVENTORY-Eintrag
mcp/INVENTORY.md(n8n-mcp) aktualisiert.
Offene Punkte
- 🔴 TP30 Posten #8: beim Ausgeben des Stack-174-Files ist
N8N_SMTP_PASS(Gmail-App-PWjohnny.claw.0x00@gmail.com) ins Transkript geraten (Redaktionsmuster hattePASSWORD, nicht barePASS). Rotation fällig — Google App-Passwort widerrufen + Stack-174-Env nachziehen. - ⚠️ Toter Orphan:
~/dev/homelab-cline/n8n-mcp-deploy/(kein Git) kann gelöscht werden — ein erneutesdocker compose updort würde sonst einen Namenskonflikt mit dem Stack-174-Container erzeugen. Nicht kritisch (nur bei Handstart). - ⚠️ Client-401 in THIS Claude-Code-Session: der n8n-mcp-Server kam in dieser Session mit
AUTH_HEADER_REJECTED(401) hoch — das ist ein Client-Config-Thema (~/.claude.json-Bearer leer/falsch, vgl. globale CLAUDE.md „kein Shell →{env:}leer"), nicht der hier gefixte Server. Der Server antwortet LAN-direkt korrekt; opencode ist unbetroffen.
Auswirkung auf TP10
Keine für den Feature-Pfad: TP10 läuft über Cloudflare Worker Cron, nicht über n8n. Der Fix
macht n8n-mcp aber wieder als Werkzeug nutzbar (n8n-Workflow-Validierung, künftig optional
TP10-als-n8n-Workflow). Rückantwort ans zuweisende Projekt:
~/dev/blaueblueten-n8n/docs/rueckantwort-n8n-mcp-fix-20260901.md.