feat: integration actions to judge logic and update docs for this
Some checks failed
build / build (push) Failing after 1m55s
Some checks failed
build / build (push) Failing after 1m55s
This commit is contained in:
15
README.md
15
README.md
@@ -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)
|
||||||
|
|||||||
120
docs/config.md
120
docs/config.md
@@ -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 |
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
.
|
.
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
Reference in New Issue
Block a user