June 21, 2026
Making CrowdSec and Shorewall Work Together Without Breaking Each Other
By default, crowdsec-firewall-bouncer injects its own chain into iptables. That works fine on a simple system where nothing else is…
Umair
2 min read
By default, crowdsec-firewall-bouncer injects its own chain into iptables. That works fine on a simple system where nothing else is managing the firewall, but it becomes fragile when Shorewall is in charge.
Shorewall expects to own the firewall ruleset. Every time you run:
shorewall safe-restartshorewall safe-restartShorewall rebuilds the rules from its own configuration and removes anything it does not know about. That includes the CrowdSec chain injected by the bouncer.
The result is annoying but easy to miss… CrowdSec still detects malicious IPs, the bouncer may still receive decisions, but the firewall no longer blocks those IPs because the injected chain has disappeared…
How to use them together
CrowdSec and Shorewall both try to touch the same layer directly. The fix is to stop making CrowdSec write firewall chains itself and let it maintain an ipset instead. Shorewall can then use that set cleanly as part of its own rules
CrowdSec maintains the list of banned IPs inside an ipset, and Shorewall uses that ipset as its dynamic blacklist source. That way, CrowdSec keeps doing the detection and ban management, while Shorewall remains responsible for the firewall rules.
1. Change the CrowdSec Bouncer Mode to ipset
Open the CrowdSec firewall bouncer configuration file:
nvim /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yamlnvim /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yamlFind the current mode setting and change it from iptables to ipset:
mode: ipsetmode: ipsetThen comment out the iptables_chains section so the bouncer no longer tries to inject its own chains into iptables:
#iptables_chains:
# - INPUT
# - FORWARD
# - DOCKER-USER#iptables_chains:
# - INPUT
# - FORWARD
# - DOCKER-USERThe important part is that CrowdSec should now populate an ipset instead of trying to manage firewall chains directly.
Restart the bouncer:
systemctl restart crowdsec-firewall-bouncersystemctl restart crowdsec-firewall-bouncerAt this point, CrowdSec should start feeding banned IPs into the crowdsec-blacklists ipset.
2. Tell Shorewall to Use the CrowdSec ipset
Now edit the Shorewall configuration file:
nvim /etc/shorewall/shorewall.confnvim /etc/shorewall/shorewall.confAdd the following directives:
# CrowdSec
DYNAMIC_BLACKLIST=ipset-only:crowdsec-blacklists
SAVE_IPSETS=Yes# CrowdSec
DYNAMIC_BLACKLIST=ipset-only:crowdsec-blacklists
SAVE_IPSETS=YesThe first directive tells Shorewall to use the crowdsec-blacklists ipset as its dynamic blacklist source:
DYNAMIC_BLACKLIST=ipset-only:crowdsec-blacklistsDYNAMIC_BLACKLIST=ipset-only:crowdsec-blacklistsThis means Shorewall does not need CrowdSec to inject extra iptables chains. Shorewall will simply consult the ipset that CrowdSec keeps updated.
The second directive makes sure ipsets are saved across restarts:
SAVE_IPSETS=YesSAVE_IPSETS=YesWithout this, you may lose the ipset state after a reboot, depending on how your system is configured.
Once the changes are in place, restart Shorewall safely:
shorewall safe-restartshorewall safe-restartYou can now check whether the CrowdSec ipset is being populated correctly:
ipset list crowdsec-blacklistsipset list crowdsec-blacklistsExample output:
198.244.240.165 timeout 12880 packets 0 bytes 0
39.101.94.83 timeout 11880 packets 15 bytes 900
87.3.25.245 timeout 9865 packets 0 bytes 0
198.244.168.192 timeout 8927 packets 0 bytes 0
89.200.229.42 timeout 10302 packets 0 bytes 0
176.31.139.6 timeout 9534 packets 0 bytes 0
39.101.93.209 timeout 11861 packets 0 bytes 0
198.244.168.182 timeout 12904 packets 0 bytes 0
198.244.183.121 timeout 9057 packets 0 bytes 0
86.97.49.220 timeout 11702 packets 0 bytes 0
39.101.93.55 timeout 13020 packets 0 bytes 0
45.146.8.36 timeout 12929 packets 0 bytes 0198.244.240.165 timeout 12880 packets 0 bytes 0
39.101.94.83 timeout 11880 packets 15 bytes 900
87.3.25.245 timeout 9865 packets 0 bytes 0
198.244.168.192 timeout 8927 packets 0 bytes 0
89.200.229.42 timeout 10302 packets 0 bytes 0
176.31.139.6 timeout 9534 packets 0 bytes 0
39.101.93.209 timeout 11861 packets 0 bytes 0
198.244.168.182 timeout 12904 packets 0 bytes 0
198.244.183.121 timeout 9057 packets 0 bytes 0
86.97.49.220 timeout 11702 packets 0 bytes 0
39.101.93.55 timeout 13020 packets 0 bytes 0
45.146.8.36 timeout 12929 packets 0 bytes 0If you see entries like these, CrowdSec is feeding banned IPs into the ipset successfully. You can also run a Shorewall restart again to confirm that the blocklist survives Shorewall rule regeneration:
shorewall safe-restart
ipset list crowdsec-blacklistsshorewall safe-restart
ipset list crowdsec-blacklistsThe CrowdSec list should still be present. Now CrowdSec watches logs, detects hostile behavior, and maintains the list of banned IPs. Shorewall manages the firewall and applies the blocking logic through its own configuration.
That is much safer than letting the CrowdSec bouncer inject chains into a firewall ruleset that Shorewall will later rebuild anyway.