---
title: "Blindar um servidor e colocar um WAF na frente da sua aplicação"
description: "O erpc worker blinda o servidor desde a primeira implantação, e uma tabela no erpc.toml põe um WAF na frente de uma API pública. O que ele faz e o que não faz."
canonical: "https://erpc.global/pt/doc/erpc-cli/worker-firewall-and-waf/"
locale: "pt"
---

# Blindar um servidor e colocar um WAF na frente da sua aplicação

Desde a primeira implantação, o `erpc worker` só permite SSH a partir do seu endereço e descarta todas as outras conexões de entrada. Uma tabela `[waf]` coloca um proxy de filtragem na frente da sua API.

Esta página descreve o ERPC CLI `v0.1.0-rc.4`, uma versão de pré-lançamento.

## O firewall

Uma implantação configura o firewall do servidor antes de a aplicação iniciar pela primeira vez:

- SSH somente a partir de `firewall.ssh_allow` e do endereço de onde vem a implantação;
- todas as outras conexões de entrada descartadas, exceto `run.port` a partir de `firewall.app_allow`; para uma aplicação atrás de um WAF, a porta do WAF no lugar dela, e somente onde o WAF no servidor já executa as regras que `[waf]` define agora ([abaixo](https://erpc.global/pt/doc/erpc-cli/worker-firewall-and-waf/#colocar-um-waf-na-frente-da-sua-aplicação)).

Cada alteração é executada sob um temporizador de rollback de 120 segundos e só é mantida depois que uma nova conexão consegue entrar, de modo que uma alteração errada não pode deixar você trancado do lado de fora.

Mas a allowlist continua valendo depois que o endereço a partir do qual ela foi criada deixa de ser o seu: se o endereço da sua casa mudar, o caminho de volta é o suporte da ERPC, para um servidor ERPC, ou o console do provedor, para um servidor próprio. Mantenha em `firewall.ssh_allow` um segundo endereço a partir do qual você consegue acessar o servidor (um escritório, uma saída de VPN) antes de confiar em um endereço doméstico.

Se o seu endereço mudar, adicione todos os endereços fixos que seus administradores usam:

```bash
erpc worker firewall allow --to ssh 203.0.113.10 198.51.100.7
```

| Comando | O que faz |
| --- | --- |
| `erpc worker firewall list` | Mostra quem pode acessar o servidor: o `erpc.toml` ao lado da tabela do servidor |
| `erpc worker firewall allow --to ssh\|app <addresses>` | Permite a entrada dos endereços e aplica a alteração. O SSH é permitido a partir de endereços individuais; uma rede só é aceita com `--to app` |
| `erpc worker firewall deny --to ssh\|app <addresses>` | Deixa de permitir a entrada deles |
| `erpc worker firewall sync` | Faz o firewall do servidor voltar a ser o que o `erpc.toml` diz |

## Colocar um WAF na frente da sua aplicação

Adicione uma tabela ao `erpc.toml`:

```toml
[waf]
port = 8080
```

Em seguida, o `erpc worker deploy` executa um proxy reverso HTTP no servidor, em uma unidade systemd própria (`erpc-waf-<app>-<env>`): um usuário dinâmico sem privilégios, sem chave, sem segredo e sem nada do worker, limitado a 1 GiB de memória. Ele escuta em `waf.port`, lê cada requisição antes da aplicação, recusa o que as regras dele indicam e encaminha o restante para a aplicação em `127.0.0.1:<run.port>`.

- **A aplicação fica no loopback.** A porta dela nunca é aberta para fora. O `erpc worker api` e o health check acessam a aplicação pelo loopback, sem passar pelo WAF.
- **Quem pode se conectar continua definido pela lista do firewall**, e a porta do WAF é o único lugar em que essa lista pode dizer todos:

  ```sh
  erpc worker firewall allow --to app 0.0.0.0/0     # and ::/0
  ```

  Sem ninguém na lista, o WAF escuta e ninguém entra, e a implantação avisa isso.
- **A porta é aberta depois que o WAF passa a escutar nela**, nunca antes. Uma implantação cujo WAF não sobe falha e diz o motivo, com a aplicação ainda em execução.
- **Quando você altera `[waf]`,** a porta não é aberta para ninguém novo até que uma implantação tenha colocado as novas regras em vigor.
- **Retirar `[waf]`** do `erpc.toml` e implantar remove o WAF do servidor.

## Configurações do WAF

Somente `port` é obrigatória. Todas as chaves, com seus valores padrão:

```toml
[waf]
port = 8080          # the public port, 1024 or above; the app keeps [run] port
methods = ["GET", "POST", "PUT", "DELETE"]
allow_paths = []     # every path
deny_paths = []
max_body_bytes = 1048576
max_header_bytes = 16384
rate = { per_second = 50, burst = 100 }
max_connections_per_address = 32
ban = { after = 100, window_secs = 60, for_secs = 600 }
block_probes = true
header_timeout_secs = 10
body_timeout_secs = 30
upstream_timeout_secs = 30
new_connections = { per_second = 50, burst = 100 }
```

| Chave | O que faz | O que é recusado recebe |
| --- | --- | --- |
| `methods` | Os métodos encaminhados, em maiúsculas (no máximo 16; nunca `CONNECT`) | 405, com `Allow` |
| `allow_paths` | Os caminhos encaminhados; sem nenhum na lista, são todos os caminhos. Um padrão é um único caminho, ou tudo sob um prefixo quando termina em `*`: `/api/*` é `/api` e tudo abaixo dele. É comparado com o caminho depois da decodificação percentual, diferenciando maiúsculas de minúsculas | 404 |
| `deny_paths` | Caminhos recusados, escritos da mesma forma e verificados primeiro | 403 |
| `max_body_bytes` | O maior corpo de requisição, até 64 MiB | 413 |
| `max_header_bytes` | O maior tamanho da linha de requisição e dos cabeçalhos juntos, de 1024 a 65536 | 431 |
| `rate` | Requisições por segundo de um endereço, e quantas de uma vez antes que a taxa se aplique | 429, com `Retry-After` |
| `max_connections_per_address` | Conexões que um endereço mantém ao mesmo tempo | A conexão é fechada, sem resposta |
| `ban` | Depois de `after` requisições bloqueadas dentro de `window_secs`, o endereço é recusado por `for_secs` (até 30 dias) | As conexões dele são fechadas, sem resposta |
| `block_probes` | Recusa o que scanners pedem (`/.env`, `/.git`, `/wp-login.php` e similares) | 403 |
| `header_timeout_secs` | Quanto tempo um cliente tem para enviar o cabeçalho de uma requisição, de 1 a 120. Também é quanto tempo se espera por um cliente que parou no meio de um corpo ou parou de receber a resposta | 408 para o cabeçalho; 400 para um corpo que parou; a conexão fechada para uma resposta não recebida |
| `body_timeout_secs` | Quanto tempo o corpo de uma requisição pode levar no total, de 1 a 600, sem contar o tempo em que o WAF espera pela aplicação | 408 |
| `upstream_timeout_secs` | Quanto tempo a aplicação tem para aceitar a conexão e começar a responder, de 1 a 600 | 504; 502 quando a aplicação não está escutando |
| `new_connections` | O limite do próprio firewall para novas conexões TCP por segundo de um endereço à porta do WAF, descartadas pelo nftables antes que o proxy as veja. Enquanto o conjunto de endereços do nftables estiver cheio, um endereço que não está nele não é contado, então esse limite não se aplica a ele até que o conjunto tenha espaço de novo; os limites do próprio proxy (`rate`, `max_connections_per_address`, `ban`) continuam valendo | O pacote é descartado |

`rate`, `max_connections_per_address`, `ban` e `new_connections` são desativados com `false` (`ban = false`), e uma chave omitida fica com o valor padrão. O `erpc worker check` diz o que a tabela `[waf]` vai fazer, e o que há de errado com ela, antes de qualquer implantação.

## O que o WAF faz sem nenhuma configuração

- Uma requisição que não pode ser lida como uma única requisição HTTP/1 sem ambiguidade recebe 400, assim como um caminho que não está na forma normal.
- Uma requisição para mudar de protocolo (`Upgrade`) recebe 501.
- Toda recusa conta para o banimento, e cada recusa encerra a conexão dela.
- Um endereço é um endereço IPv4 ou um `/64` IPv6.
- O WAF não encaminha ao proxy os cabeçalhos da conexão do cliente (`Connection` e os cabeçalhos que ele nomeia, `Keep-Alive`, `Proxy-Authenticate`, `Proxy-Authorization`, `Proxy-Connection`, `TE`, `Trailer`), `Expect`, cabeçalhos cujo nome tem um sublinhado, nem os `Forwarded`, `X-Real-IP` e `X-Forwarded-Proto` enviados pelo próprio cliente. Ele define `X-Real-IP` como o endereço de onde veio a conexão e adiciona esse endereço ao final de `X-Forwarded-For`; somente a última entrada de `X-Forwarded-For` vem do proxy.

## Ver o que o WAF faz

| Comando | Mostra |
| --- | --- |
| `erpc worker status` | A porta do WAF, para onde ele encaminha, desde quando, e as contagens desde então |
| `erpc worker firewall list` | Quem pode acessar a porta do WAF, e o que foi bloqueado, por regra |
| `erpc worker logs --waf` | Cada requisição bloqueada: a regra, o status, o endereço do cliente, o método e os primeiros 200 bytes do destino |

Uma requisição encaminhada não deixa linha de log, e nenhum cabeçalho ou corpo é registrado em log em momento algum; a query de uma requisição bloqueada é registrada, até onde os 200 bytes alcançam. O que um cliente envia não consegue escrever no seu terminal: o WAF grava o journal dele como ASCII imprimível.

## O que o WAF não faz

- **Sem TLS.** Ele usa HTTP/1.1 simples na porta dele.
- **Sem HTTP/2:** ele responde 400 a esse protocolo.
- **Sem WebSocket**, nem qualquer outro `Upgrade`: 501.
- **Não olha dentro dos corpos.** Um corpo é medido, nunca lido. A lista de sondagens é curta e é um filtro de ruído, não uma garantia: a aplicação continua verificando a própria entrada.
- **Sem autenticação.** Quem pode chamar a aplicação é decisão da aplicação, e da lista do firewall.
- **Um endereço é um cliente.** Clientes atrás de um mesmo NAT, proxy ou CDN compartilham uma taxa e um banimento; um cliente com muitos endereços tem tantas taxas quanto endereços.
- **Banimentos e contagens são esquecidos** quando o WAF reinicia.
- **Ele lembra no máximo 8192 endereços** e mantém no máximo 1024 conexões ao mesmo tempo.
- **Ele escuta somente em IPv4,** então uma entrada IPv6 em `app_allow` ainda não alcança nada.
- **Um caminho é comparado como os bytes em que ele é decodificado.** Uma aplicação que lê caminhos de forma mais permissiva (ignorando maiúsculas e minúsculas, parâmetros `;`, decodificando duas vezes) pode ser alcançada por um nome que `deny_paths` não cobre. `allow_paths` não tem essa brecha: o que não está na lista não é encaminhado.
- **Um leitor lento é atendido até o fim.** Um cliente que continua recebendo uma resposta, por mais devagar que seja, é atendido até o fim.
- **Um flood pode interromper um upload grande.** O WAF roda em uma única thread, então um flood pode interromper um upload grande com 408. Uma aplicação que recebe corpos grandes aumenta `body_timeout_secs` junto com `max_body_bytes`.

[O guia do worker](https://github.com/elsoul/erpc-cli/blob/v0.1.0-rc.4/docs/worker.md) traz todas as regras, inclusive quando uma alteração em `app_allow` fica retida até a próxima implantação.
