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] Nginx and Sshd support
- [x] Working with ufw/iptables/nftables/firewalld - [x] Working with ufw/iptables/nftables/firewalld
- [x] Prometheus metrics - [x] Prometheus metrics
- [x] Actions (email, webhook, script)
- [ ] Add support for most popular web-service - [ ] Add support for most popular web-service
- [ ] User regexp for custom services - [ ] User regexp for custom services
- [ ] TUI interface - [ ] TUI interface
@@ -112,10 +113,20 @@ For first steps use this commands
banforge init # Create config files and database banforge init # Create config files and database
banforge daemon # Start BanForge daemon (use systemd or another init system to create a service) 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/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). 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 # License
The project is licensed under the [GPL-3.0](https://github.com/d3m0k1d/BanForge/blob/master/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 max_retry = 3
method = "" method = ""
ban_time = "1m" 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** **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. 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". 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 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. 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 .IP \(bu 2
\fIrules.d/*.toml\fR \- individual rule files \fIrules.d/*.toml\fR \- individual rule files
.RE .RE
.PP
See \fBbanforge(5)\fR for configuration file format details including actions setup.
. .
.SH "EXIT STATUS" .SH "EXIT STATUS"
.PP .PP

View File

@@ -198,9 +198,36 @@ Use the following suffixes for ban duration:
\fBy\fR \- Years (365 days) \fBy\fR \- Years (365 days)
.RE .RE
. .
.SH "ACTIONS(NOT WORKING ON THIS VERSION)" .SH "ACTIONS"
.PP .PP
Rules can trigger custom actions when an IP is banned. 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" .SS "Script Action"
.PP .PP
@@ -213,7 +240,7 @@ Execute a custom script when an IP is banned.
.IP \(bu 2 .IP \(bu 2
\fBenabled\fR \- Enable/disable action (true/false) \fBenabled\fR \- Enable/disable action (true/false)
.IP \(bu 2 .IP \(bu 2
\fBinterpretator\fR \- Script interpretator (e.g., "/bin/bash") \fBinterpretator\fR \- Script interpretator (e.g., "bash", "python")
.IP \(bu 2 .IP \(bu 2
\fBscript\fR \- Path to script file \fBscript\fR \- Path to script file
.RE .RE
@@ -226,11 +253,11 @@ Execute a custom script when an IP is banned.
service = "nginx" service = "nginx"
status = "403" status = "403"
ban_time = "1h" ban_time = "1h"
[[rule.action]] [[rule.action]]
type = "script" type = "script"
enabled = true enabled = true
interpretator = "/bin/bash" interpretator = "bash"
script = "/opt/banforge/scripts/notify.sh" script = "/opt/banforge/scripts/notify.sh"
.fi .fi
.RE .RE
@@ -246,13 +273,13 @@ Send HTTP webhook when an IP is banned.
.IP \(bu 2 .IP \(bu 2
\fBenabled\fR \- Enable/disable action (true/false) \fBenabled\fR \- Enable/disable action (true/false)
.IP \(bu 2 .IP \(bu 2
\fBurl\fR \- Webhook URL \fBurl\fR \- Webhook URL \fI(required)\fR
.IP \(bu 2 .IP \(bu 2
\fBmethod\fR \- HTTP method (POST, GET) \fBmethod\fR \- HTTP method (POST, GET, etc.)
.IP \(bu 2 .IP \(bu 2
\fBheaders\fR \- Custom headers (key-value pairs) \fBheaders\fR \- Custom headers (key-value pairs)
.IP \(bu 2 .IP \(bu 2
\fBbody\fR \- Request body (supports templates) \fBbody\fR \- Request body (supports variables)
.RE .RE
.PP .PP
\fBExample:\fR \fBExample:\fR
@@ -263,14 +290,8 @@ Send HTTP webhook when an IP is banned.
enabled = true enabled = true
url = "https://hooks.example.com/ban" url = "https://hooks.example.com/ban"
method = "POST" method = "POST"
headers = { "Content-Type" = "application/json", "Authorization" = "Bearer TOKEN" }
[rule.action.headers] body = "{\\\"ip\\\": \\\"{ip}\\\", \\\"rule\\\": \\\"{rule}\\\"}"
Content-Type = "application/json"
Authorization = "Bearer TOKEN"
[rule.action.body]
ip = "{{.IP}}"
reason = "{{.Rule}}"
.fi .fi
.RE .RE
. .
@@ -285,21 +306,23 @@ Send email notification when an IP is banned.
.IP \(bu 2 .IP \(bu 2
\fBenabled\fR \- Enable/disable action (true/false) \fBenabled\fR \- Enable/disable action (true/false)
.IP \(bu 2 .IP \(bu 2
\fBemail\fR \- Recipient email address \fBemail\fR \- Recipient email address \fI(required)\fR
.IP \(bu 2 .IP \(bu 2
\fBemail_sender\fR \- Sender email address \fBemail_sender\fR \- Sender email address \fI(required)\fR
.IP \(bu 2 .IP \(bu 2
\fBemail_subject\fR \- Email subject \fBemail_subject\fR \- Email subject (default: "BanForge Alert")
.IP \(bu 2 .IP \(bu 2
\fBsmtp_host\fR \- SMTP server host \fBsmtp_host\fR \- SMTP server host \fI(required)\fR
.IP \(bu 2 .IP \(bu 2
\fBsmtp_port\fR \- SMTP server port \fBsmtp_port\fR \- SMTP server port \fI(required)\fR
.IP \(bu 2 .IP \(bu 2
\fBsmtp_user\fR \- SMTP username \fBsmtp_user\fR \- SMTP username \fI(required)\fR
.IP \(bu 2 .IP \(bu 2
\fBsmtp_password\fR \- SMTP password \fBsmtp_password\fR \- SMTP password \fI(required)\fR
.IP \(bu 2 .IP \(bu 2
\fBsmtp_tls\fR \- Enable TLS (true/false) \fBsmtp_tls\fR \- Enable TLS (true/false)
.IP \(bu 2
\fBbody\fR \- Email body text (supports variables)
.RE .RE
.PP .PP
\fBExample:\fR \fBExample:\fR
@@ -316,6 +339,49 @@ Send email notification when an IP is banned.
smtp_user = "banforge" smtp_user = "banforge"
smtp_password = "secret" smtp_password = "secret"
smtp_tls = true 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 .fi
.RE .RE
. .

View File

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

View File

@@ -5,6 +5,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/d3m0k1d/BanForge/internal/actions"
"github.com/d3m0k1d/BanForge/internal/blocker" "github.com/d3m0k1d/BanForge/internal/blocker"
"github.com/d3m0k1d/BanForge/internal/config" "github.com/d3m0k1d/BanForge/internal/config"
"github.com/d3m0k1d/BanForge/internal/logger" "github.com/d3m0k1d/BanForge/internal/logger"
@@ -124,6 +125,17 @@ func (j *Judge) Tribunal() {
metrics.IncError() metrics.IncError()
break 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( j.logger.Info(
"IP banned successfully", "IP banned successfully",
"ip", "ip",