Skip to content

set-only mode causes crowdsec-firewall-bouncer to flood crowdsec-firewall-bouncer.log #291

Description

@jarppiko

Summary

If crowdsec-firewall-bouncer uses mode=nftables and set-only=true, metrics collection floods crowdsec-firewall-bouncer.log with lines like this every 10 seconds:

$ tail /var/log/crowdsec-firewall-bouncer.log
time="28-05-2023 13:36:43" level=error msg="can't collect dropped packets for ipv4 from nft: while running /usr/sbin/nft -j list chain ip filter crowdsec-chain-input: exit status 1"
time="28-05-2023 13:36:53" level=error msg="can't collect dropped packets for ipv4 from nft: while running /usr/sbin/nft -j list chain ip filter crowdsec-chain-input: exit status 1"
time="28-05-2023 13:37:03" level=error msg="can't collect dropped packets for ipv4 from nft: while running /usr/sbin/nft -j list chain ip filter crowdsec-chain-input: exit status 1"
time="28-05-2023 13:37:13" level=error msg="can't collect dropped packets for ipv4 from nft: while running /usr/sbin/nft -j list chain ip filter crowdsec-chain-input: exit status 1"
time="28-05-2023 13:37:23" level=error msg="can't collect dropped packets for ipv4 from nft: while running /usr/sbin/nft -j list chain ip filter crowdsec-chain-input: exit status 1"

set-only mode is intended for more complex firewall setups (e.g. in routers) where Crowdsec's the automated firewall rules cannot be used (e.g. there are multiple interfaces and crowdsec should control only some of those).

Root cause

This bug was probably introduced in #231 since the PR seemed to consider only "auto-mode" (set-only=false).

nftables.metrics.CollectMetrics() (line 118) does not handle set-only mode since it assumes there is a nftables chain with name chain-hook (where hook is prerouting, input, output, forward or ingress) to query from. In set-only mode crowdsec manages only blocked IPs in a named nftables set and the chain param is not used.

Workaround

It is not possible to disable metrics collection. Therefore, as a workaround an admin has to create/rename a chain according to an undocumented naming convention $nftables.ipv4.chain-$nftables_hooks.hook (referring to bouncer config file yaml fields here).

For example, if nftables config in bouncer config looks like this:

# /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml
...
nftables:
  ipv4:
    enabled: true
    set-only: true
    table: filter
    chain: existing-chain-without-its-input-postfix

nftables_hooks:
  - input

Then there needs to be a nftables chain in the right table with name : existing-chain-without-its-input-postfix-input.

Solution options

I could come up with couple of options how to solve this issue.

  1. Add disable_metrics option
  2. Disable metrics collection in set-only mode automatically
  3. Add support for metrics collection in set-only mode

Technical considerations

1. Add disable_metrics bouncer config option

This would require admin to manually fix the issue.

Commit 9619b01 introduced this functionality, but in the same PR #282 the commit was later reversed (d17dafa). Maybe @mmetc knows why the change was reversed.

2. Disable metrics collection in set-only mode

This can be done by editing one line in collectDropped() in nftables/metrics.go.

func (c *nftContext) collectDropped(path string, hooks []string) (int, int, int) {
	if c.conn == nil || c.setOnly {     // "|| c.setOnly" added
		return 0, 0, 0
	}
        ...

3. Add support for metrics collection in set-only mode

This should not be a big change.

  • Modify collectDroppedPackets() in metrics.go to take chain name directly instead of doing string concatenation magic within the function.
  • Modify collectDropped() in metrics.go to handle set-only=true mode:
    • set-only=false: create chain name here with the string concatenation magic
    • set-only=true: use chain name directly from bouncer config

Drawback

A drawback of this implementation is that it would collect metrics only from one chain.

Collecting metrics from all chains / hooks in set-only mode would require a way to tell the bouncer what chains are being used. If nftables_hooks config option could be changed to contain actual chain names and the string concatenation could be scrapped, then the nftables_hooks config option could be used also in set-only mode to configure metrics collection right.

Disclaimer: I am the author of set-only mode

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions