WAF (ModSecurity)
Monitore eventos de WAF, analise ataques, ajuste regras e coloque IPs na lista de permissões para o OWASP ModSecurity CRS via Docker.
Documentação
Servidor MCP WAF
Um servidor MCP (Model Context Protocol) para gerenciar o OWASP ModSecurity CRS via Docker. Oferece a assistentes de IA como o Claude acesso direto ao monitoramento, análise e configuração do WAF por meio de um pipeline estruturado de detalhamento.
Desenvolvido para o Claude Code, mas funciona com qualquer cliente compatível com MCP.
Por quê
Serviços de proxy de LLM (LiteLLM, OpenRouter, etc.) ficam atrás de WAFs que geram uma quantidade enorme de falsos positivos — prompts contêm código, SQL, HTML, comandos de shell que disparam todas as regras de inspeção de conteúdo existentes. Gerenciar esses WAFs exige monitoramento constante, ajuste de exclusões e investigação de eventos.
Este servidor MCP permite que um assistente de IA faça esse trabalho diretamente:
- Visão geral — veja o total de eventos, IPs únicos, regras ativas de uma só vez
- Detalhamento — filtre eventos por IP ou regra, inspecione os dados correspondentes
- Ação — desative regras, coloque IPs na lista de permissões, altere o modo do mecanismo — tudo sem sair da conversa
Ferramentas
Análise (pipeline de detalhamento)
| Ferramenta | Descrição |
|---|---|
waf_overview | Painel: total de eventos, IPs/regras únicos, eventos na última hora |
waf_top_ips | Principais IPs por contagem de eventos com enriquecimento geográfico (ipinfo.io) |
waf_top_rules | Regras mais acionadas com gravidade e descrição |
waf_fp_candidates | Regras acionadas em respostas HTTP 2xx (candidatos a falso positivo) |
waf_events_by_ip | Eventos filtrados por IP de origem |
waf_events_by_rule | Eventos filtrados por ID de regra |
waf_event_detail | Evento completo: cabeçalhos, corpo da requisição, todas as correspondências de regras com dados correspondentes |
Ações
| Ferramenta | Descrição |
|---|---|
waf_status | Saúde do contêiner, modo do mecanismo, regras carregadas, nível de paranoia |
waf_set_engine | Alternar entre On, Off, DetectionOnly |
waf_set_paranoia | Definir nível de paranoia do CRS (1–4) |
waf_disable_rule | Desativar uma regra por ID (adiciona SecRuleRemoveById às exclusões) |
waf_enable_rule | Reativar uma regra previamente desativada |
waf_allow_ip | Colocar um IP na lista de permissões (ignorar o WAF completamente) |
waf_deny_ip | Remover um IP da lista de permissões |
waf_test | Executar suíte de testes: detecção de scanner, SQLi, XSS, path traversal |
Parâmetros comuns
since — Todas as ferramentas de análise aceitam um parâmetro since para controlar a janela de tempo. O padrão é "24h". Suporta sintaxe de duração do Docker: "1h", "24h", "7d", "30m". Dias são convertidos automaticamente para horas (o --since do Docker não suporta o sufixo d nativamente).
waf_overview(since: "7d") # last 7 days
waf_events_by_ip(ip: "1.2.3.4", since: "1h") # last hour
verbose — waf_events_by_ip, waf_events_by_rule e waf_event_detail aceitam verbose: true. Por padrão, matchedData e requestBody são truncados para manter as respostas dentro dos limites de contexto:
| Campo | Padrão | Detalhado |
|---|---|---|
matchedData (por regra) | 150–200 caracteres | 4000 caracteres |
requestBody | 500 caracteres | 8000 caracteres |
Pré-requisitos
- Docker com um contêiner owasp/modsecurity-crs em execução
- Docker Compose gerenciando o contêiner ModSecurity
- Node.js 18+
- ModSecurity configurado com log de auditoria JSON Serial (
SecAuditLogFormat JSON)
Instalação
git clone https://github.com/KratosUAE/waf_mcp.git
cd waf_mcp
npm install
npm run build
Configuração
Variáveis de ambiente
| Variável | Obrigatória | Padrão | Descrição |
|---|---|---|---|
WAF_COMPOSE_DIR | Sim | — | Caminho para o diretório que contém docker-compose.yml |
WAF_DOMAIN | Não | https://localhost | Domínio para requisições de teste do WAF |
WAF_LOGS_SINCE | Não | 24h | Janela de tempo padrão para consultas de log |
WAF_CONTAINER_PATTERN | Não | modsecurity | Padrão de grep para encontrar o contêiner ModSecurity |
WAF_EXCLUSIONS_FILE | Não | modsecurity/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf | Caminho para o arquivo de exclusões do CRS (relativo ao diretório do compose) |
WAF_COMPOSE_FILE | Não | docker-compose.yml | Nome do arquivo Docker Compose |
IPINFO_TOKEN | Não | — | Token do ipinfo.io para geolocalização de IP |
WAF_DEBUG | Não | — | Defina qualquer valor para habilitar log de depuração |
Conectar ao Claude Code
claude mcp add --transport stdio --scope user \
-e WAF_COMPOSE_DIR=/path/to/your/compose/dir \
-e WAF_DOMAIN=https://your-domain.com \
waf -- node /path/to/waf_mcp/dist/index.js
Ou adicione manualmente ao ~/.claude.json:
{
"mcpServers": {
"waf": {
"type": "stdio",
"command": "node",
"args": ["/path/to/waf_mcp/dist/index.js"],
"env": {
"WAF_COMPOSE_DIR": "/path/to/your/compose/dir",
"WAF_DOMAIN": "https://your-domain.com"
}
}
}
}
Configuração do Docker Compose
O servidor espera um contêiner ModSecurity gerenciado pelo Docker Compose. Exemplo de definição de serviço:
modsecurity:
image: owasp/modsecurity-crs:nginx-alpine
environment:
- BACKEND=http://your-app:8080
- MODSEC_RULE_ENGINE=DetectionOnly
- MODSEC_AUDIT_LOG=/dev/stderr
- MODSEC_AUDIT_LOG_FORMAT=JSON
- MODSEC_AUDIT_LOG_TYPE=Serial
- MODSEC_AUDIT_ENGINE=RelevantOnly
- MODSEC_REQ_BODY_ACCESS=On
- MODSEC_REQ_BODY_LIMIT=52428800
- MODSEC_RESP_BODY_ACCESS=Off
- PARANOIA=1
- ANOMALY_INBOUND=5
volumes:
- ./modsecurity/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf:/etc/modsecurity.d/owasp-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf:ro
Configurações principais:
MODSEC_AUDIT_LOG=/dev/stderr— envia o log de auditoria para os logs do Docker (necessário para o servidor MCP ler os eventos)MODSEC_AUDIT_LOG_FORMAT=JSON— formato JSON para análise estruturada- Montagem do arquivo de exclusões — permite recarga a quente das exclusões de regras via
nginx -s reload
Exclusões do CRS para tráfego de LLM
Os endpoints de API de LLM recebem prompts contendo código, SQL, HTML e comandos de shell — todo conteúdo legítimo que aciona regras do WAF. Crie um arquivo de exclusões para desativar regras de inspeção de conteúdo em caminhos de API:
# modsecurity/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
SecRule REQUEST_URI "@rx ^(/v1/)?(chat/completions|completions|embeddings|responses|messages)|^/anthropic/" \
"id:1000,phase:1,nolog,pass,\
ctl:ruleRemoveById=921000-944999"
Isso desativa as regras 921000–944999 (todas as categorias de inspeção de conteúdo: SQLi, XSS, RCE, LFI, RFI, etc.) nos endpoints de API de LLM, mantendo ativos a aplicação de protocolo, detecção de scanner, proteção contra DoS e verificações de reputação de IP.
Exemplo de uso
Fluxo de trabalho típico no Claude Code:
You: "Check the WAF — anything suspicious?"
Claude: [calls waf_overview]
→ 332 events, 4 unique IPs, 12 rules triggered
Claude: [calls waf_top_ips]
→ 135.237.83.23 (Washington, US, Microsoft) — 320 events
Claude: [calls waf_events_by_ip, ip: "135.237.83.23", count: 5]
→ All POST /chat/completions, HTTP 200, rules: 942360, 932100...
Claude: [calls waf_event_detail, index: 42]
→ User-Agent: OpenAI/JS 6.26.0, body contains tool descriptions
→ Rule 942360 matched "update" in cron action descriptions
Claude: "This is your OpenClaw bot — all false positives.
Want me to whitelist this IP?"
You: "Yes"
Claude: [calls waf_allow_ip, ip: "135.237.83.23"]
→ Done. IP whitelisted.
Investigando eventos mais antigos:
You: "Check IP 185.206.249.230 — it was flagged yesterday"
Claude: [calls waf_events_by_ip, ip: "185.206.249.230", since: "7d"]
→ 2 events from Apr 7, GET /v1/skills, HTTP 401, no rules triggered
→ Apple Private Relay IP (Singapore), just unauthorized API probes
Desenvolvimento
npm run build # Compile TypeScript
npm test # Run tests (43 tests)
npm run test:watch # Watch mode
WAF_DEBUG=1 npm start # Run with debug logging
Arquitetura
src/
├── index.ts # MCP server setup, tool registration
├── waf-manager.ts # Core service: Docker exec, log parsing, config management
├── types.ts # TypeScript interfaces
├── config.ts # Environment-based configuration
├── logger.ts # stderr-only logger (stdout reserved for MCP protocol)
└── tools/
├── overview.ts # L0: dashboard
├── top-ips.ts # L1: IP aggregation
├── top-rules.ts # L1: rule aggregation
├── fp-candidates.ts # L1: false positive detection
├── events-by-ip.ts # L2: drill-down by IP
├── events-by-rule.ts # L2: drill-down by rule
├── event-detail.ts # L3: full event inspection
├── status.ts # Container status
├── set-engine.ts # Engine mode control
├── set-paranoia.ts # Paranoia level control
├── disable-rule.ts # Rule management
├── enable-rule.ts # Rule management
├── allow-ip.ts # IP whitelist
├── deny-ip.ts # IP whitelist
├── test.ts # WAF test suite
└── utils.ts # Shared utilities
Os eventos são analisados dos logs do Docker e armazenados em cache por 30 segundos. Chamadas rápidas de detalhamento (visão geral → principais IPs → eventos por IP → detalhe do evento) usam o cache em vez de reanalisar. O cache é invalidado quando o parâmetro since muda.
Licença
MIT