---
title: "Een server afschermen en een WAF voor uw app plaatsen"
description: "erpc worker schermt een server af vanaf de eerste uitrol, en één tabel in erpc.toml zet een WAF voor een publieke API. Wat het doet en wat niet."
canonical: "https://erpc.global/nl/doc/erpc-cli/worker-firewall-and-waf/"
locale: "nl"
---

# Een server afschermen en een WAF voor uw app plaatsen

Vanaf de eerste uitrol laat `erpc worker` SSH alleen toe vanaf uw adres en verwerpt het elke andere inkomende verbinding. Een tabel `[waf]` zet een filterende proxy voor uw API.

Deze pagina beschrijft ERPC CLI `v0.1.0-rc.4`, een pre-release.

## De firewall

Een uitrol stelt de firewall van de server in voordat de app voor het eerst start:

- SSH alleen vanaf `firewall.ssh_allow` en het adres waarvandaan de uitrol komt;
- elke andere inkomende verbinding verworpen, behalve `run.port` vanaf `firewall.app_allow`; voor een app achter een WAF in plaats daarvan de poort van de WAF, en alleen waar de WAF op de server al de regels draait die `[waf]` nu voorschrijft ([hieronder](https://erpc.global/nl/doc/erpc-cli/worker-firewall-and-waf/#een-waf-voor-uw-app-plaatsen)).

Elke wijziging loopt onder een rollbacktimer van 120 seconden en wordt pas behouden zodra een nieuwe verbinding binnenkomt, zodat een foute wijziging u niet kan buitensluiten.

De allowlist overleeft wel het adres waarvandaan hij is gemaakt: als uw thuisadres verandert, is de weg terug naar binnen ERPC-support voor een ERPC-server, of de console van de provider voor een eigen server. Zet een tweede adres waarvandaan u de server kunt bereiken (een kantoor, een VPN-uitgang) in `firewall.ssh_allow` voordat u op een thuisadres vertrouwt.

Als uw adres verandert, voeg dan elk vast adres toe dat uw beheerders gebruiken:

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

| Commando | Wat het doet |
| --- | --- |
| `erpc worker firewall list` | Toont wie de server mag bereiken: `erpc.toml` naast de tabel van de server |
| `erpc worker firewall allow --to ssh\|app <addresses>` | Laat adressen binnen en voert dat door. SSH wordt toegestaan vanaf afzonderlijke adressen; een netwerk wordt alleen geaccepteerd met `--to app` |
| `erpc worker firewall deny --to ssh\|app <addresses>` | Laat ze niet meer toe |
| `erpc worker firewall sync` | Maakt de firewall van de server weer gelijk aan wat `erpc.toml` zegt |

## Een WAF voor uw app plaatsen

Voeg één tabel toe aan `erpc.toml`:

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

`erpc worker deploy` draait daarna een HTTP-reverse proxy op de server, in een eigen systemd-unit (`erpc-waf-<app>-<env>`): een dynamische gebruiker zonder privileges, zonder sleutel, zonder secret en zonder iets van de worker, beperkt tot 1 GiB geheugen. Hij luistert op `waf.port`, leest elk verzoek voordat de app dat doet, weigert wat zijn regels noemen en stuurt de rest door naar de app op `127.0.0.1:<run.port>`.

- **De app blijft op loopback.** Zijn eigen poort wordt nooit van buitenaf geopend. `erpc worker api` en de health check bereiken de app via loopback, buiten de WAF om.
- **Wie verbinding mag maken, wordt nog steeds bepaald door de lijst van de firewall**, en de poort van de WAF is de enige plek waar die lijst iedereen mag noemen:

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

  Staat er niemand op de lijst, dan luistert de WAF en wordt niemand toegelaten, en de uitrol meldt dat.
- **De poort wordt geopend zodra de WAF erop luistert**, nooit eerder. Een uitrol waarvan de WAF niet opkomt, mislukt en zegt waarom, terwijl de app blijft draaien.
- **Als u `[waf]` wijzigt,** wordt de poort voor niemand nieuws geopend totdat een uitrol de nieuwe regels op hun plaats heeft gezet.
- **`[waf]` weghalen** uit `erpc.toml` en uitrollen verwijdert de WAF van de server.

## WAF-instellingen

Alleen `port` is verplicht. Elke sleutel, met zijn standaardwaarde:

```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 }
```

| Sleutel | Wat het doet | Wat geweigerd wordt, krijgt |
| --- | --- | --- |
| `methods` | De methoden die worden doorgestuurd, in hoofdletters (hoogstens 16; nooit `CONNECT`) | 405, met `Allow` |
| `allow_paths` | De paden die worden doorgestuurd; staat er geen op de lijst, dan is dat elk pad. Een patroon is één pad, of alles onder een prefix als het eindigt op `*`: `/api/*` is `/api` en alles daaronder. Vergeleken met het pad na eenmalige percent-decodering, hoofdlettergevoelig | 404 |
| `deny_paths` | Geweigerde paden, op dezelfde manier geschreven en als eerste gecontroleerd | 403 |
| `max_body_bytes` | De grootste body van een verzoek, tot 64 MiB | 413 |
| `max_header_bytes` | De grootste verzoekregel en headers samen, 1024 tot 65536 | 431 |
| `rate` | Verzoeken per seconde vanaf één adres, en hoeveel tegelijk voordat de snelheidslimiet geldt | 429, met `Retry-After` |
| `max_connections_per_address` | Verbindingen die één adres tegelijk openhoudt | De verbinding gesloten, onbeantwoord |
| `ban` | Na `after` geblokkeerde verzoeken binnen `window_secs` wordt het adres `for_secs` lang geweigerd (tot 30 dagen) | Zijn verbindingen gesloten, onbeantwoord |
| `block_probes` | Weigert wat scanners opvragen (`/.env`, `/.git`, `/wp-login.php` en dergelijke) | 403 |
| `header_timeout_secs` | Hoeveel tijd een client heeft om de kop van een verzoek te versturen, 1 tot 120. Ook hoelang er wordt gewacht op een client die midden in een body is gestopt, of die is gestopt met het afnemen van zijn antwoord | 408 voor de kop; 400 voor een body die stopte; de verbinding gesloten voor een antwoord dat niet wordt afgenomen |
| `body_timeout_secs` | Hoelang de body van een verzoek in totaal mag duren, 1 tot 600, zonder de tijd mee te tellen die de WAF op de app wacht | 408 |
| `upstream_timeout_secs` | Hoeveel tijd de app heeft om de verbinding aan te nemen en te beginnen met antwoorden, 1 tot 600 | 504; 502 als de app niet luistert |
| `new_connections` | De eigen limiet van de firewall op nieuwe TCP-verbindingen per seconde vanaf één adres naar de poort van de WAF, door nftables verworpen voordat de proxy ze ziet. Zolang de adresset van nftables vol is, wordt een adres dat er niet in staat niet geteld, zodat deze limiet er niet voor geldt totdat de set weer ruimte heeft; de eigen limieten van de proxy (`rate`, `max_connections_per_address`, `ban`) gelden nog steeds | Het pakket verworpen |

`rate`, `max_connections_per_address`, `ban` en `new_connections` worden uitgeschakeld met `false` (`ban = false`), en een weggelaten sleutel heeft zijn standaardwaarde. `erpc worker check` zegt vóór elke uitrol wat de tabel `[waf]` zal doen en wat er mis mee is.

## Wat de WAF doet zonder dat er iets ingesteld hoeft te worden

- Een verzoek dat zich niet laat lezen als één ondubbelzinnig HTTP/1-verzoek krijgt 400, en een pad dat niet in normaalvorm staat ook.
- Een verzoek om van protocol te wisselen (`Upgrade`) krijgt 501.
- Elke weigering telt mee voor de ban, en elke weigering beëindigt haar verbinding.
- Een adres is een IPv4-adres, of een IPv6-`/64`.
- De WAF stuurt de headers van de verbinding tussen de client en de proxy niet door (`Connection` en de headers die deze noemt, `Keep-Alive`, `Proxy-Authenticate`, `Proxy-Authorization`, `Proxy-Connection`, `TE`, `Trailer`), evenmin `Expect`, headers met een underscore in hun naam, of de eigen `Forwarded`, `X-Real-IP` en `X-Forwarded-Proto` van de client. Hij zet `X-Real-IP` op het adres waarvandaan de verbinding kwam en voegt dat adres toe aan het einde van `X-Forwarded-For`; alleen voor de laatste vermelding van `X-Forwarded-For` staat de proxy in.

## Zien wat de WAF doet

| Commando | Toont |
| --- | --- |
| `erpc worker status` | De poort van de WAF, waarheen hij doorstuurt, sinds wanneer, en de tellingen sindsdien |
| `erpc worker firewall list` | Wie de poort van de WAF mag bereiken, en wat er is geblokkeerd, per regel |
| `erpc worker logs --waf` | Elk geblokkeerd verzoek: de regel, de status, het adres van de client, de methode en de eerste 200 bytes van het doel |

Een doorgestuurd verzoek laat geen logregel achter, en er wordt nooit een header of body gelogd; de query van een geblokkeerd verzoek wel, voor zover de 200 bytes reiken. Wat een client stuurt, kan niets op uw terminal schrijven: de WAF schrijft zijn journal als afdrukbare ASCII.

## Wat de WAF niet doet

- **Geen TLS.** Hij spreekt onversleuteld HTTP/1.1 op zijn poort.
- **Geen HTTP/2:** daarop antwoordt hij met 400.
- **Geen WebSocket**, en ook geen andere `Upgrade`: 501.
- **Geen blik in bodies.** Een body wordt gemeten, nooit gelezen. De probelijst is kort en een ruisfilter, geen garantie: de app blijft zijn invoer controleren.
- **Geen authenticatie.** Wie de app mag aanroepen, is aan de app om te bepalen, en aan de lijst van de firewall.
- **Eén adres is één client.** Clients achter één NAT, proxy of CDN delen een snelheidslimiet en een ban; een client met veel adressen heeft evenveel snelheidslimieten.
- **Bans en tellingen worden vergeten** wanneer de WAF herstart.
- **Hij onthoudt hoogstens 8192 adressen** en houdt hoogstens 1024 verbindingen tegelijk open.
- **Hij luistert alleen op IPv4,** dus een IPv6-vermelding in `app_allow` bereikt nog niets.
- **Een pad wordt vergeleken als de bytes waarnaar het decodeert.** Een app die paden losser leest (hoofdletters negeren, parameters met `;`, dubbel decoderen) kan worden bereikt onder een naam die `deny_paths` niet dekt. `allow_paths` heeft zo'n gat niet: wat niet op de lijst staat, wordt niet doorgestuurd.
- **Een trage lezer wordt tot het einde bediend.** Een client die een antwoord blijft afnemen, hoe langzaam ook, wordt tot het einde bediend.
- **Een flood kan een grote upload afbreken.** De WAF draait op één thread, dus een flood kan een grote upload afbreken met 408. Een app die grote bodies aanneemt, verhoogt `body_timeout_secs` samen met `max_body_bytes`.

[De worker-handleiding](https://github.com/elsoul/erpc-cli/blob/v0.1.0-rc.4/docs/worker.md) bevat elke regel, ook wanneer een wijziging aan `app_allow` tot de volgende uitrol wordt aangehouden.
