# Firewall Blocklist

> Block inbound traffic from IPs and CIDRs across one or more agents via nftables.

URL: https://docs.serverbee.app/en/docs/firewall

ServerBee can centrally manage an inbound-traffic blocklist. The server holds the canonical list, and each opted-in agent applies it via `nftables`.

## Requirements [#requirements]

* **Linux only** — agent uses the `nft` CLI.
* **`CAP_FIREWALL_BLOCK`** (bit `512`) must be enabled on the agent. It is **on by default**; capabilities are agent-owned, so to turn it off add `firewall_block` to the agent's `[capabilities]` deny list. See [Capabilities](/en/docs/capabilities).
* Agent process needs root or `CAP_NET_ADMIN`.

## Manual blocking [#manual-blocking]

Settings → Firewall → **Add block**. Enter an IP (`1.2.3.4`) or a CIDR (`10.0.0.0/8`). Choose the scope (`All servers`, `Selected`, `All except`). Optionally add a comment.

The server rejects targets that overlap a protected range:

* Loopback (`127.0.0.0/8`, `::1`)
* RFC 1918 (`10/8`, `172.16/12`, `192.168/16`, `fc00::/7`, `fe80::/10`)
* Multicast / unspecified
* Any CIDR in `firewall.allow_list` (`server.toml`)
* `server.trusted_proxies`
* Any agent's reported external IP

A `409` response with the matched reason is returned in those cases.

<Callout type="warn">
  **Protect your own public IP.** The "agent external IP" guardrail relies on the IPv4 /
  IPv6 address each agent reports about itself. On hosts where the agent's primary
  interface is a private bridge (Docker, NAT VPS, multi-homed), the reported address may
  **not** be the real public IP — and the guardrail will not catch an attempt to block it.

  To be safe, **add your VPS's public IP (or CIDR) to `firewall.allow_list` in
  `server.toml`**. Anything that overlaps this list is refused at create time, no matter
  who requests it. Example:

  ```toml
  [firewall]
  allow_list = ["198.51.100.42", "203.0.113.0/29"]
  ```

  This is also the way to protect your bastion / admin IPs from accidental auto-block
  actions.
</Callout>

## Auto-block from alerts [#auto-block-from-alerts]

Brute-force and port-scan alert rules can append a `block_source_ip` action that auto-inserts the event's source IP. See [Security Events → Auto-block source IP](/en/docs/security-events).

Auto-block is deduplicated by canonical target. If a row already exists and covers the triggering server, the auto-block is silently skipped. If it exists but does not cover the triggering server, the conflict is audited (`firewall_auto_block_skipped_conflict`) and no row is created — the operator can broaden the existing row manually.

## Agent execution [#agent-execution]

Each opted-in agent maintains an `inet serverbee` nftables table:

```text
table inet serverbee {
    set block_v4 { type ipv4_addr; flags interval; }
    set block_v6 { type ipv6_addr; flags interval; }
    chain input {
        type filter hook input priority -10;
        ip  saddr @block_v4 drop
        ip6 saddr @block_v6 drop
    }
}
```

The server pushes incremental adds/removes over WebSocket. On agent reconnect or capability transition, it sends a `Reset` followed by a full `Sync`. The agent acks the result of each entry; failed entries stay eligible for retry on the next sync.

## Removing the cleanup [#removing-the-cleanup]

Capabilities are Agent-owned, so there is no Server-side switch. To stop using the feature:

1. On the Agent host, add `firewall_block` to `[capabilities].deny` in `/opt/serverbee/etc/agent.toml` (preserve any existing deny entries).
2. Run `sudo serverbee restart agent`. The capability transition resets the synchronized blocklist and removes ServerBee's table.
3. Verify with `sudo nft list table inet serverbee`. If the Agent could not complete the reset (for example it was offline or lacked nftables privileges), remove only ServerBee's table manually:

```bash
sudo nft delete table inet serverbee
```

## Audit log [#audit-log]

Every action is recorded in the audit log and shown on the Firewall page's Activity tab: `firewall_block_created`, `firewall_block_deleted`, `firewall_block_applied_agent`, `firewall_block_removed_agent`, `firewall_block_rejected_server`, `firewall_block_rejected_agent`, `firewall_auto_block_skipped_conflict`, `firewall_reset_acked`.

## Limitations [#limitations]

* nftables only — no iptables fallback
* IPv4 and IPv6, no domain names
* Permanent blocks — no scheduled expiry
* `input` chain only — does not filter `forward` / `output`

<Cards>
  <Card title="Capabilities" href="/en/docs/capabilities" />

  <Card title="Security Events" href="/en/docs/security-events" />

  <Card title="Alerts & Notifications" href="/en/docs/alerts" />

  <Card title="Configuration" href="/en/docs/configuration" />
</Cards>
