Firewall Rules
How the bouncer creates and manages firewall rules.
Rule types
Section titled “Rule types”The bouncer can create rules in three locations:
| Type | RouterOS path | Purpose |
| -------------- | ------------------------------------ | --------------------------------------------------------------- |
| Filter input | /ip/firewall/filter | Block incoming traffic (after connection tracking) |
| Raw prerouting | /ip/firewall/raw | Block incoming traffic (before connection tracking — lower CPU) |
| Filter output | /ip/firewall/filter (output chain) | Block outgoing traffic to banned IPs |
Each type has an IPv6 equivalent (e.g., /ipv6/firewall/filter).
Rule creation flow
Section titled “Rule creation flow”On startup, the bouncer follows this sequence:
-
Check for existing rules
Scans for bouncer-managed rules by matching the comment pattern.
-
Clean state
Removes any existing rules to ensure a fresh start.
-
Create new rules
Creates rules according to the current configuration.
-
Place at configured position
Places the managed block according to the effective
rule_placementfor that protocol and table: top, bottom, a numeric RouterOS position, or an anchor comment.
Rule structure
Section titled “Rule structure”Each rule has:
- Chain:
input,forward,prerouting, oroutput - Action:
droporreject(with optionalreject-with) - Interface: Optional input/output interface restriction
- Connection state: Optional connection-state matcher (filter only)
- Log settings: Optional logging with configurable prefix
- Comment: Structured identifier for management
Example rule as seen in RouterOS:
/ip/firewall/filter print where comment~"crowdsec-bouncer"# chain=input action=drop src-address-list=crowdsec-banned# in-interface=ether1 log=no# comment="crowdsec-bouncer:filter-input-input-v4 @cs-routeros-bouncer"Rule placement
Section titled “Rule placement”The bouncer places related rules as ordered blocks. A typical input block includes the following rules in order: whitelist (when configured), counting (when processed metrics are enabled), then the deny/reject rule. Placement happens after all rules in the block exist, so the internal order stays stable.
Placement is menu-local. A filter block is positioned within /ip firewall filter or /ipv6 firewall filter; a raw block is positioned within /ip firewall raw or /ipv6 firewall raw.
The bouncer can place its managed block (the related rules it creates and moves together) at the top, at the bottom, at a numeric RouterOS print position, or relative to an existing comment owned by another rule. If output blocking is enabled, the output block is moved with the same internal ordering. By default, the bouncer reuses the same placement strategy for IPv4 and IPv6. Table and protocol overrides can send filter, raw, IPv4, and IPv6 blocks to different locations. Precedence is global placement, global table override, protocol override, then protocol table override.
| Strategy | Behavior |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| top | Moves the block before the first usable non-bouncer rule. If RouterOS refuses the position, for example before dynamic or built-in rules, the bouncer retries lower positions. |
| bottom | Leaves newly-created rules appended at the end. |
| position | Requires position and uses zero-based RouterOS print numbering, excluding existing bouncer rules. Out-of-range positions append at bottom. |
| before_comment | Moves the block before the first non-bouncer rule whose comment matches the configured anchor. |
| after_comment | Moves the block after the matched anchor by inserting before the next non-bouncer rule; if the anchor is last, the block remains appended. |
Comment placement uses fallback (top by default, or bottom) when the anchor is missing or cannot be used. Numeric position ignores fallback because an out-of-range position naturally means append.
# Rules appear near the configured location; retry or fallback placement can choose a later valid target./ip/firewall/filter print# 0 chain=input action=drop src-address-list=crowdsec-banned ...# 1 chain=forward action=drop src-address-list=crowdsec-banned ...# 2 ... (your other rules)Rule identification
Section titled “Rule identification”Rules are identified by a structured comment:
{prefix}:{type}-{chain}-{direction}-{protocol} @cs-routeros-bouncer| Part | Values |
| ----------- | --------------------------------------------------------------- |
| prefix | Configurable via comment_prefix (default: crowdsec-bouncer) |
| type | filter or raw |
| chain | input, forward, prerouting, output |
| direction | input, output, or whitelist |
| protocol | v4 or v6 |
Cleanup on shutdown
Section titled “Cleanup on shutdown”When the bouncer receives a SIGTERM signal:
-
Remove rules
All firewall rules with matching comments are removed.
-
Preserve address lists
Address list entries are not removed — they expire naturally via their timeout.
This design means:
- Protection continues briefly after bouncer stops (until entries expire)
- No mass-delete operations are needed on shutdown
- Quick restart doesn’t leave the router unprotected during the gap