feat: integration actions to judge logic and update docs for this
Some checks failed
build / build (push) Failing after 1m55s

This commit is contained in:
d3m0k1d
2026-02-24 18:03:17 +03:00
parent fd38af9cb0
commit 5cc61aca75
6 changed files with 236 additions and 25 deletions

View File

@@ -23,6 +23,7 @@ If you have any questions or suggestions, create issue on [Github](https://githu
- [x] Nginx and Sshd support
- [x] Working with ufw/iptables/nftables/firewalld
- [x] Prometheus metrics
- [x] Actions (email, webhook, script)
- [ ] Add support for most popular web-service
- [ ] User regexp for custom services
- [ ] TUI interface
@@ -112,10 +113,20 @@ For first steps use this commands
banforge init # Create config files and database
banforge daemon # Start BanForge daemon (use systemd or another init system to create a service)
```
You can edit the config file with examples in
You can edit the config file with examples in
- `/etc/banforge/config.toml` main config file
- `/etc/banforge/rules.toml` ban rules
- `/etc/banforge/rules.d/*.toml` individual rule files with actions support
For more information see the [docs](https://github.com/d3m0k1d/BanForge/docs).
## Actions
BanForge supports actions that are executed after a successful IP ban:
- **Email** - Send email notifications via SMTP
- **Webhook** - Send HTTP requests to external services (Slack, Telegram, etc.)
- **Script** - Execute custom scripts
See [configuration docs](https://github.com/d3m0k1d/BanForge/blob/main/docs/config.md#actions) for detailed setup instructions.
# License
The project is licensed under the [GPL-3.0](https://github.com/d3m0k1d/BanForge/blob/master/LICENSE)

View File

@@ -43,9 +43,129 @@ Example:
max_retry = 3
method = ""
ban_time = "1m"
# Actions are executed after successful ban
[[rule.action]]
type = "email"
enabled = true
email = "admin@example.com"
email_sender = "banforge@example.com"
email_subject = "BanForge Alert: IP Banned"
smtp_host = "smtp.example.com"
smtp_port = 587
smtp_user = "user@example.com"
smtp_password = "password"
smtp_tls = true
body = "IP {ip} has been banned for rule {rule}"
[[rule.action]]
type = "webhook"
enabled = true
url = "https://hooks.example.com/alert"
method = "POST"
headers = { "Content-Type" = "application/json", "Authorization" = "Bearer token" }
body = "{\"ip\": \"{ip}\", \"rule\": \"{rule}\", \"service\": \"{service}\"}"
[[rule.action]]
type = "script"
enabled = true
script = "/usr/local/bin/notify.sh"
interpretator = "bash"
```
**Description**
The [[rule]] section require name and one of the following parameters: service, path, status, method. To add a rule, create a [[rule]] block and specify the parameters.
ban_time require in format "1m", "1h", "1d", "1M", "1y".
If you want to ban all requests to PHP files (e.g., path = "*.php") or requests to the admin panel (e.g., path = "/admin/*").
If max_retry = 0 ban on first request.
## Actions
Actions are executed after a successful IP ban. You can configure multiple actions per rule.
### Action Types
#### 1. Email Notification
Send email alerts when an IP is banned.
```toml
[[rule.action]]
type = "email"
enabled = true
email = "admin@example.com"
email_sender = "banforge@example.com"
email_subject = "BanForge Alert"
smtp_host = "smtp.example.com"
smtp_port = 587
smtp_user = "user@example.com"
smtp_password = "password"
smtp_tls = true
body = "IP {ip} has been banned"
```
| Field | Required | Description |
|-------|----------|-------------|
| `type` | + | Must be "email" |
| `enabled` | + | Enable/disable this action |
| `email` | + | Recipient email address |
| `email_sender` | + | Sender email address |
| `email_subject` | - | Email subject (default: "BanForge Alert") |
| `smtp_host` | + | SMTP server host |
| `smtp_port` | + | SMTP server port |
| `smtp_user` | + | SMTP username |
| `smtp_password` | + | SMTP password |
| `smtp_tls` | - | Use TLS connection (default: false) |
| `body` | - | Email body text |
#### 2. Webhook Notification
Send HTTP webhook requests when an IP is banned.
```toml
[[rule.action]]
type = "webhook"
enabled = true
url = "https://hooks.example.com/alert"
method = "POST"
headers = { "Content-Type" = "application/json", "Authorization" = "Bearer token" }
body = "{\"ip\": \"{ip}\", \"rule\": \"{rule}\"}"
```
| Field | Required | Description |
|-------|----------|-------------|
| `type` | + | Must be "webhook" |
| `enabled` | + | Enable/disable this action |
| `url` | + | Webhook URL |
| `method` | - | HTTP method (default: "POST") |
| `headers` | - | HTTP headers as key-value pairs |
| `body` | - | Request body (supports variables) |
#### 3. Script Execution
Execute a custom script when an IP is banned.
```toml
[[rule.action]]
type = "script"
enabled = true
script = "/usr/local/bin/notify.sh"
interpretator = "bash"
```
| Field | Required | Description |
|-------|----------|-------------|
| `type` | + | Must be "script" |
| `enabled` | + | Enable/disable this action |
| `script` | + | Path to script file |
| `interpretator` | - | Script interpretator (e.g., "bash", "python"). If empty, script runs directly |
### Variables
The following variables can be used in `body` fields (email, webhook):
| Variable | Description |
|----------|-------------|
| `{ip}` | Banned IP address |
| `{rule}` | Rule name that triggered the ban |
| `{service}` | Service name |
| `{ban_time}` | Ban duration |

View File

@@ -214,6 +214,8 @@ Configuration files are stored in \fI/etc/banforge/\fR:
.IP \(bu 2
\fIrules.d/*.toml\fR \- individual rule files
.RE
.PP
See \fBbanforge(5)\fR for configuration file format details including actions setup.
.
.SH "EXIT STATUS"
.PP

View File

@@ -198,9 +198,36 @@ Use the following suffixes for ban duration:
\fBy\fR \- Years (365 days)
.RE
.
.SH "ACTIONS(NOT WORKING ON THIS VERSION)"
.SH "ACTIONS"
.PP
Rules can trigger custom actions when an IP is banned.
Multiple actions can be configured per rule.
Actions are executed after successful ban at firewall level.
.
.SS "Supported Action Types"
.PP
.RS
.IP \(bu 2
\fBemail\fR \- Send email notification via SMTP
.IP \(bu 2
\fBwebhook\fR \- Send HTTP request to external service
.IP \(bu 2
\fBscript\fR \- Execute custom script
.RE
.
.SS "Variables"
.PP
The following variables can be used in \fBbody\fR fields:
.RS
.IP \(bu 2
\fB{ip}\fR \- Banned IP address
.IP \(bu 2
\fB{rule}\fR \- Rule name that triggered the ban
.IP \(bu 2
\fB{service}\fR \- Service name
.IP \(bu 2
\fB{ban_time}\fR \- Ban duration
.RE
.
.SS "Script Action"
.PP
@@ -213,7 +240,7 @@ Execute a custom script when an IP is banned.
.IP \(bu 2
\fBenabled\fR \- Enable/disable action (true/false)
.IP \(bu 2
\fBinterpretator\fR \- Script interpretator (e.g., "/bin/bash")
\fBinterpretator\fR \- Script interpretator (e.g., "bash", "python")
.IP \(bu 2
\fBscript\fR \- Path to script file
.RE
@@ -226,11 +253,11 @@ Execute a custom script when an IP is banned.
service = "nginx"
status = "403"
ban_time = "1h"
[[rule.action]]
type = "script"
enabled = true
interpretator = "/bin/bash"
interpretator = "bash"
script = "/opt/banforge/scripts/notify.sh"
.fi
.RE
@@ -246,13 +273,13 @@ Send HTTP webhook when an IP is banned.
.IP \(bu 2
\fBenabled\fR \- Enable/disable action (true/false)
.IP \(bu 2
\fBurl\fR \- Webhook URL
\fBurl\fR \- Webhook URL \fI(required)\fR
.IP \(bu 2
\fBmethod\fR \- HTTP method (POST, GET)
\fBmethod\fR \- HTTP method (POST, GET, etc.)
.IP \(bu 2
\fBheaders\fR \- Custom headers (key-value pairs)
.IP \(bu 2
\fBbody\fR \- Request body (supports templates)
\fBbody\fR \- Request body (supports variables)
.RE
.PP
\fBExample:\fR
@@ -263,14 +290,8 @@ Send HTTP webhook when an IP is banned.
enabled = true
url = "https://hooks.example.com/ban"
method = "POST"
[rule.action.headers]
Content-Type = "application/json"
Authorization = "Bearer TOKEN"
[rule.action.body]
ip = "{{.IP}}"
reason = "{{.Rule}}"
headers = { "Content-Type" = "application/json", "Authorization" = "Bearer TOKEN" }
body = "{\\\"ip\\\": \\\"{ip}\\\", \\\"rule\\\": \\\"{rule}\\\"}"
.fi
.RE
.
@@ -285,21 +306,23 @@ Send email notification when an IP is banned.
.IP \(bu 2
\fBenabled\fR \- Enable/disable action (true/false)
.IP \(bu 2
\fBemail\fR \- Recipient email address
\fBemail\fR \- Recipient email address \fI(required)\fR
.IP \(bu 2
\fBemail_sender\fR \- Sender email address
\fBemail_sender\fR \- Sender email address \fI(required)\fR
.IP \(bu 2
\fBemail_subject\fR \- Email subject
\fBemail_subject\fR \- Email subject (default: "BanForge Alert")
.IP \(bu 2
\fBsmtp_host\fR \- SMTP server host
\fBsmtp_host\fR \- SMTP server host \fI(required)\fR
.IP \(bu 2
\fBsmtp_port\fR \- SMTP server port
\fBsmtp_port\fR \- SMTP server port \fI(required)\fR
.IP \(bu 2
\fBsmtp_user\fR \- SMTP username
\fBsmtp_user\fR \- SMTP username \fI(required)\fR
.IP \(bu 2
\fBsmtp_password\fR \- SMTP password
\fBsmtp_password\fR \- SMTP password \fI(required)\fR
.IP \(bu 2
\fBsmtp_tls\fR \- Enable TLS (true/false)
.IP \(bu 2
\fBbody\fR \- Email body text (supports variables)
.RE
.PP
\fBExample:\fR
@@ -316,6 +339,49 @@ Send email notification when an IP is banned.
smtp_user = "banforge"
smtp_password = "secret"
smtp_tls = true
body = "IP {ip} has been banned for rule {rule}"
.fi
.RE
.
.SH "COMPLETE RULE EXAMPLE WITH ACTIONS"
.PP
.RS
.nf
[[rule]]
name = "nginx-403"
service = "nginx"
status = "403"
max_retry = 3
ban_time = "1h"
# Email notification
[[rule.action]]
type = "email"
enabled = true
email = "admin@example.com"
email_sender = "banforge@example.com"
smtp_host = "smtp.example.com"
smtp_port = 587
smtp_user = "banforge"
smtp_password = "secret"
smtp_tls = true
body = "IP {ip} banned by rule {rule}"
# Slack webhook
[[rule.action]]
type = "webhook"
enabled = true
url = "https://hooks.slack.com/services/XXX/YYY/ZZZ"
method = "POST"
headers = { "Content-Type" = "application/json" }
body = "{\\\"text\\\": \\\"IP {ip} banned for rule {rule}\\\"}"
# Custom script
[[rule.action]]
type = "script"
enabled = true
script = "/usr/local/bin/ban-notify.sh"
interpretator = "bash"
.fi
.RE
.

View File

@@ -31,7 +31,7 @@ type Rule struct {
Method string `toml:"method"`
MaxRetry int `toml:"max_retry"`
BanTime string `toml:"ban_time"`
Action []Action
Action []Action `toml:"action"`
}
type Metrics struct {

View File

@@ -5,6 +5,7 @@ import (
"strings"
"time"
"github.com/d3m0k1d/BanForge/internal/actions"
"github.com/d3m0k1d/BanForge/internal/blocker"
"github.com/d3m0k1d/BanForge/internal/config"
"github.com/d3m0k1d/BanForge/internal/logger"
@@ -124,6 +125,17 @@ func (j *Judge) Tribunal() {
metrics.IncError()
break
}
for _, action := range rule.Action {
executor := &actions.Executor{Action: action}
if err := executor.Execute(); err != nil {
j.logger.Error("Action execution failed",
"rule", rule.Name,
"action_type", action.Type,
"error", err)
}
}
j.logger.Info(
"IP banned successfully",
"ip",