> For the complete documentation index, see [llms.txt](https://docs.ipcheck.ing/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ipcheck.ing/developer/pt-br/configuration/security-options.md).

# Opções de Segurança

Proteja uma instância pública do MyIP: primeiro o firewall de borda (Cloudflare como exemplo prático), com a limitação de taxa integrada do app e as verificações de referer como a proteção final.

O backend do MyIP faz proxy de várias APIs de terceiros, algumas pagas. Deixado totalmente aberto, uma instância pública vira um proxy anônimo e gratuito para quem quer que a encontre.

Pense na proteção como duas camadas, nesta ordem:

1. **A borda (camada primária recomendada).** Um CDN/WAF na frente da sua origem — o Cloudflare é o exemplo usado abaixo — bloqueia tráfego abusivo antes que ele chegue ao seu servidor, com ferramentas muito melhores do que qualquer aplicativo consegue oferecer: detecção gerenciada de bots, regras flexíveis de limitação de taxa, desafios e uma visão global dos IPs dos atacantes.
2. **O próprio app (a rede de segurança).** Quatro variáveis de ambiente constroem uma última linha de defesa no backend. Vale a pena configurá-las mesmo atrás de uma borda — é isso que protege você quando alguém encontra o endereço real da sua origem e contorna a borda por completo — mas elas são uma retaguarda, não a defesa principal.

## Proteja primeiro na borda (recomendado)

Qualquer CDN/WAF com regras de taxa por IP funciona do mesmo jeito; as etapas abaixo usam o Cloudflare porque é a escolha mais comum e o plano gratuito dele já cobre o essencial.

{% stepper %}
{% step %}

#### Proxie seus registros DNS pelo Cloudflare

No painel de DNS do Cloudflare, mantenha o registro do hostname do seu MyIP **Proxy ativado** (nuvem laranja), para que todo o tráfego entre pela borda do Cloudflare. O MyIP foi feito para isso: o backend já lê `CF-Connecting-IP` para identificar os IPs reais dos clientes, e suas rotas com cache `/api/*` são servidas pelo cache da borda, que absorve uma grande parte da carga antes que ela chegue até você.
{% endstep %}

{% step %}

#### Adicione uma regra de limitação de taxa para `/api/*`

Em **Segurança → WAF → Regras de limitação de taxa**, crie uma regra que corresponda ao caminho da sua API — por exemplo, expressão `(http.request.uri.path wildcard "/api/*")` — e bloqueie o IP de origem quando ele exceder seu limite. A limitação de taxa está disponível em todos os planos; a contagem de regras e as opções de janela variam conforme o plano. Como o cache da borda já responde às buscas repetidas, visitantes legítimos raramente precisam de volumes altos de requisições — comece mais rígido do que você imagina e afrouxe se os usuários reais reclamarem.
{% endstep %}

{% step %}

#### Ative a proteção contra bots

Ative **Bot Fight Mode** (Segurança → Bots). A maior parte do abuso de uma instância pública do MyIP é raspagem automatizada dos endpoints de geolocalização, que é exatamente o que isso combate. Se o seu plano tiver regras WAF personalizadas, um **Desafio gerenciado** em tráfego não proveniente de navegador para `/api/*` é uma alternativa mais suave que nunca bloqueia um usuário real.
{% endstep %}

{% step %}

#### Tranque sua origem

As regras de borda só ajudam se o tráfego não puder pular a borda. Configure o firewall do servidor de origem para aceitar HTTP(S) somente de [os intervalos de IP do Cloudflare](https://www.cloudflare.com/ips/) — ou retire a origem da internet pública por completo com o Cloudflare Tunnel. Se a origem responder a requisições diretas, um invasor que descubra o endereço dela contorna todas as regras acima; este é exatamente o cenário para o qual existem as variáveis em nível de app abaixo.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
As requisições atendidas pelo cache do Cloudflare nunca chegam à origem, então ficam invisíveis para os limitadores em nível de app abaixo — outro motivo pelo qual a borda é o lugar certo para o controle de volume.
{% endhint %}

## A própria rede de segurança do app

Quatro variáveis de ambiente constroem a camada de retaguarda no backend. Todas as quatro são opcionais e vêm desligadas (ou permissivas) por padrão.

| Variável                           | Finalidade                                  | Padrão                 |
| ---------------------------------- | ------------------------------------------- | ---------------------- |
| `ALLOWED_DOMAINS`                  | Quais sites podem chamar `/api/*`           | `localhost` único      |
| `SECURITY_RATE_LIMIT`              | Limite rígido de requisições por IP         | `0` — desativado       |
| `SECURITY_DELAY_AFTER`             | Redução progressiva de velocidade por IP    | `0` — desativado       |
| `SECURITY_BLACKLIST_LOG_FILE_PATH` | Registro em disco de IPs limitados por taxa | vazio — nenhum arquivo |

## `ALLOWED_DOMAINS` — a proteção por referer

Toda `/api/*` a rota passa por uma verificação de referer. O backend lê o cabeçalho `Referer` , extrai seu **hostname**, e exige que esse hostname esteja na lista de permitidos.

A lista de permitidos é `localhost` mais as entradas separadas por vírgula em `ALLOWED_DOMAINS`.

As rejeições são `403`:

| Situação                                                             | Resposta                                |
| -------------------------------------------------------------------- | --------------------------------------- |
| Não `Referer` nenhum cabeçalho                                       | `{"error": "O que você está fazendo?"}` |
| Referer presente, hostname não permitido (ou não pôde ser analisado) | `{"error": "Acesso negado"}`            |

{% hint style="danger" %}
**Se você servir o MyIP em um domínio real, precisa configurar isso.** Com `ALLOWED_DOMAINS` vazio, apenas `localhost` passa — então uma implantação acessada em `https://ip.example.com` ou `http://192.168.1.10:18966` recebe `403` em cada chamada de API, e o app parece quebrado enquanto a página estática carrega normalmente.
{% endhint %}

Regras para ter em mente:

* **Apenas hostnames.** Sem esquema, sem porta, sem caminho: `example.com`, não `https://example.com:443/`.
* **Correspondências exatas.** `example.com` não cobre `www.example.com`. Liste ambos.
* **Endereços IP contam como hostnames.** Chegar ao app em `http://192.168.1.10:18966` significa adicionar `192.168.1.10`.
* **`localhost` é sempre permitido**, então o desenvolvimento local nunca precisa de configuração.

{% code title=".env" %}

```bash
ALLOWED_DOMAINS="example.com,www.example.com,ip.example.com"
```

{% endcode %}

{% hint style="warning" %}
A verificação de referer é um impedimento a abuso, não autenticação. Qualquer cliente pode enviar um cabeçalho `Referer` arbitrário. Ela impede hotlinking casual e scripts oportunistas; não impede um raspador determinado. Combine-a com limitação de taxa.
{% endhint %}

Atrás de um proxy reverso, certifique-se de que seu proxy encaminhe o cabeçalho `Referer` intacto. Veja [Proxy reverso e domínios](/developer/pt-br/getting-started/reverse-proxy-and-domains.md).

## `SECURITY_RATE_LIMIT` — limite rígido

Um limite de requisições por IP em `/api/*`, com suporte de `express-rate-limit`.

* **Janela**: 20 minutos, deslizante.
* **Limite**: o número que você definir. `0` ou vazio significa que o limitador simplesmente nunca é montado.
* **Acima do limite**: `429` com `{"message": "Muitas requisições"}`.
* **Rota isenta**: `/api/monitoring`, o túnel do Sentry, que tem seu próprio limitador — veja [Monitoramento de erros](/developer/pt-br/configuration/error-monitoring.md).

{% hint style="info" %}
A linha de inicialização imprime `🛡️ Limitador de taxa ativado — N solicitações por 60 minutos`. A janela aplicada no código é **20 minutos**.
{% endhint %}

### O que é registrado

O backend registra o momento em que um IP cruza o limite — **uma vez**, na transição, não em cada requisição bloqueada subsequente. Isso evita que um cliente abusivo martelando um endpoint limitado inunde seus logs.

```
WARN: IP com limitação de taxa
    ip: "203.0.113.45"
```

Quando um DSN de backend do Sentry está configurado, essa mesma linha é espelhada para o Sentry.

### Como o IP do cliente é determinado

O limitador e a linha de log resolvem o IP do solicitante nesta ordem:

1. `CF-Connecting-IP`
2. a primeira entrada de `X-Forwarded-For`
3. `CF-Connecting-IPv6`
4. o endereço de socket que o Express vê

O app roda com `trust proxy` definido como `1`, o que significa que ele confia em exatamente um salto de cabeçalhos de proxy.

{% hint style="warning" %}
Se o seu proxy reverso não definir `X-Forwarded-For`, cada requisição parece vir do proxy — um IP, uma cota compartilhada, e o primeiro visitante mais ativo bloqueia todo mundo. Verifique o encaminhamento de cabeçalhos antes de ativar o limitador.
{% endhint %}

## `SECURITY_DELAY_AFTER` — redução progressiva de velocidade

Um companheiro mais suave, apoiado por `express-slow-down`. Em vez de rejeitar, ele atrasa.

* **Janela**: 60 minutos, deslizante.
* **Requisições gratuitas**: o número que você definir. As requisições além dele são respondidas lentamente.
* **Atraso**: `400 ms × total de requisições feitas na janela`.
* `0` ou vazio significa que o middleware nunca é montado.
* Mesma `/api/monitoring` isenção.

{% hint style="warning" %}
O atraso é calculado a partir da contagem **total** de acessos, não do excedente — então ele começa alto e sobe rápido. Com `SECURITY_DELAY_AFTER="40"`, a requisição 41 já espera cerca de 16 segundos; com `"100"`, a requisição 101 espera cerca de 40 segundos. Escolha um valor sabendo que a primeira requisição limitada já é uma espera longa, e espere timeouts do lado do cliente além disso.
{% endhint %}

Redução de velocidade e limitação de taxa se acumulam. Trate `SECURITY_RATE_LIMIT` como a defesa principal e recorra à redução de velocidade apenas quando quiser que surtos automatizados desacelerem em vez de falhar.

## `SECURITY_BLACKLIST_LOG_FILE_PATH` — registro em disco

Opcional. Quando definido, toda transição de limitação de taxa também é anexada a um arquivo de texto simples.

{% code title=".env" %}

```bash
SECURITY_BLACKLIST_LOG_FILE_PATH="logs/blacklist-ip.log"
```

{% endcode %}

* O caminho é resolvido **relativo à raiz da aplicação**. Diretórios ausentes são criados.
* Uma linha CSV por IP: `ip,count,first-seen-timestamp`.
* O timestamp é a hora local do host com um deslocamento UTC explícito, por exemplo `2026-07-14 10:23:45 +0800`.
* Em um reincidente, a **contagem incrementa e o timestamp original permanece**, para que você possa ver quando um IP apareceu pela primeira vez.

```
203.0.113.45,7,2026-07-14 10:23:45 +0800
198.51.100.9,1,2026-07-15 02:11:07 +0800
```

Deixá-lo vazio não muda nada na aplicação das regras — o log de aviso continua sendo acionado. O arquivo existe para implantações que querem um registro permanente, por exemplo para alimentar um firewall ou um script no estilo fail2ban.

{% hint style="info" %}
No Docker, escreva o registro em um volume montado. Um caminho dentro da camada gravável do contêiner desaparece quando o contêiner é recriado.
{% endhint %}

## Ordem dos middlewares

Vale saber quando você depura um `403` ou um `429`:

1. registro de requisições HTTP, se `LOG_HTTP=true` — então os 429 aparecem no log
2. Limitador de taxa (se ativado)
3. Redução de velocidade (se ativada)
4. Análise do corpo JSON
5. Filtro de Referer
6. O manipulador da rota

A limitação de taxa, portanto, acontece **antes de** a verificação de referer. Uma enxurrada de requisições com um referer ruim ainda consome a cota do infrator — o que é o comportamento desejado.

Observe também que um CDN na frente do app serve respostas `/api/*` em cache sem jamais chegar à origem, então essas requisições ficam invisíveis para o limitador. A maioria das rotas com muita leitura pode ser colocada em cache na borda.

## Valores de retaguarda recomendados para uma instância pública

Mesmo com a borda configurada, defina estas variáveis para que a origem consiga se defender sozinha:

{% tabs %}
{% tab title="Node (.env)" %}
{% code title=".env" %}

```bash
ALLOWED_DOMAINS="example.com,www.example.com"
SECURITY_RATE_LIMIT="600"
SECURITY_BLACKLIST_LOG_FILE_PATH="logs/blacklist-ip.log"
```

{% endcode %}
{% endtab %}

{% tab title="Docker" %}

```bash
docker run -d -p 18966:18966 \
  -e ALLOWED_DOMAINS="example.com,www.example.com" \
  -e SECURITY_RATE_LIMIT="600" \
  -e SECURITY_BLACKLIST_LOG_FILE_PATH="logs/blacklist-ip.log" \
  -v "$(pwd)/logs:/app/logs" \
  --name myip \
  jason5ng32/myip:latest
```

{% endtab %}
{% endtabs %}

Esses números são um ponto de partida, não uma regra. Ajuste-os:

* Um carregamento completo de página dispara **muitas** `/api/*` chamadas — fontes de IP, verificações de conectividade, sondagens DNS. Um único visitante facilmente gasta dezenas de requisições por sessão.
* Defina o limite baixo demais e usuários normais encontrarão `429` no meio do diagnóstico.
* Acompanhe o registro e os `IP com limitação de taxa` avisos por uma semana e depois aperte.
* Atrás de um CGNAT ou de um NAT corporativo, muitos usuários reais compartilham um único IP. Deixe margem.

{% hint style="success" %}
A camada em uma frase: deixe a borda absorver e filtrar o volume, e dimensione estas variáveis com generosidade suficiente para que elas só atuem em tráfego que passou por ela.
{% endhint %}

## Páginas relacionadas

* [Variáveis de Ambiente](/developer/pt-br/reference/environment-variables.md) — a lista completa
* [Proxy reverso e domínios](/developer/pt-br/getting-started/reverse-proxy-and-domains.md) — cabeçalhos que seu proxy precisa encaminhar
* [Logs](/developer/pt-br/configuration/logging.md) — onde os avisos aparecem
* [Chaves de API opcionais](/developer/pt-br/configuration/optional-api-keys.md) — as cotas que você está protegendo


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.ipcheck.ing/developer/pt-br/configuration/security-options.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
