Add optional ntfy ban alerts to CrowdSec variants
When configuring CrowdSec, optionally wire up an ntfy push notification via CrowdSec's HTTP notification plugin: writes /etc/crowdsec/notifications/ntfy.yaml and references it from the default profile in profiles.yaml. Alerts fire on a ban decision (after repeated failed attempts), not on every failed login. Document the behavior in SCRIPT-VARIANTS.md, including why Authelia (email-only) doesn't cover failed-login push. Both crowdsec variants verified with 'bash -n' and a --dry-run --unattended pass (exit 0). https://claude.ai/code/session_017eA2qqq9jfF2tNtpUYL8vK
This commit is contained in:
@@ -28,6 +28,26 @@ complete, standalone script).
|
|||||||
- Enforcement via `crowdsec-firewall-bouncer-iptables`
|
- Enforcement via `crowdsec-firewall-bouncer-iptables`
|
||||||
- **Geo-blocking + community IP-reputation blocklists** — the capability
|
- **Geo-blocking + community IP-reputation blocklists** — the capability
|
||||||
that fail2ban and Authelia both lack
|
that fail2ban and Authelia both lack
|
||||||
|
- **Optional ntfy alerts on bans** — when configuring CrowdSec the script
|
||||||
|
can wire up an [ntfy](https://ntfy.sh/) push notification (via CrowdSec's
|
||||||
|
HTTP notification plugin). It writes `/etc/crowdsec/notifications/ntfy.yaml`
|
||||||
|
and references it from the default profile in
|
||||||
|
`/etc/crowdsec/profiles.yaml`. The same script can also install a
|
||||||
|
self-hosted **ntfy server** (separate menu option), so alerts can stay on
|
||||||
|
your own infrastructure.
|
||||||
|
|
||||||
|
### A note on "notification of failed attempts"
|
||||||
|
|
||||||
|
CrowdSec alerts fire on a **ban decision** — i.e. once an IP crosses the
|
||||||
|
failed-attempt threshold for a scenario (e.g. `crowdsecurity/ssh-bf`), not on
|
||||||
|
every individual failed login. That gives you one actionable "X banned for Y"
|
||||||
|
push instead of a flood. To alert on a single failed login you'd lower the
|
||||||
|
scenario threshold or write a custom scenario, but the ban-level alert is the
|
||||||
|
recommended default.
|
||||||
|
|
||||||
|
Authelia, by contrast, only sends **email/SMTP** notifications (for password
|
||||||
|
reset and 2FA device registration) — it has no built-in "failed login" push,
|
||||||
|
which is why CrowdSec → ntfy is the path used here.
|
||||||
|
|
||||||
## Notes on the security layers
|
## Notes on the security layers
|
||||||
|
|
||||||
|
|||||||
@@ -4748,6 +4748,45 @@ labels:
|
|||||||
echo " Subscribe to community/3rd-party blocklists at:"
|
echo " Subscribe to community/3rd-party blocklists at:"
|
||||||
echo " https://app.crowdsec.net/"
|
echo " https://app.crowdsec.net/"
|
||||||
|
|
||||||
|
# Optional: push ban alerts to ntfy
|
||||||
|
prompt_yn "Send CrowdSec ban alerts to an ntfy topic? (y/n):" "n" CS_NTFY
|
||||||
|
if [ "$CS_NTFY" = "y" ] || [ "$CS_NTFY" = "Y" ]; then
|
||||||
|
prompt_text " ntfy topic URL (e.g. https://ntfy.sh/my-crowdsec):" "https://ntfy.sh/crowdsec-alerts" CS_NTFY_URL
|
||||||
|
sudo mkdir -p /etc/crowdsec/notifications
|
||||||
|
NTFY_FILE="/etc/crowdsec/notifications/ntfy.yaml"
|
||||||
|
NTFY_CONTENT="type: http
|
||||||
|
name: ntfy
|
||||||
|
log_level: info
|
||||||
|
format: |
|
||||||
|
{{range . -}}
|
||||||
|
{{range .Decisions -}}
|
||||||
|
{{.Value}} banned: {{.Scenario}} for {{.Duration}}
|
||||||
|
{{end -}}
|
||||||
|
{{end -}}
|
||||||
|
url: $CS_NTFY_URL
|
||||||
|
method: POST
|
||||||
|
headers:
|
||||||
|
Title: CrowdSec ban
|
||||||
|
Priority: high
|
||||||
|
Tags: rotating_light"
|
||||||
|
if echo "$NTFY_CONTENT" | sudo tee "$NTFY_FILE" > /dev/null; then
|
||||||
|
echo " ✓ Created ntfy notification ($NTFY_FILE)"
|
||||||
|
# Wire the notification into the default profile (only once)
|
||||||
|
if ! grep -qE "^\s*- ntfy" /etc/crowdsec/profiles.yaml 2>/dev/null; then
|
||||||
|
sudo awk '1; /^on_success:/ && !d {print "notifications:"; print " - ntfy"; d=1}' \
|
||||||
|
/etc/crowdsec/profiles.yaml | sudo tee /etc/crowdsec/profiles.yaml.new > /dev/null \
|
||||||
|
&& sudo mv /etc/crowdsec/profiles.yaml.new /etc/crowdsec/profiles.yaml
|
||||||
|
echo " ✓ Enabled ntfy alerts in CrowdSec default profile"
|
||||||
|
else
|
||||||
|
echo " ✓ ntfy already referenced in CrowdSec profile"
|
||||||
|
fi
|
||||||
|
echo " ℹ Alerts fire when an IP is banned (after repeated failed attempts),"
|
||||||
|
echo " not on every individual failed login."
|
||||||
|
else
|
||||||
|
echo " ⚠ Failed to write ntfy notification config"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Restart services to apply
|
# Restart services to apply
|
||||||
prompt_yn "Restart CrowdSec to apply changes? (y/n):" "y" RESTART_CS
|
prompt_yn "Restart CrowdSec to apply changes? (y/n):" "y" RESTART_CS
|
||||||
if [ "$RESTART_CS" = "y" ] || [ "$RESTART_CS" = "Y" ]; then
|
if [ "$RESTART_CS" = "y" ] || [ "$RESTART_CS" = "Y" ]; then
|
||||||
|
|||||||
@@ -4728,6 +4728,45 @@ labels:
|
|||||||
echo " Subscribe to community/3rd-party blocklists at:"
|
echo " Subscribe to community/3rd-party blocklists at:"
|
||||||
echo " https://app.crowdsec.net/"
|
echo " https://app.crowdsec.net/"
|
||||||
|
|
||||||
|
# Optional: push ban alerts to ntfy
|
||||||
|
prompt_yn "Send CrowdSec ban alerts to an ntfy topic? (y/n):" "n" CS_NTFY
|
||||||
|
if [ "$CS_NTFY" = "y" ] || [ "$CS_NTFY" = "Y" ]; then
|
||||||
|
prompt_text " ntfy topic URL (e.g. https://ntfy.sh/my-crowdsec):" "https://ntfy.sh/crowdsec-alerts" CS_NTFY_URL
|
||||||
|
sudo mkdir -p /etc/crowdsec/notifications
|
||||||
|
NTFY_FILE="/etc/crowdsec/notifications/ntfy.yaml"
|
||||||
|
NTFY_CONTENT="type: http
|
||||||
|
name: ntfy
|
||||||
|
log_level: info
|
||||||
|
format: |
|
||||||
|
{{range . -}}
|
||||||
|
{{range .Decisions -}}
|
||||||
|
{{.Value}} banned: {{.Scenario}} for {{.Duration}}
|
||||||
|
{{end -}}
|
||||||
|
{{end -}}
|
||||||
|
url: $CS_NTFY_URL
|
||||||
|
method: POST
|
||||||
|
headers:
|
||||||
|
Title: CrowdSec ban
|
||||||
|
Priority: high
|
||||||
|
Tags: rotating_light"
|
||||||
|
if echo "$NTFY_CONTENT" | sudo tee "$NTFY_FILE" > /dev/null; then
|
||||||
|
echo " ✓ Created ntfy notification ($NTFY_FILE)"
|
||||||
|
# Wire the notification into the default profile (only once)
|
||||||
|
if ! grep -qE "^\s*- ntfy" /etc/crowdsec/profiles.yaml 2>/dev/null; then
|
||||||
|
sudo awk '1; /^on_success:/ && !d {print "notifications:"; print " - ntfy"; d=1}' \
|
||||||
|
/etc/crowdsec/profiles.yaml | sudo tee /etc/crowdsec/profiles.yaml.new > /dev/null \
|
||||||
|
&& sudo mv /etc/crowdsec/profiles.yaml.new /etc/crowdsec/profiles.yaml
|
||||||
|
echo " ✓ Enabled ntfy alerts in CrowdSec default profile"
|
||||||
|
else
|
||||||
|
echo " ✓ ntfy already referenced in CrowdSec profile"
|
||||||
|
fi
|
||||||
|
echo " ℹ Alerts fire when an IP is banned (after repeated failed attempts),"
|
||||||
|
echo " not on every individual failed login."
|
||||||
|
else
|
||||||
|
echo " ⚠ Failed to write ntfy notification config"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Restart services to apply
|
# Restart services to apply
|
||||||
prompt_yn "Restart CrowdSec to apply changes? (y/n):" "y" RESTART_CS
|
prompt_yn "Restart CrowdSec to apply changes? (y/n):" "y" RESTART_CS
|
||||||
if [ "$RESTART_CS" = "y" ] || [ "$RESTART_CS" = "Y" ]; then
|
if [ "$RESTART_CS" = "y" ] || [ "$RESTART_CS" = "Y" ]; then
|
||||||
|
|||||||
Reference in New Issue
Block a user