Compare commits
3 Commits
e5ae4649b3
...
3a5d73a485
| Author | SHA1 | Date |
|---|---|---|
|
|
3a5d73a485 | |
|
|
d9a0b14d6f | |
|
|
822dde3d06 |
|
|
@ -70,7 +70,13 @@ O container `nginx-proxy` é construído manualmente (`Dockerfile`) para incluir
|
|||
- `nginx-mod-http-headers-more`
|
||||
|
||||
### 2. ModSecurity (WAF)
|
||||
Rodar o WAF em container separado (`modsecurity`) evita a necessidade de compilar o ModSecurity no NGINX principal, facilitando atualizações e isolando falhas. Se o WAF falhar, o Proxy pode ser exposto diretamente mudando as portas no `docker-compose.yml` (Bypass de emergência).
|
||||
Rodar o WAF em container separado (`modsecurity`) evita a necessidade de compilar o ModSecurity no NGINX principal.
|
||||
|
||||
**Arquitetura Customizada:**
|
||||
- **Injeção de Template**: Um arquivo `modsec.conf.template` local é montado durante o boot para contornar limitações de permissão do container oficial. Ele instrui o NGINX a carregar regras customizadas.
|
||||
- **Regras Modulares**: Localizadas em `modsec_rules/`, divididas por aplicação (`gitea-rule-exceptions.conf`, `nextcloud...`).
|
||||
- **Global**: `global-exceptions.conf` define apenas a whitelist de rede.
|
||||
- **Bypass de Emergência**: Se o WAF falhar, altere as portas no `docker-compose.yml` para expor o `nginx-proxy` diretamente.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -111,6 +117,13 @@ docker compose logs nginx-proxy | grep "SSL"
|
|||
docker compose exec nginx-proxy /scripts/renew_ssl.sh
|
||||
```
|
||||
|
||||
**Reload Zero-Downtime (Blue-Green Logic):**
|
||||
Este comando valida a configuração e executa um reload gracioso (`nginx -s reload`), onde novos workers assumem as novas configurações enquanto os antigos terminam as requisições correntes.
|
||||
```bash
|
||||
./scripts/reload.sh # Linux
|
||||
./scripts/reload.ps1 # Windows PowerShell
|
||||
```
|
||||
|
||||
**Banir um IP manualmente:**
|
||||
```bash
|
||||
docker compose exec fail2ban fail2ban-client set nginx-badbots banip 1.2.3.4
|
||||
|
|
|
|||
|
|
@ -8,11 +8,12 @@
|
|||
|
||||
## 2. Revisão de Regras ModSecurity
|
||||
**Origem:** Migração de `legacy/nginx/modsecurity/*.conf` (Regras Antigas)
|
||||
- **Status:** ⚠️ Parcial (Arquivos em `modsec_rules/`, mas injeção desabilitada).
|
||||
- **Objetivo:** Rever todas as regras para fazerem sentido no contexto atual (OWASP CRS v4) ou mudar o método de inserção.
|
||||
- **Ação:** Auditar exceções de Gitea, Grafana, etc., e reativar apenas o necessário.
|
||||
- **Status:** ✅ Concluído.
|
||||
- **Resolução:** Regras refatoradas para estrutura modular (`modsec_rules/`). WAF ativo e configurado via template injection para Gitea, Nextcloud, Exchange, Zabbix e outros.
|
||||
- **Ação:** Monitorar logs (`modsec_audit.log`) para ajustes finos futuros.
|
||||
|
||||
## 3. Atualizações Zero-Downtime (Sem Queda)
|
||||
**Objetivo:** Criar um método para atualizar configurações de sites sem que clientes externos percam a conexão.
|
||||
- **Cenário Atual:** Restart do container ou reload podem causar breves interrupções se não gerenciados corretamente.
|
||||
- **Solução Proposta:** Implementar scripts de "Reload Suave" (`nginx -s reload`) com validação prévia (`nginx -t`) automatizada, garantindo que conexões ativas terminem graciosamente.
|
||||
- **Status:** ✅ Concluído.
|
||||
- **Solução Implementada:** Script `./scripts/reload.sh` que executa `nginx -t` e `nginx -s reload` (Reload Suave/Process-Level Blue-Green).
|
||||
- **Como usar:** Execute `./scripts/reload.sh` após alterar qualquer `.conf`.
|
||||
|
|
|
|||
16
README.md
16
README.md
|
|
@ -86,6 +86,16 @@ As configurações globais são modularizadas na pasta `snippets/`.
|
|||
- **Bloqueio de Bots**: Edite `snippets/security_maps.conf` para adicionar novos User-Agents à lista negra.
|
||||
- **Cache**: Edite `snippets/cache_zones.conf` para definir novas zonas ou tempos de cache.
|
||||
|
||||
### 3.1. Modificar Regras do WAF (ModSecurity)
|
||||
O WAF agora utiliza uma estrutura modular de regras localizada na pasta `modsec_rules/`.
|
||||
- **Arquivos Específicos**: Regras para Gitea, Nextcloud, Exchange, Zabbix, etc. ficam em seus respectivos arquivos `.conf`.
|
||||
- **Global**: `global-exceptions.conf` contém apenas whitelists de rede interna.
|
||||
- **Aplicação**: Após editar qualquer regra, reinicie o container do WAF para aplicar:
|
||||
```bash
|
||||
docker compose restart modsecurity
|
||||
```
|
||||
> **Nota Técnica**: O arquivo `modsec.conf.template` na raiz é injetado no container durante o boot para contornar problemas de permissão e garantir o carregamento das regras customizadas.
|
||||
|
||||
### 4. Gerenciar Certificados SSL
|
||||
O sistema gerencia isso automaticamente, mas você pode intervir manualmente se necessário.
|
||||
|
||||
|
|
@ -101,6 +111,12 @@ O sistema gerencia isso automaticamente, mas você pode intervir manualmente se
|
|||
docker compose exec nginx-proxy /scripts/renew_ssl.sh
|
||||
```
|
||||
|
||||
- **Reload sem Downtime (Recomendado)**:
|
||||
Para aplicar alterações de configuração (vhosts, SSL) sem derrubar conexões ativas:
|
||||
```bash
|
||||
./scripts/reload.sh
|
||||
```
|
||||
|
||||
### 5. Monitorar e Debugar
|
||||
|
||||
- **Verificar Status dos Containers**:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
ssl_session_cache shared:le_nginx_SSL:1m;
|
||||
ssl_session_timeout 1440m;
|
||||
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
-----BEGIN DH PARAMETERS-----
|
||||
MIIBDAKCAQEA7aEz2xmnoIbgtStbhLjO2kIgHb+mXbTBJi2aXSnMlih9Q2WWfEOY
|
||||
TrSw98BLop6l/6FS9XqCNAaB06AQLYIrXx1V3MtT1x9JcHfwbgKacDsEf+B+yYXS
|
||||
Avv8G6j6t4k0s7ovg9tVEpRr1n8YCDj1bWv1iiQjfotmzeex6NNE9rX31GvRpRhP
|
||||
jY+I9JDU0xG7GA16dNYYkq7kNPF7f1HmpFZOPiqox+IoMxZPlMZsKfRxmWpNPbgy
|
||||
Pmzbrf7i3Wj9gjjGbPSvJ5dnaz4XGqUxAXemAXhjQ9TLVEig2NNo8LeYp/1r22+H
|
||||
Wls/ddseH7N2lOr3M4oHsaUo4vsKG/SAfwIBAgICAOE=
|
||||
-----END DH PARAMETERS-----
|
||||
|
|
@ -17,8 +17,8 @@ services:
|
|||
volumes:
|
||||
- ./ssl:/etc/nginx/ssl:ro
|
||||
- modsec_logs:/var/log/modsecurity
|
||||
# - ./modsec_rules:/etc/nginx/modsecurity.d/custom_rules
|
||||
# - ./modsec_includes.conf:/etc/nginx/modsecurity.d/modsecurity-override.conf
|
||||
- ./modsec_rules:/etc/nginx/custom_rules
|
||||
- ./modsec.conf.template:/etc/nginx/templates/modsecurity.d/modsecurity.conf.template
|
||||
depends_on:
|
||||
- nginx-proxy
|
||||
extra_hosts:
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -0,0 +1,75 @@
|
|||
# Original of the latest recommended version:
|
||||
# https://github.com/owasp-modsecurity/ModSecurity/blob/v3/master/modsecurity.conf-recommended
|
||||
|
||||
# Directives configured upstream (in the same order)
|
||||
SecRuleEngine ${MODSEC_RULE_ENGINE}
|
||||
SecRequestBodyAccess ${MODSEC_REQ_BODY_ACCESS}
|
||||
SecRequestBodyLimit ${MODSEC_REQ_BODY_LIMIT}
|
||||
SecRequestBodyNoFilesLimit ${MODSEC_REQ_BODY_NOFILES_LIMIT}
|
||||
SecRequestBodyLimitAction ${MODSEC_REQ_BODY_LIMIT_ACTION}
|
||||
SecRequestBodyJsonDepthLimit ${MODSEC_REQ_BODY_JSON_DEPTH_LIMIT}
|
||||
SecArgumentsLimit ${MODSEC_ARGUMENTS_LIMIT}
|
||||
SecPcreMatchLimit ${MODSEC_PCRE_MATCH_LIMIT}
|
||||
SecPcreMatchLimitRecursion ${MODSEC_PCRE_MATCH_LIMIT_RECURSION}
|
||||
SecResponseBodyAccess ${MODSEC_RESP_BODY_ACCESS}
|
||||
SecResponseBodyMimeType ${MODSEC_RESP_BODY_MIMETYPE}
|
||||
SecResponseBodyLimit ${MODSEC_RESP_BODY_LIMIT}
|
||||
SecResponseBodyLimitAction ${MODSEC_RESP_BODY_LIMIT_ACTION}
|
||||
SecTmpDir ${MODSEC_TMP_DIR}
|
||||
SecDataDir ${MODSEC_DATA_DIR}
|
||||
SecAuditEngine ${MODSEC_AUDIT_ENGINE}
|
||||
SecAuditLogRelevantStatus "${MODSEC_AUDIT_LOG_RELEVANT_STATUS}"
|
||||
SecAuditLogParts ${MODSEC_AUDIT_LOG_PARTS}
|
||||
SecAuditLogType ${MODSEC_AUDIT_LOG_TYPE}
|
||||
SecAuditLog ${MODSEC_AUDIT_LOG}
|
||||
SecArgumentSeparator ${MODSEC_ARGUMENT_SEPARATOR}
|
||||
SecCookieFormat ${MODSEC_COOKIE_FORMAT}
|
||||
SecUnicodeMapFile unicode.mapping ${MODSEC_UNICODE_MAPPING}
|
||||
SecStatusEngine ${MODSEC_STATUS_ENGINE}
|
||||
|
||||
# Additional directives
|
||||
SecAuditLogFormat ${MODSEC_AUDIT_LOG_FORMAT}
|
||||
SecAuditLogStorageDir ${MODSEC_AUDIT_STORAGE_DIR}
|
||||
SecDebugLog ${MODSEC_DEBUG_LOG}
|
||||
SecDebugLogLevel ${MODSEC_DEBUG_LOGLEVEL}
|
||||
SecDisableBackendCompression ${MODSEC_DISABLE_BACKEND_COMPRESSION}
|
||||
SecTmpSaveUploadedFiles ${MODSEC_TMP_SAVE_UPLOADED_FILES}
|
||||
SecUploadDir ${MODSEC_UPLOAD_DIR}
|
||||
SecUploadFileMode ${MODSEC_UPLOAD_FILE_MODE}
|
||||
SecUploadKeepFiles ${MODSEC_UPLOAD_KEEP_FILES}
|
||||
|
||||
# Rules configured upstream (in the same order)
|
||||
SecRule REQUEST_HEADERS:Content-Type "^(?:application(?:/soap\+|/)|text/)xml" \
|
||||
"id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
|
||||
SecRule REQUEST_HEADERS:Content-Type "^application/json" \
|
||||
"id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
|
||||
SecRule &ARGS "@ge ${MODSEC_ARGUMENTS_LIMIT}" \
|
||||
"id:'200007', phase:2,t:none,log,deny,status:400,msg:'Failed to fully parse request body due to large argument count',severity:2"
|
||||
SecRule REQBODY_ERROR "!@eq 0" \
|
||||
"id:'200002', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2"
|
||||
SecRule MULTIPART_STRICT_ERROR "!@eq 0" \
|
||||
"id:'200003',phase:2,t:none,log,deny,status:400, \
|
||||
msg:'Multipart request body failed strict validation: \
|
||||
PE %{REQBODY_PROCESSOR_ERROR}, \
|
||||
BQ %{MULTIPART_BOUNDARY_QUOTED}, \
|
||||
BW %{MULTIPART_BOUNDARY_WHITESPACE}, \
|
||||
DB %{MULTIPART_DATA_BEFORE}, \
|
||||
DA %{MULTIPART_DATA_AFTER}, \
|
||||
HF %{MULTIPART_HEADER_FOLDING}, \
|
||||
LF %{MULTIPART_LF_LINE}, \
|
||||
SM %{MULTIPART_MISSING_SEMICOLON}, \
|
||||
IQ %{MULTIPART_INVALID_QUOTING}, \
|
||||
IP %{MULTIPART_INVALID_PART}, \
|
||||
IH %{MULTIPART_INVALID_HEADER_FOLDING}, \
|
||||
FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'"
|
||||
SecRule MULTIPART_UNMATCHED_BOUNDARY "@eq 1" \
|
||||
"id:'200004',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'"
|
||||
SecRule TX:/^MSC_/ "!@streq 0" \
|
||||
"id:'200005',phase:2,t:none,log,deny,msg:'ModSecurity internal error flagged: %{MATCHED_VAR_NAME}'"
|
||||
|
||||
# Additional rules
|
||||
SecRule REQUEST_HEADERS:Content-Type "^application/[a-z0-9.-]+[+]json" \
|
||||
"id:'200006',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
|
||||
|
||||
# Gemini: Include Custom Rules
|
||||
include /etc/nginx/custom_rules/*.conf
|
||||
|
|
@ -1,2 +1,2 @@
|
|||
# Include all custom rules form legacy migration
|
||||
include /etc/nginx/modsecurity.d/custom_rules/*.conf
|
||||
include /etc/nginx/custom_rules/*.conf
|
||||
|
|
|
|||
|
|
@ -1,8 +1,15 @@
|
|||
# Ficheiro de Exceções do ModSecurity para o Microsoft Exchange
|
||||
# Ficheiro de Exceções do ModSecurity para o Microsoft Exchange (ATUALIZADO)
|
||||
|
||||
# Desativa completamente o motor de regras do ModSecurity para QUALQUER URL
|
||||
# que comece com /owa/ ou /ecp/.
|
||||
# Isto resolve os falsos positivos que bloqueiam a funcionalidade legítima
|
||||
# do Outlook Web App e do Exchange Admin Center.
|
||||
SecRule REQUEST_URI "@rx ^/(owa|ecp)/" \
|
||||
"id:1003,phase:1,nolog,allow,ctl:ruleEngine=Off"
|
||||
# --------------------------------------------------------------------------
|
||||
# Exchange Protocols Whitelist
|
||||
# --------------------------------------------------------------------------
|
||||
# Whitelists standard Exchange 2016/2019 paths to prevent WAF blocking
|
||||
# essential email and admin functionality.
|
||||
|
||||
SecRule REQUEST_URI "@rx ^/(owa|ecp|Microsoft-Server-ActiveSync|EWS|OAB|Autodiscover|rpc|mapi)/" \
|
||||
"id:10006, \
|
||||
phase:1, \
|
||||
pass, \
|
||||
nolog, \
|
||||
ctl:ruleEngine=Off, \
|
||||
msg:'WHITELIST: Microsoft Exchange Services'"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,45 @@
|
|||
# Ficheiro de Exceções do ModSecurity para o Gitea (VERSÃO FINAL E COMPLETA)
|
||||
# Ficheiro de Exceções do ModSecurity para o Gitea (ATUALIZADO)
|
||||
|
||||
# Desativa completamente o motor de regras do ModSecurity para QUALQUER URL
|
||||
# que envolva a visualização, edição, criação ou visualização de commits de ficheiros no Gitea.
|
||||
# A expressão regular agora apanha os caminhos "/src/branch/", "/_edit/", "/_new/" e "/commits/branch/".
|
||||
# --------------------------------------------------------------------------
|
||||
# Git Operations & Web Interface
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
# ID 10008: Permitir operacoes de edição na UI
|
||||
SecRule REQUEST_URI "@rx ^/.*/(src/branch|_edit|_new|commits/branch)/" \
|
||||
"id:1005,phase:1,nolog,allow,ctl:ruleEngine=Off"
|
||||
"id:10008,phase:1,nolog,allow,ctl:ruleEngine=Off"
|
||||
|
||||
# ID 10011: Permitir acesso a assets e raw files
|
||||
SecRule REQUEST_URI "@rx ^/.*/.*(raw|assets)/" \
|
||||
"id:10011,phase:1,nolog,pass,ctl:ruleEngine=Off"
|
||||
|
||||
# ID 10013: Permitir acesso a arquivos .conf (git repos)
|
||||
SecRule REQUEST_FILENAME "@rx \.conf$" \
|
||||
"id:10013,phase:1,nolog,pass,chain,msg:'[CUSTOM] Whitelist .conf files for Git server'"
|
||||
SecRule SERVER_NAME "@streq git.itguys.com.br" "ctl:ruleRemoveById=930120"
|
||||
|
||||
# ID 10025: Upload de Arquivos na UI
|
||||
SecRule REQUEST_URI "@rx ^/[^/]+/[^/]+/upload-file$" \
|
||||
"id:10025,phase:1,pass,nolog,ctl:ruleEngine=Off"
|
||||
|
||||
# ID 10026: Wiki
|
||||
SecRule REQUEST_URI "@rx ^/[^/]+/[^/]+/wiki$" \
|
||||
"id:10026,phase:1,pass,nolog,ctl:ruleEngine=Off"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Git Hooks & Uploads
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
# ID 10040: Git Smart Protocol (Push/Pull)
|
||||
# Disables rule engine and INCREASES request body limit for git-receive-pack (Push)
|
||||
# to allow large uploads.
|
||||
SecRule REQUEST_URI "@rx /git-(upload|receive)-pack$" \
|
||||
"id:10040, \
|
||||
phase:1, \
|
||||
pass, \
|
||||
nolog, \
|
||||
ctl:ruleEngine=Off, \
|
||||
ctl:requestBodyAccess=Off"
|
||||
|
||||
# ID 10041: Permitir LFS (Large File Storage) e Uploads via HTTP
|
||||
SecRule REQUEST_URI "@rx /(info/lfs|objects/batch)" \
|
||||
"id:10041,phase:1,pass,nolog,ctl:ruleEngine=Off"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
# ==========================================================================
|
||||
# Arquivo Global de Exceções do ModSecurity
|
||||
# ==========================================================================
|
||||
# Este arquivo centraliza todas as regras de exceção para as aplicações.
|
||||
# Todos os IDs foram reorganizados para serem únicos.
|
||||
# Este arquivo contém apenas regras genéricas ou de infraestrutura.
|
||||
# Regras específicas de aplicações estão em arquivos separados.
|
||||
|
||||
# WHITELIST: Acesso permitido da rede interna, ModSecurity desativado
|
||||
SecRule REMOTE_ADDR "@ipMatch 172.16.0.0/16,10.10.0.0/16,10.11.0.0/16,10.12.0.0/16" \
|
||||
"id:10000, \
|
||||
phase:1, \
|
||||
|
|
@ -10,183 +12,3 @@ SecRule REMOTE_ADDR "@ipMatch 172.16.0.0/16,10.10.0.0/16,10.11.0.0/16,10.12.0.0/
|
|||
nolog, \
|
||||
ctl:ruleEngine=Off, \
|
||||
msg:'WHITELIST: Acesso permitido da rede interna, ModSecurity desativado'"
|
||||
# --------------------------------------------------------------------------
|
||||
# Exceções para o Nextcloud
|
||||
# --------------------------------------------------------------------------
|
||||
# Desliga o motor de regras para as rotas de sincronização (WebDAV).
|
||||
SecRule REQUEST_URI "@beginsWith /remote.php" "id:10001,phase:1,nolog,pass,ctl:ruleEngine=Off"
|
||||
SecRule REQUEST_URI "@streq /.well-known/caldav" "id:10002,phase:1,nolog,pass,ctl:ruleEngine=Off"
|
||||
SecRule REQUEST_URI "@streq /.well-known/carddav" "id:10003,phase:1,nolog,pass,ctl:ruleEngine=Off"
|
||||
# --------------------------------------------------------------------------
|
||||
# Exceções para o Zabbix
|
||||
# --------------------------------------------------------------------------
|
||||
# Desliga o ModSecurity para a API JSON-RPC e zabbix.php.
|
||||
SecRule REQUEST_URI "@rx (api_jsonrpc\.php|jsrpc\.php|zabbix\.php)" "id:10004,phase:1,nolog,pass,ctl:ruleEngine=Off"
|
||||
# Desativa regras específicas na página de Descoberta de Hosts.
|
||||
# Lembre-se de substituir os IDs abaixo pelos que encontrou no seu log.
|
||||
SecRule REQUEST_URI "@beginsWith /zabbix/host_discovery.php" "id:10005,phase:1,nolog,allow,ctl:ruleRemoveById=9XXXXX,ctl:ruleRemoveById=9YYYYY"
|
||||
# --------------------------------------------------------------------------
|
||||
# Exceções para o Microsoft Exchange
|
||||
# --------------------------------------------------------------------------
|
||||
# Desliga o ModSecurity para o Outlook Web App (OWA) e o Exchange Admin Center (ECP).
|
||||
SecRule REQUEST_URI "@rx ^/(owa|ecp)/" "id:10006,phase:1,nolog,allow,ctl:ruleEngine=Off"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Exceções para o Zammad
|
||||
# --------------------------------------------------------------------------
|
||||
# Desativa regra de falso positivo para a API do Zammad.
|
||||
# Lembre-se de substituir '9XXXXX' pelo ID da regra real.
|
||||
SecRule REQUEST_URI "@beginsWith /api/v1/" "id:10007,phase:1,nolog,allow,ctl:ruleRemoveById=9XXXXX"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Exceções para o Gitea
|
||||
# --------------------------------------------------------------------------
|
||||
# Desliga o motor de regras para operações de ficheiros no Gitea.
|
||||
SecRule REQUEST_URI "@rx ^/.*/(src/branch|_edit|_new|commits/branch)/" "id:10008,phase:1,nolog,allow,ctl:ruleEngine=Off"
|
||||
SecRule REQUEST_URI "@rx ^/.*/.*(raw|assets)/" "id:10011,phase:1,nolog,pass,ctl:ruleEngine=Off"
|
||||
SecRule REQUEST_FILENAME "@rx \.conf$" "id:10013,phase:1,nolog,pass,chain,msg:'[CUSTOM] Whitelist .conf files for Git server'"
|
||||
SecRule SERVER_NAME "@streq git.itguys.com.br" "ctl:ruleRemoveById=930120"
|
||||
SecRule REQUEST_URI "@rx ^/[^/]+/[^/]+/upload-file$" \
|
||||
"id:10025, \
|
||||
phase:1, \
|
||||
pass, \
|
||||
nolog, \
|
||||
ctl:ruleEngine=Off, \
|
||||
msg:'TUNING: ModSecurity desativado para a rota de upload de arquivos do Gitea'"
|
||||
SecRule REQUEST_URI "@rx ^/[^/]+/[^/]+/wiki$" \
|
||||
"id:10026, \
|
||||
phase:1, \
|
||||
pass, \
|
||||
nolog, \
|
||||
ctl:ruleEngine=Off, \
|
||||
msg:'TUNING: ModSecurity desativado para a rota de wiki do Gitea'"
|
||||
# --------------------------------------------------------------------------
|
||||
# Exceções para o Grafana
|
||||
# --------------------------------------------------------------------------
|
||||
# Desativa a regra de falso positivo para a API de dashboards.
|
||||
# Lembre-se de substituir '9XXXXX' pelo ID da regra real.
|
||||
SecRule REQUEST_URI "@beginsWith /api/dashboards/" "id:10009,phase:1,nolog,allow,ctl:ruleRemoveById=9XXXXX"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Exceções para a Geração de Prévias (Thumbnails) do Nextcloud
|
||||
# --------------------------------------------------------------------------
|
||||
# Desativa a regra de falso positivo que bloqueia a criação de miniaturas.
|
||||
# Substitua '9XXXXX' pelo ID real encontrado no log de auditoria.
|
||||
SecRule REQUEST_URI "@beginsWith /index.php/core/preview" "id:10010,phase:1,nolog,pass,ctl:ruleRemoveById=9XXXXX
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Exceções para o Nextcloud Office Online
|
||||
# --------------------------------------------------------------------------
|
||||
# Desliga completamente o motor de regras para as rotas de comunicação do
|
||||
# Office Online, que geram muitos falsos positivos.
|
||||
# As rotas são /hosting/discovery, /hosting/wopi/ e /op/.
|
||||
SecRule REQUEST_URI "@rx ^/(hosting|op|we|wv|p|x|lo|m|o)/" "id:10014,phase:1,nolog,pass,ctl:ruleEngine=Off"
|
||||
SecRule REQUEST_URI "@streq /index.php/apps/officeonline/ajax/admin.php" "id:10015,phase:1,nolog,pass,ctl:ruleEngine=Off"
|
||||
|
||||
# Exceções para a API do UniFi Controller
|
||||
# --------------------------------------------------------------------------
|
||||
# Desativa a regra que bloqueia o método 'PUT' para a API.
|
||||
SecRule REQUEST_URI "@beginsWith /api/" "id:10012,phase:1,nolog,pass,ctl:ruleEngine=Off"
|
||||
|
||||
# Exceção para o Editor de Texto (Nextcloud Text)
|
||||
# --------------------------------------------------------------------------
|
||||
# Desliga o motor de regras para a criação de sessão do editor de texto,
|
||||
# que é bloqueada por regras de segurança (falso positivo).
|
||||
SecRule REQUEST_URI "@beginsWith /apps/text/session" "id:10016,phase:1,nolog,pass,ctl:ruleEngine=Off"
|
||||
SecRule REQUEST_URI "@streq /apps/logreader/api/settings" "id:10020,phase:1,nolog,pass,ctl:ruleEngine=Off"
|
||||
# ==========================================================================================
|
||||
# NOVAS EXCEÇÕES - AJUSTADAS EM 2025-09-25 22:24
|
||||
# ------------------------------------------------------------------------------------------
|
||||
# MOTIVO: Corrige erros 403 (falsos positivos) em rotas da app "External Sites" do Nextcloud.
|
||||
# MÉTODO: Em vez de desligar o motor, desabilita apenas as regras específicas que
|
||||
# contribuem para o score de anomalia, mantendo as demais proteções.
|
||||
# AÇÃO: Substitua 9XXXXX e 9YYYYY pelos IDs de regras encontrados no modsec_audit.log.
|
||||
|
||||
# Exceção para a API de "sites externos". Bloqueava requisições PUT.
|
||||
SecRule REQUEST_URI "@beginsWith /ocs/v2.php/apps/external/api/v1/sites" "id:10017,phase:1,nolog,pass,ctl:ruleEngine=Off"
|
||||
|
||||
# Exceção para os ícones da app "sites externos". Bloqueava requisições DELETE.
|
||||
SecRule REQUEST_URI "@beginsWith /apps/external/icons" "id:10018,phase:1,pass,nolog,ctl:ruleEngine=Off"
|
||||
# ==========================================================================================
|
||||
SecRule REQUEST_URI "@rx ^/(ocs/v2\.php/apps/user_status/api/v1/heartbeat|apps/files/api/v1/config/(sort_favorites_first|show_hidden|grid_view|folder_tree|sort_folders_first|crop_image_previews|show_dialog_file_extension))" \
|
||||
"id:10022, \
|
||||
phase:1, \
|
||||
pass, \
|
||||
nolog, \
|
||||
ctl:ruleEngine=Off, \
|
||||
msg:'TUNING: ModSecurity desativado para APIs de configuracao de UI do Nextcloud'"
|
||||
SecRule REQUEST_URI "@rx ^/ocs/v2\.php/cloud/users|profile/.*" \
|
||||
"id:10023, \
|
||||
phase:1, \
|
||||
pass, \
|
||||
nolog, \
|
||||
ctl:ruleEngine=Off, \
|
||||
msg:'TUNING: ModSecurity desativado para a API de atualizacao de perfil de usuario do Nextcloud'"
|
||||
SecRule REQUEST_URI "@streq /apps/files/api/v1/views" \
|
||||
"id:10024, \
|
||||
phase:1, \
|
||||
pass, \
|
||||
nolog, \
|
||||
ctl:ruleEngine=Off, \
|
||||
msg:'TUNING: ModSecurity desativado para a API de views de arquivos do Nextcloud'"
|
||||
SecRule REQUEST_URI "@rx ^/(index\.php/core/preview|ocs/v2\.php/apps/user_status/api/v1/user_status)" \
|
||||
"id:10027, \
|
||||
phase:1, \
|
||||
pass, \
|
||||
nolog, \
|
||||
ctl:ruleEngine=Off, \
|
||||
msg:'TUNING: ModSecurity desativado para as APIs de Preview e User Status do Nextcloud'"
|
||||
SecRule REQUEST_URI "@streq /ocs/v2.php/cloud/groups/details" \
|
||||
"id:10028, \
|
||||
phase:1, \
|
||||
pass, \
|
||||
nolog, \
|
||||
ctl:ruleEngine=Off, \
|
||||
msg:'TUNING: ModSecurity desativado para a API de busca de grupos do Nextcloud'"
|
||||
SecRule REQUEST_URI "@beginsWith /ocs/v2.php/apps/forms/api/" \
|
||||
"id:10031, \
|
||||
phase:1, \
|
||||
pass, \
|
||||
nolog, \
|
||||
ctl:ruleEngine=Off, \
|
||||
msg:'TUNING: ModSecurity desativado para a API do Nextcloud Forms'"
|
||||
SecRule REQUEST_METHOD "@streq PUT" "phase:1,id:1001,chain,nolog,pass"
|
||||
SecRule REQUEST_URI "@rx ^/apps/integration_onedrive/(?:admin-config|sensitive-admin-config)$" \
|
||||
"t:none,ctl:ruleRemoveById=949110"
|
||||
SecRule REQUEST_URI "@rx ^/(apps/tables/|ocs/v2\.php/apps/tables/)" \
|
||||
"id:10032, \
|
||||
phase:1, \
|
||||
pass, \
|
||||
nolog, \
|
||||
ctl:ruleEngine=Off, \
|
||||
msg:'TUNING: (Nuke) ModSecurity DESATIVADO para Nextcloud Tables'"
|
||||
SecRule REQUEST_URI "@beginsWith /ocs/v2.php/apps/notifications/api/v2/notifications" \
|
||||
"id:10019, \
|
||||
phase:1, \
|
||||
nolog, \
|
||||
pass, \
|
||||
ctl:ruleEngine=Off, \
|
||||
msg:'TUNING: (Corrigido) ModSecurity DESATIVADO para API de Notificações'"
|
||||
SecRule REQUEST_URI "@beginsWith /apps/files_pdfviewer/" \
|
||||
"id:10033, \
|
||||
phase:1, \
|
||||
pass, \
|
||||
nolog, \
|
||||
ctl:ruleRemoveById=949110, \
|
||||
msg:'TUNING: Remove bloqueio por Anomaly Score (949110) para Nextcloud PDF Viewer'"
|
||||
SecRule REMOTE_ADDR "@ipMatch 172.16.254.1" \
|
||||
"id:10034, \
|
||||
phase:1, \
|
||||
pass, \
|
||||
nolog, \
|
||||
chain, \
|
||||
msg:'WHITELIST: [Proxy 172.16.254.1] Desativa WAF para Office Online (WOPI)'"
|
||||
SecRule REQUEST_URI "@beginsWith /index.php/apps/officeonline/wopi/files/" \
|
||||
"ctl:ruleEngine=Off"
|
||||
SecRule REQUEST_URI "@streq /apps/officeonline/index" \
|
||||
"id:10035, \
|
||||
phase:1, \
|
||||
pass, \
|
||||
nolog, \
|
||||
ctl:ruleEngine=Off, \
|
||||
msg:'TUNING: Desativa WAF para a pagina de indice do Office Online (falso positivo em GET)'"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
# Ficheiro de Exceções do ModSecurity para o Grafana
|
||||
|
||||
# Desativa a regra 9XXXXX (que estava a causar um falso positivo com o método DELETE)
|
||||
# APENAS para as requisições que começam com /api/dashboards/.
|
||||
# Isto mantém a regra ativa para o resto do site.
|
||||
# ID 10009: Whitelist Grafana Dashboard API
|
||||
SecRule REQUEST_URI "@beginsWith /api/dashboards/" \
|
||||
"id:1007,phase:1,nolog,allow,ctl:ruleRemoveById=9XXXXX"
|
||||
"id:10009,phase:1,pass,nolog,allow,ctl:ruleRemoveById=9XXXXX"
|
||||
|
|
|
|||
|
|
@ -1,14 +1,30 @@
|
|||
# --------------------------------------------------------------------------
|
||||
# Nextcloud: Exceções para o Nextcloud (Sintaxe para Nginx)
|
||||
# --------------------------------------------------------------------------
|
||||
# Este arquivo contém regras de exclusão para o Nextcloud.
|
||||
# A ação aqui desliga completamente o motor do ModSecurity para as rotas
|
||||
# de sincronização (WebDAV), o que é funcional mas menos seguro.
|
||||
# Ficheiro de Exceções do ModSecurity para o Nextcloud (ATUALIZADO)
|
||||
|
||||
# Desliga o motor de regras para qualquer URL que comece com /remote.php
|
||||
# Isso cobre o WebDAV e outras operações do cliente.
|
||||
SecRule REQUEST_URI "@beginsWith /remote.php" "id:1001,phase:1,nolog,pass,ctl:ruleEngine=Off"
|
||||
# --------------------------------------------------------------------------
|
||||
# Broad API & Extension Whitelist (User Request: "Liberate all APIs")
|
||||
# --------------------------------------------------------------------------
|
||||
# Allows /apps/, /ocs/ (Open Cloud Standard), and /remote.php (WebDAV)
|
||||
# to ensure plugins and sync clients work without restriction.
|
||||
SecRule REQUEST_URI "@rx ^/(index\.php/apps|apps|ocs|remote\.php)/" \
|
||||
"id:10050,phase:1,pass,nolog,ctl:ruleEngine=Off"
|
||||
|
||||
# Desliga o motor de regras para as rotas de descoberta de CalDAV e CardDAV.
|
||||
SecRule REQUEST_URI "@streq /.well-known/caldav" "id:1002,phase:1,nolog,pass,ctl:ruleEngine=Off"
|
||||
SecRule REQUEST_URI "@streq /.well-known/carddav" "id:1003,phase:1,nolog,pass,ctl:ruleEngine=Off"
|
||||
# --------------------------------------------------------------------------
|
||||
# Office Online (WOPI & Hosting)
|
||||
# --------------------------------------------------------------------------
|
||||
# Whitelist for Office Online server communication
|
||||
SecRule REQUEST_URI "@rx ^/(hosting|op|we|wv|p|x|lo|m|o|browser)/" \
|
||||
"id:10014,phase:1,pass,nolog,ctl:ruleEngine=Off"
|
||||
|
||||
# Proxy Whitelist for Office Online (Internal)
|
||||
SecRule REMOTE_ADDR "@ipMatch 172.16.254.1" \
|
||||
"id:10034,phase:1,pass,nolog,chain,msg:'WHITELIST: [Proxy 172.16.254.1] Office Online WOPI'"
|
||||
SecRule REQUEST_URI "@beginsWith /index.php/apps/officeonline/wopi/files/" "ctl:ruleEngine=Off"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Specific Sync & Discovery (Legacy/Specific IDs reserved)
|
||||
# --------------------------------------------------------------------------
|
||||
SecRule REQUEST_URI "@streq /.well-known/caldav" "id:10002,phase:1,pass,nolog,ctl:ruleEngine=Off"
|
||||
SecRule REQUEST_URI "@streq /.well-known/carddav" "id:10003,phase:1,pass,nolog,ctl:ruleEngine=Off"
|
||||
|
||||
# Preview Generator
|
||||
SecRule REQUEST_URI "@beginsWith /index.php/core/preview" "id:10010,phase:1,pass,nolog,ctl:ruleRemoveById=9XXXXX"
|
||||
|
|
|
|||
|
|
@ -1,11 +1,22 @@
|
|||
# Ficheiro de Exceções do ModSecurity para o Zabbix (VERSÃO CORRIGIDA)
|
||||
# Ficheiro de Exceções do ModSecurity para o Zabbix (ATUALIZADO)
|
||||
|
||||
# Regra 1: Desativa completamente o ModSecurity para a API JSON-RPC e zabbix.php.
|
||||
# Esta regra continua a ser útil e está correta.
|
||||
SecRule REQUEST_URI "@rx (jsrpc\.php|zabbix\.php)" \
|
||||
"id:1001,phase:1,nolog,allow,ctl:ruleEngine=Off"
|
||||
# --------------------------------------------------------------------------
|
||||
# Zabbix Web Interface Protection
|
||||
# --------------------------------------------------------------------------
|
||||
# REMOVED: zabbix.php whitelist. The UI should be protected by WAF.
|
||||
# REMOVED: api_jsonrpc.php whitelist. This should only be accessed via VPN
|
||||
# (covered by Global Internal Network rule 10000).
|
||||
|
||||
# Regra 2: Desativa as regras específicas que causam falsos positivos na página de Descoberta de Hosts.
|
||||
# Lembre-se de substituir os IDs abaixo pelos que encontrou no seu log de auditoria.
|
||||
# --------------------------------------------------------------------------
|
||||
# Dashboard Noise Reduction
|
||||
# --------------------------------------------------------------------------
|
||||
# Allows jsrpc.php which handles some background AJAX for the dashboard.
|
||||
# If this causes security concerns, it can be removed, but usually generates false positives.
|
||||
SecRule REQUEST_URI "@streq /jsrpc.php" \
|
||||
"id:10004,phase:1,pass,nolog,ctl:ruleEngine=Off"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Host Discovery
|
||||
# --------------------------------------------------------------------------
|
||||
SecRule REQUEST_URI "@beginsWith /zabbix/host_discovery.php" \
|
||||
"id:1002,phase:1,nolog,allow,ctl:ruleRemoveById=9XXXXX,ctl:ruleRemoveById=9YYYYY"
|
||||
"id:10005,phase:1,pass,nolog,ctl:ruleRemoveById=9XXXXX,ctl:ruleRemoveById=9YYYYY"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
# Ficheiro de Exceções do ModSecurity para o Zammad
|
||||
|
||||
# Desativa a regra de falso positivo para toda a API do Zammad (/api/v1/).
|
||||
# Isto previne que o WAF bloqueie as ações legítimas da interface.
|
||||
# Lembre-se de substituir '9XXXXX' pelo ID da regra que encontrou no seu log de auditoria.
|
||||
# ID 10007: Whitelist Zammad API
|
||||
SecRule REQUEST_URI "@beginsWith /api/v1/" \
|
||||
"id:1004,phase:1,nolog,allow,ctl:ruleRemoveById=9XXXXX"
|
||||
"id:10007,phase:1,pass,nolog,allow,ctl:ruleRemoveById=9XXXXX"
|
||||
|
|
|
|||
|
|
@ -29,7 +29,13 @@ http {
|
|||
ssl_session_cache shared:SSL:60m;
|
||||
|
||||
# Include Snippets
|
||||
include /etc/nginx/snippets/*.conf;
|
||||
# Include Snippets (Global HTTP context)
|
||||
# Excludes acme_challenge.conf which is server-context only
|
||||
include /etc/nginx/snippets/cache_zones.conf;
|
||||
include /etc/nginx/snippets/log_formats.conf;
|
||||
include /etc/nginx/snippets/rate_limit.conf;
|
||||
include /etc/nginx/snippets/security_maps.conf;
|
||||
# include /etc/nginx/snippets/custom_errors.conf; # Optional globally
|
||||
|
||||
# Global Fallback Logs
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
$ContainerName = "nginx-proxy"
|
||||
|
||||
Write-Host "[Reload] Checking configuration in $ContainerName..." -ForegroundColor Cyan
|
||||
|
||||
# 1. Validate Configuration
|
||||
docker exec $ContainerName nginx -t
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host "[Reload] Configuration is VALID." -ForegroundColor Green
|
||||
|
||||
# 2. Graceful Reload
|
||||
Write-Host "[Reload] Triggering graceful reload..." -ForegroundColor Cyan
|
||||
docker exec $ContainerName nginx -s reload
|
||||
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host "[Reload] ✅ Reload signal sent successfully." -ForegroundColor Green
|
||||
Write-Host "[Reload] Zero-downtime update in progress." -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[Reload] ❌ Failed to send reload signal." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
} else {
|
||||
Write-Host "[Reload] ❌ Configuration is INVALID. Aborting reload." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
#!/bin/bash
|
||||
# Zero-Downtime Reload Script
|
||||
# Validates config first, then reloads NGINX gracefully.
|
||||
|
||||
CONTAINER_NAME="nginx-proxy"
|
||||
|
||||
echo "[Reload] Checking configuration in $CONTAINER_NAME..."
|
||||
|
||||
# 1. Validate Configuration (nginx -t)
|
||||
if docker exec "$CONTAINER_NAME" nginx -t; then
|
||||
echo "[Reload] Configuration is VALID."
|
||||
else
|
||||
echo "[Reload] ❌ Configuration is INVALID. Aborting reload."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 2. Graceful Reload (nginx -s reload)
|
||||
# This starts new workers with new config, while old workers finish requests.
|
||||
echo "[Reload] Triggering graceful reload..."
|
||||
if docker exec "$CONTAINER_NAME" nginx -s reload; then
|
||||
echo "[Reload] ✅ Reload signal sent successfully."
|
||||
echo "[Reload] Zero-downtime update in progress."
|
||||
else
|
||||
echo "[Reload] ❌ Failed to send reload signal."
|
||||
exit 1
|
||||
fi
|
||||
Loading…
Reference in New Issue